Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 2/4] usb: musb: core: added helper function for parsing DT
From: Alexandre Bailon @ 2016-11-03 15:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478188752-22447-1-git-send-email-abailon@baylibre.com>

From: Petr Kulhavy <petr@barix.com>

This adds the function musb_get_mode() to get the DT property "dr_mode"

Signed-off-by: Petr Kulhavy <petr@barix.com>
Acked-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Tested-by: David Lechner <david@lechnology.com>
Reviewed-by: Kevin Hilman <khilman@baylibre.com>
---
 drivers/usb/musb/musb_core.c | 19 +++++++++++++++++++
 drivers/usb/musb/musb_core.h |  6 ++++++
 2 files changed, 25 insertions(+)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 27dadc0..bba07e7 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -100,6 +100,7 @@
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
 #include <linux/usb.h>
+#include <linux/usb/of.h>
 
 #include "musb_core.h"
 #include "musb_trace.h"
@@ -130,6 +131,24 @@ static inline struct musb *dev_to_musb(struct device *dev)
 	return dev_get_drvdata(dev);
 }
 
+enum musb_mode musb_get_mode(struct device *dev)
+{
+	enum usb_dr_mode mode;
+
+	mode = usb_get_dr_mode(dev);
+	switch (mode) {
+	case USB_DR_MODE_HOST:
+		return MUSB_HOST;
+	case USB_DR_MODE_PERIPHERAL:
+		return MUSB_PERIPHERAL;
+	case USB_DR_MODE_OTG:
+	case USB_DR_MODE_UNKNOWN:
+	default:
+		return MUSB_OTG;
+	}
+}
+EXPORT_SYMBOL_GPL(musb_get_mode);
+
 /*-------------------------------------------------------------------------*/
 
 #ifndef CONFIG_BLACKFIN
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 2cb88a49..76f00f6 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -617,4 +617,10 @@ static inline void musb_platform_post_root_reset_end(struct musb *musb)
 		musb->ops->post_root_reset_end(musb);
 }
 
+/*
+ * gets the "dr_mode" property from DT and converts it into musb_mode
+ * if the property is not found or not recognized returns MUSB_OTG
+ */
+extern enum musb_mode musb_get_mode(struct device *dev);
+
 #endif	/* __MUSB_CORE_H__ */
-- 
2.7.3

^ permalink raw reply related

* [PATCH v4 3/4] usb: musb: da8xx: Add DT support for the DA8xx driver
From: Alexandre Bailon @ 2016-11-03 15:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478188752-22447-1-git-send-email-abailon@baylibre.com>

From: Petr Kulhavy <petr@barix.com>

This adds DT support for TI DA8xx/OMAP-L1x/AM17xx/AM18xx MUSB driver

Signed-off-by: Petr Kulhavy <petr@barix.com>
Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
Tested-by: David Lechner <david@lechnology.com>
---
 drivers/usb/musb/da8xx.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 210b7e4..51ae3b6 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -6,6 +6,9 @@
  * Based on the DaVinci "glue layer" code.
  * Copyright (C) 2005-2006 by Texas Instruments
  *
+ * DT support
+ * Copyright (c) 2016 Petr Kulhavy <petr@barix.com>
+ *
  * This file is part of the Inventra Controller Driver for Linux.
  *
  * The Inventra Controller Driver for Linux is free software; you
@@ -433,6 +436,21 @@ static int da8xx_musb_exit(struct musb *musb)
 	return 0;
 }
 
+static inline u8 get_vbus_power(struct device *dev)
+{
+	struct regulator *vbus_supply;
+	int current_uA;
+
+	vbus_supply = regulator_get_optional(dev, "vbus");
+	if (IS_ERR(vbus_supply))
+		return 255;
+	current_uA = regulator_get_current_limit(vbus_supply);
+	regulator_put(vbus_supply);
+	if (current_uA <= 0 || current_uA > 510000)
+		return 255;
+	return current_uA / 1000 / 2;
+}
+
 static const struct musb_platform_ops da8xx_ops = {
 	.quirks		= MUSB_DMA_CPPI | MUSB_INDEXED_EP,
 	.init		= da8xx_musb_init,
@@ -458,6 +476,12 @@ static const struct platform_device_info da8xx_dev_info = {
 	.dma_mask	= DMA_BIT_MASK(32),
 };
 
+static const struct musb_hdrc_config da8xx_config = {
+	.ram_bits = 10,
+	.num_eps = 5,
+	.multipoint = 1,
+};
+
 static int da8xx_probe(struct platform_device *pdev)
 {
 	struct resource musb_resources[2];
@@ -465,6 +489,7 @@ static int da8xx_probe(struct platform_device *pdev)
 	struct da8xx_glue		*glue;
 	struct platform_device_info	pinfo;
 	struct clk			*clk;
+	struct device_node		*np = pdev->dev.of_node;
 	int				ret;
 
 	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
@@ -486,6 +511,16 @@ static int da8xx_probe(struct platform_device *pdev)
 	glue->dev			= &pdev->dev;
 	glue->clk			= clk;
 
+	if (IS_ENABLED(CONFIG_OF) && np) {
+		pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+		if (!pdata)
+			return -ENOMEM;
+
+		pdata->config	= &da8xx_config;
+		pdata->mode	= musb_get_mode(&pdev->dev);
+		pdata->power	= get_vbus_power(&pdev->dev);
+	}
+
 	pdata->platform_ops		= &da8xx_ops;
 
 	glue->usb_phy = usb_phy_generic_register();
@@ -536,11 +571,22 @@ static int da8xx_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id da8xx_id_table[] = {
+	{
+		.compatible = "ti,da830-musb",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, da8xx_id_table);
+#endif
+
 static struct platform_driver da8xx_driver = {
 	.probe		= da8xx_probe,
 	.remove		= da8xx_remove,
 	.driver		= {
 		.name	= "musb-da8xx",
+		.of_match_table = of_match_ptr(da8xx_id_table),
 	},
 };
 
-- 
2.7.3

^ permalink raw reply related

* [PATCH v4 4/4] ARM: dts: da850: Add the usb otg device node
From: Alexandre Bailon @ 2016-11-03 15:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478188752-22447-1-git-send-email-abailon@baylibre.com>

This adds the device tree node for the usb otg
controller present in the da850 family of SoC's.
This also enables the otg usb controller for the lcdk board.

Signed-off-by: Alexandre Bailon <abailon@baylibre.com>
---
 arch/arm/boot/dts/da850-lcdk.dts |  8 ++++++++
 arch/arm/boot/dts/da850.dtsi     | 15 +++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/arch/arm/boot/dts/da850-lcdk.dts b/arch/arm/boot/dts/da850-lcdk.dts
index 7b8ab21..9f5040c 100644
--- a/arch/arm/boot/dts/da850-lcdk.dts
+++ b/arch/arm/boot/dts/da850-lcdk.dts
@@ -158,6 +158,14 @@
 	rx-num-evt = <32>;
 };
 
+&usb_phy {
+	status = "okay";
+	};
+
+&usb0 {
+	status = "okay";
+};
+
 &aemif {
 	pinctrl-names = "default";
 	pinctrl-0 = <&nand_pins>;
diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index f79e1b9..322a31a 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -372,6 +372,21 @@
 					>;
 			status = "disabled";
 		};
+		usb_phy: usb-phy {
+			compatible = "ti,da830-usb-phy";
+			#phy-cells = <1>;
+			status = "disabled";
+		};
+		usb0: usb at 200000 {
+			compatible = "ti,da830-musb";
+			reg = <0x200000 0x10000>;
+			interrupts = <58>;
+			interrupt-names = "mc";
+			dr_mode = "otg";
+			phys = <&usb_phy 0>;
+			phy-names = "usb-phy";
+			status = "disabled";
+		};
 		gpio: gpio at 226000 {
 			compatible = "ti,dm6441-gpio";
 			gpio-controller;
-- 
2.7.3

^ permalink raw reply related

* [GIT PULL] iommu/arm-smmu: Fixes for 4.9
From: Will Deacon @ 2016-11-03 16:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161103153303.GA837@8bytes.org>

Hi Joerg,

On Thu, Nov 03, 2016 at 09:33:04AM -0600, Joerg Roedel wrote:
> On Fri, Oct 28, 2016 at 05:01:48PM +0100, Will Deacon wrote:
> >       iommu/arm-smmu: Don't inadvertently reject multiple SMMUv3s
> 
> Hmm, this patch is pretty ugly. Wouldn't it be better to have
> hardware-independent init-routine in the arm-smmu-v3 driver that checks
> DT whether there is an SMMU at all and if yes, sets the per-bus
> iommu-ops?

We're basically doing that already, since the bus_set_iommu call happens in
the probe routine, which won't run unless an SMMUv3 has been found in the
DT. The issue we're trying to avoid is failing the probe of a second SMMUv3
in the system, because the bus will already have the iommu ops set by the
first SMMUv3 that probed.

I suppose we could go and compare bus->iommu_ops with &arm_smmu_ops, but
given that we can't support different IOMMU types on a single bus, I don't
think we gain anything from that.

Will

^ permalink raw reply

* [PATCH v2 0/3] davinci: ohci: fix usb ohci device name
From: Axel Haslam @ 2016-11-03 16:03 UTC (permalink / raw)
  To: linux-arm-kernel

The usb ohci clock match is not working because the usb clock
is registered as "ohci" instead of "ohci.0"

But since there is only a single ohci instance, lets pass -1 to
the platform data id parameter and avoid the extra ".0" matching.

while we are fixing this, rename the driver from "ohci" to
"ohci-da8xx" which  is less generic and consistent with other
usb drivers.

changes form v1 -> v2
*Reword commit messages (David Lechner)

Because of the recently accepted patches on the ARM-davinci side,
This patch series is based on:
branch: /v4.10/soc of the linux-davinci tree.

It Depends on two accepted usb patches missing on that branch:
6c21caa USB: OHCI: make ohci-da8xx a separate driver (in next-usb)
6110c42 usb: ohci-da8xx: Remove code that references mach (in linux-next)

A branch with both patches applied + this series can be found here:
https://github.com/axelhaslamx/linux-axel/commits/ti-davinci-ohci-rename


Axel Haslam (3):
  ARM: davinci: da8xx: Fix ohci device name
  phy: da8xx-usb: rename the ohci device to ohci-da8xx
  usb: ohci-da8xx: rename driver to ohci-da8xx

 arch/arm/mach-davinci/da830.c     | 2 +-
 arch/arm/mach-davinci/da850.c     | 2 +-
 arch/arm/mach-davinci/da8xx-dt.c  | 2 +-
 arch/arm/mach-davinci/usb-da8xx.c | 4 ++--
 drivers/phy/phy-da8xx-usb.c       | 5 +++--
 drivers/usb/host/ohci-da8xx.c     | 2 +-
 6 files changed, 9 insertions(+), 8 deletions(-)

-- 
2.10.1

^ permalink raw reply

* [PATCH v2 1/3] ARM: davinci: da8xx: Fix ohci device name
From: Axel Haslam @ 2016-11-03 16:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161103160308.29588-1-ahaslam@baylibre.com>

While the clk lookup table is making reference to "ohci"
other subsystems (such as phy) are trying to match "ohci.0"

Since there is a single ohci instance, instead of changing
the clk name, change the dev id to -1, and add the "-da8xx"
postfix to match the driver name that will also be changed
in a subsequent patch.

Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
---
 arch/arm/mach-davinci/da830.c     | 2 +-
 arch/arm/mach-davinci/da850.c     | 2 +-
 arch/arm/mach-davinci/da8xx-dt.c  | 2 +-
 arch/arm/mach-davinci/usb-da8xx.c | 4 ++--
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index 41459bd..073c458 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -420,7 +420,7 @@ static struct clk_lookup da830_clks[] = {
 	CLK("davinci_mdio.0",   "fck",          &emac_clk),
 	CLK(NULL,		"gpio",		&gpio_clk),
 	CLK("i2c_davinci.2",	NULL,		&i2c1_clk),
-	CLK("ohci",		"usb11",	&usb11_clk),
+	CLK("ohci-da8xx",	"usb11",	&usb11_clk),
 	CLK(NULL,		"emif3",	&emif3_clk),
 	CLK(NULL,		"arm",		&arm_clk),
 	CLK(NULL,		"rmii",		&rmii_clk),
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 196e262..3961556 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -503,7 +503,7 @@ static struct clk_lookup da850_clks[] = {
 	CLK("da830-mmc.1",	NULL,		&mmcsd1_clk),
 	CLK("ti-aemif",		NULL,		&aemif_clk),
 	CLK(NULL,		"aemif",	&aemif_clk),
-	CLK("ohci",		"usb11",	&usb11_clk),
+	CLK("ohci-da8xx",	"usb11",	&usb11_clk),
 	CLK("musb-da8xx",	"usb20",	&usb20_clk),
 	CLK("spi_davinci.0",	NULL,		&spi0_clk),
 	CLK("spi_davinci.1",	NULL,		&spi1_clk),
diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c
index 92ae093..2afb067 100644
--- a/arch/arm/mach-davinci/da8xx-dt.c
+++ b/arch/arm/mach-davinci/da8xx-dt.c
@@ -39,7 +39,7 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("ti,da830-mcasp-audio", 0x01d00000, "davinci-mcasp.0", NULL),
 	OF_DEV_AUXDATA("ti,da850-aemif", 0x68000000, "ti-aemif", NULL),
 	OF_DEV_AUXDATA("ti,da850-tilcdc", 0x01e13000, "da8xx_lcdc.0", NULL),
-	OF_DEV_AUXDATA("ti,da830-ohci", 0x01e25000, "ohci", NULL),
+	OF_DEV_AUXDATA("ti,da830-ohci", 0x01e25000, "ohci-da8xx", NULL),
 	OF_DEV_AUXDATA("ti,da830-musb", 0x01e00000, "musb-da8xx", NULL),
 	OF_DEV_AUXDATA("ti,da830-usb-phy", 0x01c1417c, "da8xx-usb-phy", NULL),
 	{}
diff --git a/arch/arm/mach-davinci/usb-da8xx.c b/arch/arm/mach-davinci/usb-da8xx.c
index b010e5f..c6feecf 100644
--- a/arch/arm/mach-davinci/usb-da8xx.c
+++ b/arch/arm/mach-davinci/usb-da8xx.c
@@ -109,8 +109,8 @@ static struct resource da8xx_usb11_resources[] = {
 static u64 da8xx_usb11_dma_mask = DMA_BIT_MASK(32);
 
 static struct platform_device da8xx_usb11_device = {
-	.name		= "ohci",
-	.id		= 0,
+	.name		= "ohci-da8xx",
+	.id		= -1,
 	.dev = {
 		.dma_mask		= &da8xx_usb11_dma_mask,
 		.coherent_dma_mask	= DMA_BIT_MASK(32),
-- 
2.10.1

^ permalink raw reply related

* [PATCH v2 2/3] phy: da8xx-usb: rename the ohci device to ohci-da8xx
From: Axel Haslam @ 2016-11-03 16:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161103160308.29588-1-ahaslam@baylibre.com>

The ohci device name has changed in the board configuraion files,
hence, change the phy lookup table to match the new name.

Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
---
 drivers/phy/phy-da8xx-usb.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/phy-da8xx-usb.c b/drivers/phy/phy-da8xx-usb.c
index 32ae78c..c85fb0b 100644
--- a/drivers/phy/phy-da8xx-usb.c
+++ b/drivers/phy/phy-da8xx-usb.c
@@ -198,7 +198,8 @@ static int da8xx_usb_phy_probe(struct platform_device *pdev)
 	} else {
 		int ret;
 
-		ret = phy_create_lookup(d_phy->usb11_phy, "usb-phy", "ohci.0");
+		ret = phy_create_lookup(d_phy->usb11_phy, "usb-phy",
+					"ohci-da8xx");
 		if (ret)
 			dev_warn(dev, "Failed to create usb11 phy lookup\n");
 		ret = phy_create_lookup(d_phy->usb20_phy, "usb-phy",
@@ -216,7 +217,7 @@ static int da8xx_usb_phy_remove(struct platform_device *pdev)
 
 	if (!pdev->dev.of_node) {
 		phy_remove_lookup(d_phy->usb20_phy, "usb-phy", "musb-da8xx");
-		phy_remove_lookup(d_phy->usb11_phy, "usb-phy", "ohci.0");
+		phy_remove_lookup(d_phy->usb11_phy, "usb-phy", "ohci-da8xx");
 	}
 
 	return 0;
-- 
2.10.1

^ permalink raw reply related

* [PATCH v2 3/3] usb: ohci-da8xx: rename driver to ohci-da8xx
From: Axel Haslam @ 2016-11-03 16:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161103160308.29588-1-ahaslam@baylibre.com>

The davinci ohci driver name (currently "ohci") is too generic.
To be consistent with other usb dirvers, append the "-da8xx" postfix
to the name.

Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
---
 drivers/usb/host/ohci-da8xx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 30c4878..429d58b 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -27,7 +27,7 @@
 #include "ohci.h"
 
 #define DRIVER_DESC "DA8XX"
-#define DRV_NAME "ohci"
+#define DRV_NAME "ohci-da8xx"
 
 static struct hc_driver __read_mostly ohci_da8xx_hc_driver;
 
-- 
2.10.1

^ permalink raw reply related

* [GIT PULL] iommu/arm-smmu: Fixes for 4.9
From: Joerg Roedel @ 2016-11-03 16:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161103160006.GS22791@arm.com>

On Thu, Nov 03, 2016 at 04:00:06PM +0000, Will Deacon wrote:
> We're basically doing that already, since the bus_set_iommu call happens in
> the probe routine, which won't run unless an SMMUv3 has been found in the
> DT. The issue we're trying to avoid is failing the probe of a second SMMUv3
> in the system, because the bus will already have the iommu ops set by the
> first SMMUv3 that probed.
> 
> I suppose we could go and compare bus->iommu_ops with &arm_smmu_ops, but
> given that we can't support different IOMMU types on a single bus, I don't
> think we gain anything from that.

Can you instead check whether there is already another smmu probed and
skip the bus_set_iommu call then?


	Joerg

^ permalink raw reply

* [GIT PULL] iommu/arm-smmu: Fixes for 4.9
From: Robin Murphy @ 2016-11-03 16:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161103161407.GR3541@8bytes.org>

On 03/11/16 16:14, Joerg Roedel wrote:
> On Thu, Nov 03, 2016 at 04:00:06PM +0000, Will Deacon wrote:
>> We're basically doing that already, since the bus_set_iommu call happens in
>> the probe routine, which won't run unless an SMMUv3 has been found in the
>> DT. The issue we're trying to avoid is failing the probe of a second SMMUv3
>> in the system, because the bus will already have the iommu ops set by the
>> first SMMUv3 that probed.
>>
>> I suppose we could go and compare bus->iommu_ops with &arm_smmu_ops, but
>> given that we can't support different IOMMU types on a single bus, I don't
>> think we gain anything from that.
> 
> Can you instead check whether there is already another smmu probed and
> skip the bus_set_iommu call then?

But bus_set_iommu() is already checking whether another SMMU (in this
case) has probed, by virtue of bus->iommu_ops being non-NULL, and
returning without doing anything if so. What's the value of adding a
whole  bunch more code to effectively duplicate that in a less elegant
manner?

Robin.

> 
> 
> 	Joerg
> 

^ permalink raw reply

* [PATCH] ASoC: sun4i-i2s: Implement capture support
From: Maxime Ripard @ 2016-11-03 16:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161103153218.fibbz7y7pqwqyo7r@sirena.org.uk>

On Thu, Nov 03, 2016 at 09:32:18AM -0600, Mark Brown wrote:
> On Thu, Nov 03, 2016 at 11:20:48AM +0100, Maxime Ripard wrote:
> > The i2s driver was only implementing playback for now. Implement capture to
> > make sure that's not a limitation anymore.
> 
> This doesn't apply against current code, please check and resend.

Argh, yes, sorry.

I'll send a new version.

Maxime

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

^ permalink raw reply

* [PATCH v2] ASoC: sun4i-i2s: Implement capture support
From: Maxime Ripard @ 2016-11-03 16:27 UTC (permalink / raw)
  To: linux-arm-kernel

The i2s driver was only implementing playback for now. Implement capture to
make sure that's not a limitation anymore.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Changes from v1:
   - Rebased on top of asoc's topic/sunxi branch

 sound/soc/sunxi/sun4i-i2s.c | 52 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 49 insertions(+), 3 deletions(-)

diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
index 687a8f83dbe5..a7653114e895 100644
--- a/sound/soc/sunxi/sun4i-i2s.c
+++ b/sound/soc/sunxi/sun4i-i2s.c
@@ -93,6 +93,7 @@ struct sun4i_i2s {
 	struct clk	*mod_clk;
 	struct regmap	*regmap;
 
+	struct snd_dmaengine_dai_dma_data	capture_dma_data;
 	struct snd_dmaengine_dai_dma_data	playback_dma_data;
 };
 
@@ -341,6 +342,27 @@ static int sun4i_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 	return 0;
 }
 
+static void sun4i_i2s_start_capture(struct sun4i_i2s *i2s)
+{
+	/* Flush RX FIFO */
+	regmap_update_bits(i2s->regmap, SUN4I_I2S_FIFO_CTRL_REG,
+			   SUN4I_I2S_FIFO_CTRL_FLUSH_RX,
+			   SUN4I_I2S_FIFO_CTRL_FLUSH_RX);
+
+	/* Clear RX counter */
+	regmap_write(i2s->regmap, SUN4I_I2S_RX_CNT_REG, 0);
+
+	/* Enable RX Block */
+	regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
+			   SUN4I_I2S_CTRL_RX_EN,
+			   SUN4I_I2S_CTRL_RX_EN);
+
+	/* Enable RX DRQ */
+	regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG,
+			   SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN,
+			   SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN);
+}
+
 static void sun4i_i2s_start_playback(struct sun4i_i2s *i2s)
 {
 	/* Flush TX FIFO */
@@ -362,6 +384,18 @@ static void sun4i_i2s_start_playback(struct sun4i_i2s *i2s)
 			   SUN4I_I2S_DMA_INT_CTRL_TX_DRQ_EN);
 }
 
+static void sun4i_i2s_stop_capture(struct sun4i_i2s *i2s)
+{
+	/* Disable RX Block */
+	regmap_update_bits(i2s->regmap, SUN4I_I2S_CTRL_REG,
+			   SUN4I_I2S_CTRL_RX_EN,
+			   0);
+
+	/* Disable RX DRQ */
+	regmap_update_bits(i2s->regmap, SUN4I_I2S_DMA_INT_CTRL_REG,
+			   SUN4I_I2S_DMA_INT_CTRL_RX_DRQ_EN,
+			   0);
+}
 
 static void sun4i_i2s_stop_playback(struct sun4i_i2s *i2s)
 {
@@ -388,7 +422,7 @@ static int sun4i_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 			sun4i_i2s_start_playback(i2s);
 		else
-			return -EINVAL;
+			sun4i_i2s_start_capture(i2s);
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
@@ -397,7 +431,7 @@ static int sun4i_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 			sun4i_i2s_stop_playback(i2s);
 		else
-			return -EINVAL;
+			sun4i_i2s_stop_capture(i2s);
 		break;
 
 	default:
@@ -459,7 +493,9 @@ static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai)
 {
 	struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai);
 
-	snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, NULL);
+	snd_soc_dai_init_dma_data(dai,
+				  &i2s->playback_dma_data,
+				  &i2s->capture_dma_data);
 
 	snd_soc_dai_set_drvdata(dai, i2s);
 
@@ -468,6 +504,13 @@ static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai)
 
 static struct snd_soc_dai_driver sun4i_i2s_dai = {
 	.probe = sun4i_i2s_dai_probe,
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_192000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	},
 	.playback = {
 		.stream_name = "Playback",
 		.channels_min = 2,
@@ -630,6 +673,9 @@ static int sun4i_i2s_probe(struct platform_device *pdev)
 	i2s->playback_dma_data.addr = res->start + SUN4I_I2S_FIFO_TX_REG;
 	i2s->playback_dma_data.maxburst = 4;
 
+	i2s->capture_dma_data.addr = res->start + SUN4I_I2S_FIFO_RX_REG;
+	i2s->capture_dma_data.maxburst = 4;
+
 	pm_runtime_enable(&pdev->dev);
 	if (!pm_runtime_enabled(&pdev->dev)) {
 		ret = sun4i_i2s_runtime_resume(&pdev->dev);
-- 
2.10.1

^ permalink raw reply related

* [GIT PULL] iommu/arm-smmu: Fixes for 4.9
From: Joerg Roedel @ 2016-11-03 16:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <0dbf2665-4292-d49a-b9e7-688bcdf29c6e@arm.com>

On Thu, Nov 03, 2016 at 04:22:04PM +0000, Robin Murphy wrote:
> But bus_set_iommu() is already checking whether another SMMU (in this
> case) has probed, by virtue of bus->iommu_ops being non-NULL, and
> returning without doing anything if so. What's the value of adding a
> whole  bunch more code to effectively duplicate that in a less elegant
> manner?

No, bus_set_iommu() checks whether there is _any_ other IOMMU already
registered. This doesn't need to be an smmu. So I think the return value
of bus_set_iommu shouldn't be generally ignored.


	Joerg

^ permalink raw reply

* [PATCH v2 6/6] ARM: dts: stm32f429: Add QSPI clock
From: Alexandre Torgue @ 2016-11-03 16:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476436699-21879-7-git-send-email-gabriel.fernandez@st.com>

Hi Gabriel,

On 10/14/2016 11:18 AM, gabriel.fernandez at st.com wrote:
> From: Gabriel Fernandez <gabriel.fernandez@st.com>
>
> This patch adds the QSPI clock for stm32f469 discovery board.
>
> Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
> ---
>  arch/arm/boot/dts/stm32f469-disco.dts | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/arch/arm/boot/dts/stm32f469-disco.dts b/arch/arm/boot/dts/stm32f469-disco.dts
> index e911af8..4052023 100644
> --- a/arch/arm/boot/dts/stm32f469-disco.dts
> +++ b/arch/arm/boot/dts/stm32f469-disco.dts
> @@ -66,6 +66,10 @@
>  	};
>  };
>
> +&rcc {
> +	compatible = "st,stm32f469-rcc", "st,stm32-rcc";
> +};
> +

With this patch, stm32f469-disco doesn't boot if clk drivers patch are 
not applied.
Can you please send a new version to keep compatibility with older clk 
driver.

&rcc {
 > +	compatible = "st,stm32f469-rcc", "st,stm32-rcc";
-> compatible = "st,stm32f469-rcc", "st,stm32f42xx-rcc", "st,stm32-rcc";
 > +};
 > +
I will take it in next pull request round.


Regards
Alex


>  &clk_hse {
>  	clock-frequency = <8000000>;
>  };
>

^ permalink raw reply

* [PATCH v5 5/7] net: ethernet: bgmac: device tree phy enablement
From: Jon Mason @ 2016-11-03 16:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <35b16640-8600-8c48-2f04-886dc925229d@milecki.pl>

On Thu, Nov 03, 2016 at 09:31:21AM +0100, Rafal Milecki wrote:
> On 11/02/2016 06:08 PM, Jon Mason wrote:
> >Change the bgmac driver to allow for phy's defined by the device tree
> 
> This is a late review, I know, sorry... :(
> 
> 
> >+static int bcma_phy_direct_connect(struct bgmac *bgmac)
> >+{
> >+	struct fixed_phy_status fphy_status = {
> >+		.link = 1,
> >+		.speed = SPEED_1000,
> >+		.duplex = DUPLEX_FULL,
> >+	};
> >+	struct phy_device *phy_dev;
> >+	int err;
> >+
> >+	phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
> >+	if (!phy_dev || IS_ERR(phy_dev)) {
> >+		dev_err(bgmac->dev, "Failed to register fixed PHY device\n");
> >+		return -ENODEV;
> >+	}
> >+
> >+	err = phy_connect_direct(bgmac->net_dev, phy_dev, bgmac_adjust_link,
> >+				 PHY_INTERFACE_MODE_MII);
> >+	if (err) {
> >+		dev_err(bgmac->dev, "Connecting PHY failed\n");
> >+		return err;
> >+	}
> >+
> >+	return err;
> >+}
> 
> This bcma specific function looks exactly the same as...
> 
> 
> >+static int platform_phy_direct_connect(struct bgmac *bgmac)
> >+{
> >+	struct fixed_phy_status fphy_status = {
> >+		.link = 1,
> >+		.speed = SPEED_1000,
> >+		.duplex = DUPLEX_FULL,
> >+	};
> >+	struct phy_device *phy_dev;
> >+	int err;
> >+
> >+	phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
> >+	if (!phy_dev || IS_ERR(phy_dev)) {
> >+		dev_err(bgmac->dev, "Failed to register fixed PHY device\n");
> >+		return -ENODEV;
> >+	}
> >+
> >+	err = phy_connect_direct(bgmac->net_dev, phy_dev, bgmac_adjust_link,
> >+				 PHY_INTERFACE_MODE_MII);
> >+	if (err) {
> >+		dev_err(bgmac->dev, "Connecting PHY failed\n");
> >+		return err;
> >+	}
> >+
> >+	return err;
> >+}
> 
> This one.
> 
> Would that make sense to keep bgmac_phy_connect_direct and just use it in
> bcma/platform code?

Yes, I was having the same internal debate.  I hate the duplication of
code, but I really wanted to keep the PHY logic out of the bgmac.c
file.  Do you think it is acceptable to make this an inline function
in bgmac.h?

Thanks,
Jon

^ permalink raw reply

* [PATCH v2 0/3] davinci: ohci: fix usb ohci device name
From: David Lechner @ 2016-11-03 16:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161103160308.29588-1-ahaslam@baylibre.com>

On 11/03/2016 11:03 AM, Axel Haslam wrote:
> The usb ohci clock match is not working because the usb clock
> is registered as "ohci" instead of "ohci.0"
>
> But since there is only a single ohci instance, lets pass -1 to
> the platform data id parameter and avoid the extra ".0" matching.
>
> while we are fixing this, rename the driver from "ohci" to
> "ohci-da8xx" which  is less generic and consistent with other
> usb drivers.
>
> changes form v1 -> v2
> *Reword commit messages (David Lechner)
>
> Because of the recently accepted patches on the ARM-davinci side,
> This patch series is based on:
> branch: /v4.10/soc of the linux-davinci tree.
>
> It Depends on two accepted usb patches missing on that branch:
> 6c21caa USB: OHCI: make ohci-da8xx a separate driver (in next-usb)
> 6110c42 usb: ohci-da8xx: Remove code that references mach (in linux-next)
>
> A branch with both patches applied + this series can be found here:
> https://github.com/axelhaslamx/linux-axel/commits/ti-davinci-ohci-rename
>
>
> Axel Haslam (3):
>   ARM: davinci: da8xx: Fix ohci device name
>   phy: da8xx-usb: rename the ohci device to ohci-da8xx
>   usb: ohci-da8xx: rename driver to ohci-da8xx
>
>  arch/arm/mach-davinci/da830.c     | 2 +-
>  arch/arm/mach-davinci/da850.c     | 2 +-
>  arch/arm/mach-davinci/da8xx-dt.c  | 2 +-
>  arch/arm/mach-davinci/usb-da8xx.c | 4 ++--
>  drivers/phy/phy-da8xx-usb.c       | 5 +++--
>  drivers/usb/host/ohci-da8xx.c     | 2 +-
>  6 files changed, 9 insertions(+), 8 deletions(-)
>

Thanks for making the changes. The commit messages make better sense to 
me now. :-)

^ permalink raw reply

* [PATCH 2/3] phy: da8xx-usb: rename the ohci device to ohci-da8xx
From: Kishon Vijay Abraham I @ 2016-11-03 16:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161102124435.31777-3-ahaslam@baylibre.com>



On Wednesday 02 November 2016 06:14 PM, Axel Haslam wrote:
> There is only one ohci on the da8xx series of chips,
> so remove the ".0" when creating the phy. Also add
> the "-da8xx" postfix to be consistent across davinci
> usb drivers.
> 
> Signed-off-by: Axel Haslam <ahaslam@baylibre.com>

Acked-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---
>  drivers/phy/phy-da8xx-usb.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/phy/phy-da8xx-usb.c b/drivers/phy/phy-da8xx-usb.c
> index 32ae78c..c85fb0b 100644
> --- a/drivers/phy/phy-da8xx-usb.c
> +++ b/drivers/phy/phy-da8xx-usb.c
> @@ -198,7 +198,8 @@ static int da8xx_usb_phy_probe(struct platform_device *pdev)
>  	} else {
>  		int ret;
>  
> -		ret = phy_create_lookup(d_phy->usb11_phy, "usb-phy", "ohci.0");
> +		ret = phy_create_lookup(d_phy->usb11_phy, "usb-phy",
> +					"ohci-da8xx");
>  		if (ret)
>  			dev_warn(dev, "Failed to create usb11 phy lookup\n");
>  		ret = phy_create_lookup(d_phy->usb20_phy, "usb-phy",
> @@ -216,7 +217,7 @@ static int da8xx_usb_phy_remove(struct platform_device *pdev)
>  
>  	if (!pdev->dev.of_node) {
>  		phy_remove_lookup(d_phy->usb20_phy, "usb-phy", "musb-da8xx");
> -		phy_remove_lookup(d_phy->usb11_phy, "usb-phy", "ohci.0");
> +		phy_remove_lookup(d_phy->usb11_phy, "usb-phy", "ohci-da8xx");
>  	}
>  
>  	return 0;
> 

^ permalink raw reply

* [GIT PULL] iommu/arm-smmu: Fixes for 4.9
From: Robin Murphy @ 2016-11-03 16:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161103162943.GS3541@8bytes.org>

On 03/11/16 16:29, Joerg Roedel wrote:
> On Thu, Nov 03, 2016 at 04:22:04PM +0000, Robin Murphy wrote:
>> But bus_set_iommu() is already checking whether another SMMU (in this
>> case) has probed, by virtue of bus->iommu_ops being non-NULL, and
>> returning without doing anything if so. What's the value of adding a
>> whole  bunch more code to effectively duplicate that in a less elegant
>> manner?
> 
> No, bus_set_iommu() checks whether there is _any_ other IOMMU already
> registered. This doesn't need to be an smmu. So I think the return value
> of bus_set_iommu shouldn't be generally ignored.

But if it is someone else's ops, then all that means is that the SMMU
driver isn't going to get notified about devices on that bus, or get
called with them later, so I still don't see where the problem is. If
there are devices on that bus which the SMMU *is* supposed to be
managing, then that system can't be supported with the current API anyway.

Robin.

^ permalink raw reply

* [PATCH] ARM: DTS: r8a7794: alt: Fix PCF names for DU
From: Sergei Shtylyov @ 2016-11-03 16:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478180574-15464-1-git-send-email-jacopo@jmondi.org>

Hello.

On 11/03/2016 04:42 PM, Jacopo Mondi wrote:

> Update the PCF pin groups and function names of DU interface for

    PFC maybe?

> r8a7794 ALT board.
>
> The currently specified pin groups and function names prevented PCF and
> DU interfaces from being correctly configured:
>
> sh-pfc e6060000.pin-controller: function 'du' not supported
> sh-pfc e6060000.pin-controller: invalid function du in map table
> sh-pfc e6060000.pin-controller: function 'du' not supported
> sh-pfc e6060000.pin-controller: invalid function du in map table
> sh-pfc e6060000.pin-controller: function 'du' not supported
> sh-pfc e6060000.pin-controller: invalid function du in map table
> sh-pfc e6060000.pin-controller: function 'du' not supported
> sh-pfc e6060000.pin-controller: invalid function du in map table
> rcar-du: probe of feb00000.display failed with error -22
>
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
>
> Patch applied against Simon Horman's renesas/master branch.
> The PCF pin groups and function renaming was introduced by commit 56ed4bb9 and
> DTS for ALT board has never been update accordingly.

    We didn't care about Alt at the time, the patch was done in the interests 
of the SILK board. I didn't realize the DU pin groups were used for Alt before 
the actual support was added for them. Thank you for finally fixing this!

> Tested displaying frames on VGA interface: the rcar-du driver loads correctly.

MBR, Sergei

^ permalink raw reply

* [PATCHv2] PCI: QDF2432 32 bit config space accessors
From: Sinan Kaya @ 2016-11-03 16:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161103140058.GA31142@bhelgaas-glaptop.roam.corp.google.com>


On 11/3/2016 10:00 AM, Bjorn Helgaas wrote:
> On Wed, Nov 02, 2016 at 12:36:16PM -0400, Sinan Kaya wrote:
>> Hi Bjorn,
>>
>> On 11/2/2016 12:08 PM, Bjorn Helgaas wrote:
>>> On Tue, Nov 01, 2016 at 07:06:31AM -0600, cov at codeaurora.org wrote:
>>>> Hi Bjorn,
>>>>
>>>> On 2016-10-31 15:48, Bjorn Helgaas wrote:
>>>>> On Wed, Sep 21, 2016 at 06:38:05PM -0400, Christopher Covington wrote:
>>>>>> The Qualcomm Technologies QDF2432 SoC does not support accesses
>>>>>> smaller
>>>>>> than 32 bits to the PCI configuration space. Register the appropriate
>>>>>> quirk.
>>>>>>
>>>>>> Signed-off-by: Christopher Covington <cov@codeaurora.org>
>>>>>
>>>>> Hi Christopher,
>>>>>
>>>>> Can you rebase this against v4.9-rc1?  It no longer applies to my tree.
>>>>
>>>> I apologize for not being clearer. This patch depends on:
>>>>
>>>> PCI/ACPI: Extend pci_mcfg_lookup() responsibilities
>>>> PCI/ACPI: Check platform-specific ECAM quirks
>>>>
>>>> These patches from Tomasz Nowicki were previously in your pci/ecam-v6
>>>> branch, but that seems to have come and gone. How would you like to
>>>> proceed?
>>>
>>> Oh yes, that's right, I forgot that connection.  I'm afraid I kind of
>>> dropped the ball on that thread, so I went back and read through it
>>> again.
>>>
>>> I *think* the current state is:
>>>
>>>   - I'm OK with the first two patches that add the quirk
>>>     infrastructure.
>>>
>>>   - My issue with the last three patches that add ThunderX quirks is
>>>     that there's no generic description of the ECAM address space.
>>>
>>> So if I understand correctly, your Qualcomm patch depends only on the
>>> first two patches.
>>>
>>> Then the question is how the Qualcomm ECAM address space is described.
>>> Your quirk overrides the default pci_generic_ecam_ops with the
>>> &pci_32b_ops, but it doesn't touch the address space part, so I assume
>>> the bus ranges and corresponding address space in your MCFG is
>>> correct.  So far, so good.
>>
>> Qualcomm ECAM space includes both the root port and the endpoint address
>> space with a single contiguous 256 MB address space described in MCFG table.
>> There is no need to describe additional resources like PNP0C02.
> 
> This is the crucial point I have failed to communicate clearly: the
> PNP0C02 resource is *always* required, even if the MCFG is correct.
> 

Interesting...

It looks like there is a lot of lessons learnt here from history.

I think this requirement is only true if your system DDR space and PCIe
space overlaps in the memory map. I understand that Intel systems allow
sharing of these two memory ranges. An OS could potentially reclaim this
address range.

If there is no overlap and PCI is not enabled, there can't be any SW entity
to reclaim this space. 

Did I miss something?

> The reason is that MCFG is a PCI-specific table, and it should be
> possible to boot a kernel with no PCI support.  That kernel will not
> look at the MCFG.  The PCI hardware will still be present and will
> still consume the ECAM space, so the OS must be able to discover that
> the ECAM space is not available for other devices.
> 
> The usual way to for the OS to discover that would be via the _CRS of
> a PNP0A03 or PNP0A08 host bridge device.  _CRS is what I mean by a
> "generic" way to describe this address space, because the ACPI core
> can interpret _CRS for all ACPI devices, even if the kernel doesn't
> contain drivers for all of those devices.
> 
> It turns out that we can't use the _CRS of host bridges because of the
> Producer/Consumer bit screwup [1].  So the fallback is to include the
> ECAM space in the _CRS of a PNP0C02 device.  This is what the PCI
> Firmware spec r3.0, Table 4-2, footnote 2 is talking about.
> 
> Bjorn
> 
> [1] The original ACPI spec intent was that Consumer resources would be
> space like ECAM that is consumed directly by the bridge, and Producer
> resources would be the windows forwarded down to PCI.  But BIOSes
> didn't use the Producer/Consumer bit consistently, so we have to
> assume that all resources in host bridge _CRS are windows, which
> leaves us no way to describe the Consumer resources.
> --
> 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
> 


-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCHv2] PCI: QDF2432 32 bit config space accessors
From: Sinan Kaya @ 2016-11-03 17:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <aa8bc916-9363-2de7-2997-4ce470562b2c@codeaurora.org>

On 11/3/2016 12:58 PM, Sinan Kaya wrote:
>> > This is the crucial point I have failed to communicate clearly: the
>> > PNP0C02 resource is *always* required, even if the MCFG is correct.
>> > 
> Interesting...
> 
> It looks like there is a lot of lessons learnt here from history.
> 
> I think this requirement is only true if your system DDR space and PCIe
> space overlaps in the memory map. I understand that Intel systems allow
> sharing of these two memory ranges. An OS could potentially reclaim this
> address range.
> 
> If there is no overlap and PCI is not enabled, there can't be any SW entity
> to reclaim this space. 
> 
> Did I miss something?
> 

For protection, it makes sense to reserve this range. I'm trying to understand
who would claim this range.

-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH v2 1/2] phy: rockchip-inno-usb2: support otg-port for rk3399
From: Kishon Vijay Abraham I @ 2016-11-03 17:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478138774-3254-2-git-send-email-wulf@rock-chips.com>



On Thursday 03 November 2016 07:36 AM, William Wu wrote:
> The rk3399 SoC USB2 PHY is comprised of one Host port and
> one OTG port. And OTG port is for USB2.0 part of USB3.0 OTG
> controller, as a part to construct a fully feature Type-C
> subsystem.
> 
> With this patch, we can support OTG port with the following
> functions:
> - Support BC1.2 charger detect, and use extcon notifier to
>   send USB charger types to power driver.
> - Support PHY suspend for power management.
> - Support OTG Host only mode.
> 
> Also, correct 480MHz output clock stable time. We found that
> the system crashed due to 480MHz output clock of USB2 PHY was
> unstable after clock had been enabled by gpu module.

Can you split the clock fix into a separate patch?

Thanks
Kishon
> 
> Theoretically, 1 millisecond is a critical value for 480 output
> clock stable time, so we try changing the delay time to 1.2
> millisecond to avoid this issue.
> 
> Signed-off-by: William Wu <wulf@rock-chips.com>
> ---
> Changes in v2:
> - remove wakelock
> 
>  drivers/phy/phy-rockchip-inno-usb2.c | 593 +++++++++++++++++++++++++++++++++--
>  1 file changed, 562 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/phy/phy-rockchip-inno-usb2.c b/drivers/phy/phy-rockchip-inno-usb2.c
> index ac20310..8f2d2b6 100644
> --- a/drivers/phy/phy-rockchip-inno-usb2.c
> +++ b/drivers/phy/phy-rockchip-inno-usb2.c
> @@ -17,6 +17,7 @@
>  #include <linux/clk.h>
>  #include <linux/clk-provider.h>
>  #include <linux/delay.h>
> +#include <linux/extcon.h>
>  #include <linux/interrupt.h>
>  #include <linux/io.h>
>  #include <linux/gpio/consumer.h>
> @@ -30,11 +31,15 @@
>  #include <linux/of_platform.h>
>  #include <linux/phy/phy.h>
>  #include <linux/platform_device.h>
> +#include <linux/power_supply.h>
>  #include <linux/regmap.h>
>  #include <linux/mfd/syscon.h>
> +#include <linux/usb/of.h>
> +#include <linux/usb/otg.h>
>  
>  #define BIT_WRITEABLE_SHIFT	16
> -#define SCHEDULE_DELAY	(60 * HZ)
> +#define SCHEDULE_DELAY		(60 * HZ)
> +#define OTG_SCHEDULE_DELAY	(2 * HZ)
>  
>  enum rockchip_usb2phy_port_id {
>  	USB2PHY_PORT_OTG,
> @@ -49,6 +54,37 @@ enum rockchip_usb2phy_host_state {
>  	PHY_STATE_FS_LS_ONLINE	= 4,
>  };
>  
> +/**
> + * Different states involved in USB charger detection.
> + * USB_CHG_STATE_UNDEFINED	USB charger is not connected or detection
> + *				process is not yet started.
> + * USB_CHG_STATE_WAIT_FOR_DCD	Waiting for Data pins contact.
> + * USB_CHG_STATE_DCD_DONE	Data pin contact is detected.
> + * USB_CHG_STATE_PRIMARY_DONE	Primary detection is completed (Detects
> + *				between SDP and DCP/CDP).
> + * USB_CHG_STATE_SECONDARY_DONE	Secondary detection is completed (Detects
> + *				between DCP and CDP).
> + * USB_CHG_STATE_DETECTED	USB charger type is determined.
> + */
> +enum usb_chg_state {
> +	USB_CHG_STATE_UNDEFINED = 0,
> +	USB_CHG_STATE_WAIT_FOR_DCD,
> +	USB_CHG_STATE_DCD_DONE,
> +	USB_CHG_STATE_PRIMARY_DONE,
> +	USB_CHG_STATE_SECONDARY_DONE,
> +	USB_CHG_STATE_DETECTED,
> +};
> +
> +static const unsigned int rockchip_usb2phy_extcon_cable[] = {
> +	EXTCON_USB,
> +	EXTCON_USB_HOST,
> +	EXTCON_CHG_USB_SDP,
> +	EXTCON_CHG_USB_CDP,
> +	EXTCON_CHG_USB_DCP,
> +	EXTCON_CHG_USB_SLOW,
> +	EXTCON_NONE,
> +};
> +
>  struct usb2phy_reg {
>  	unsigned int	offset;
>  	unsigned int	bitend;
> @@ -58,19 +94,55 @@ struct usb2phy_reg {
>  };
>  
>  /**
> + * struct rockchip_chg_det_reg: usb charger detect registers
> + * @cp_det: charging port detected successfully.
> + * @dcp_det: dedicated charging port detected successfully.
> + * @dp_det: assert data pin connect successfully.
> + * @idm_sink_en: open dm sink curren.
> + * @idp_sink_en: open dp sink current.
> + * @idp_src_en: open dm source current.
> + * @rdm_pdwn_en: open dm pull down resistor.
> + * @vdm_src_en: open dm voltage source.
> + * @vdp_src_en: open dp voltage source.
> + * @opmode: utmi operational mode.
> + */
> +struct rockchip_chg_det_reg {
> +	struct usb2phy_reg	cp_det;
> +	struct usb2phy_reg	dcp_det;
> +	struct usb2phy_reg	dp_det;
> +	struct usb2phy_reg	idm_sink_en;
> +	struct usb2phy_reg	idp_sink_en;
> +	struct usb2phy_reg	idp_src_en;
> +	struct usb2phy_reg	rdm_pdwn_en;
> +	struct usb2phy_reg	vdm_src_en;
> +	struct usb2phy_reg	vdp_src_en;
> +	struct usb2phy_reg	opmode;
> +};
> +
> +/**
>   * struct rockchip_usb2phy_port_cfg: usb-phy port configuration.
>   * @phy_sus: phy suspend register.
> + * @bvalid_det_en: vbus valid rise detection enable register.
> + * @bvalid_det_st: vbus valid rise detection status register.
> + * @bvalid_det_clr: vbus valid rise detection clear register.
>   * @ls_det_en: linestate detection enable register.
>   * @ls_det_st: linestate detection state register.
>   * @ls_det_clr: linestate detection clear register.
> + * @utmi_avalid: utmi vbus avalid status register.
> + * @utmi_bvalid: utmi vbus bvalid status register.
>   * @utmi_ls: utmi linestate state register.
>   * @utmi_hstdet: utmi host disconnect register.
>   */
>  struct rockchip_usb2phy_port_cfg {
>  	struct usb2phy_reg	phy_sus;
> +	struct usb2phy_reg	bvalid_det_en;
> +	struct usb2phy_reg	bvalid_det_st;
> +	struct usb2phy_reg	bvalid_det_clr;
>  	struct usb2phy_reg	ls_det_en;
>  	struct usb2phy_reg	ls_det_st;
>  	struct usb2phy_reg	ls_det_clr;
> +	struct usb2phy_reg	utmi_avalid;
> +	struct usb2phy_reg	utmi_bvalid;
>  	struct usb2phy_reg	utmi_ls;
>  	struct usb2phy_reg	utmi_hstdet;
>  };
> @@ -80,31 +152,51 @@ struct rockchip_usb2phy_port_cfg {
>   * @reg: the address offset of grf for usb-phy config.
>   * @num_ports: specify how many ports that the phy has.
>   * @clkout_ctl: keep on/turn off output clk of phy.
> + * @chg_det: charger detection registers.
>   */
>  struct rockchip_usb2phy_cfg {
>  	unsigned int	reg;
>  	unsigned int	num_ports;
>  	struct usb2phy_reg	clkout_ctl;
>  	const struct rockchip_usb2phy_port_cfg	port_cfgs[USB2PHY_NUM_PORTS];
> +	const struct rockchip_chg_det_reg	chg_det;
>  };
>  
>  /**
>   * struct rockchip_usb2phy_port: usb-phy port data.
>   * @port_id: flag for otg port or host port.
>   * @suspended: phy suspended flag.
> + * @utmi_avalid: utmi avalid status usage flag.
> + *	true	- use avalid to get vbus status
> + *	flase	- use bvalid to get vbus status
> + * @vbus_attached: otg device vbus status.
> + * @bvalid_irq: IRQ number assigned for vbus valid rise detection.
>   * @ls_irq: IRQ number assigned for linestate detection.
>   * @mutex: for register updating in sm_work.
> - * @sm_work: OTG state machine work.
> + * @chg_work: charge detect work.
> + * @otg_sm_work: OTG state machine work.
> + * @sm_work: HOST state machine work.
>   * @phy_cfg: port register configuration, assigned by driver data.
> + * @event_nb: hold event notification callback.
> + * @state: define OTG enumeration states before device reset.
> + * @mode: the dr_mode of the controller.
>   */
>  struct rockchip_usb2phy_port {
>  	struct phy	*phy;
>  	unsigned int	port_id;
>  	bool		suspended;
> +	bool		utmi_avalid;
> +	bool		vbus_attached;
> +	int		bvalid_irq;
>  	int		ls_irq;
>  	struct mutex	mutex;
> +	struct		delayed_work chg_work;
> +	struct		delayed_work otg_sm_work;
>  	struct		delayed_work sm_work;
>  	const struct	rockchip_usb2phy_port_cfg *port_cfg;
> +	struct notifier_block	event_nb;
> +	enum usb_otg_state	state;
> +	enum usb_dr_mode	mode;
>  };
>  
>  /**
> @@ -113,6 +205,11 @@ struct rockchip_usb2phy_port {
>   * @clk: clock struct of phy input clk.
>   * @clk480m: clock struct of phy output clk.
>   * @clk_hw: clock struct of phy output clk management.
> + * @chg_state: states involved in USB charger detection.
> + * @chg_type: USB charger types.
> + * @dcd_retries: The retry count used to track Data contact
> + *		 detection process.
> + * @edev: extcon device for notification registration
>   * @phy_cfg: phy register configuration, assigned by driver data.
>   * @ports: phy port instance.
>   */
> @@ -122,6 +219,10 @@ struct rockchip_usb2phy {
>  	struct clk	*clk;
>  	struct clk	*clk480m;
>  	struct clk_hw	clk480m_hw;
> +	enum usb_chg_state	chg_state;
> +	enum power_supply_type	chg_type;
> +	u8			dcd_retries;
> +	struct extcon_dev	*edev;
>  	const struct rockchip_usb2phy_cfg	*phy_cfg;
>  	struct rockchip_usb2phy_port	ports[USB2PHY_NUM_PORTS];
>  };
> @@ -166,7 +267,7 @@ static int rockchip_usb2phy_clk480m_enable(struct clk_hw *hw)
>  			return ret;
>  
>  		/* waitting for the clk become stable */
> -		mdelay(1);
> +		udelay(1200);
>  	}
>  
>  	return 0;
> @@ -263,33 +364,84 @@ rockchip_usb2phy_clk480m_register(struct rockchip_usb2phy *rphy)
>  	return ret;
>  }
>  
> -static int rockchip_usb2phy_init(struct phy *phy)
> +static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy)
>  {
> -	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
> -	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
>  	int ret;
> +	struct device_node *node = rphy->dev->of_node;
> +	struct extcon_dev *edev;
> +
> +	if (of_property_read_bool(node, "extcon")) {
> +		edev = extcon_get_edev_by_phandle(rphy->dev, 0);
> +		if (IS_ERR(edev)) {
> +			if (PTR_ERR(edev) != -EPROBE_DEFER)
> +				dev_err(rphy->dev, "Invalid or missing extcon\n");
> +			return PTR_ERR(edev);
> +		}
> +	} else {
> +		/* Initialize extcon device */
> +		edev = devm_extcon_dev_allocate(rphy->dev,
> +						rockchip_usb2phy_extcon_cable);
>  
> -	if (rport->port_id == USB2PHY_PORT_HOST) {
> -		/* clear linestate and enable linestate detect irq */
> -		mutex_lock(&rport->mutex);
> +		if (IS_ERR(edev))
> +			return -ENOMEM;
>  
> -		ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
> +		ret = devm_extcon_dev_register(rphy->dev, edev);
>  		if (ret) {
> -			mutex_unlock(&rport->mutex);
> +			dev_err(rphy->dev, "failed to register extcon device\n");
>  			return ret;
>  		}
> +	}
>  
> -		ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true);
> -		if (ret) {
> -			mutex_unlock(&rport->mutex);
> -			return ret;
> +	rphy->edev = edev;
> +
> +	return 0;
> +}
> +
> +static int rockchip_usb2phy_init(struct phy *phy)
> +{
> +	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
> +	struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
> +	int ret = 0;
> +
> +	mutex_lock(&rport->mutex);
> +
> +	if (rport->port_id == USB2PHY_PORT_OTG) {
> +		if (rport->mode != USB_DR_MODE_HOST) {
> +			/* clear bvalid status and enable bvalid detect irq */
> +			ret = property_enable(rphy,
> +					      &rport->port_cfg->bvalid_det_clr,
> +					      true);
> +			if (ret)
> +				goto out;
> +
> +			ret = property_enable(rphy,
> +					      &rport->port_cfg->bvalid_det_en,
> +					      true);
> +			if (ret)
> +				goto out;
> +
> +			schedule_delayed_work(&rport->otg_sm_work,
> +					      OTG_SCHEDULE_DELAY);
> +		} else {
> +			/* If OTG works in host only mode, do nothing. */
> +			dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode);
>  		}
> +	} else if (rport->port_id == USB2PHY_PORT_HOST) {
> +		/* clear linestate and enable linestate detect irq */
> +		ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
> +		if (ret)
> +			goto out;
> +
> +		ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true);
> +		if (ret)
> +			goto out;
>  
> -		mutex_unlock(&rport->mutex);
>  		schedule_delayed_work(&rport->sm_work, SCHEDULE_DELAY);
>  	}
>  
> -	return 0;
> +out:
> +	mutex_unlock(&rport->mutex);
> +	return ret;
>  }
>  
>  static int rockchip_usb2phy_power_on(struct phy *phy)
> @@ -340,7 +492,11 @@ static int rockchip_usb2phy_exit(struct phy *phy)
>  {
>  	struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
>  
> -	if (rport->port_id == USB2PHY_PORT_HOST)
> +	if (rport->port_id == USB2PHY_PORT_OTG &&
> +	    rport->mode != USB_DR_MODE_HOST) {
> +		cancel_delayed_work_sync(&rport->otg_sm_work);
> +		cancel_delayed_work_sync(&rport->chg_work);
> +	} else if (rport->port_id == USB2PHY_PORT_HOST)
>  		cancel_delayed_work_sync(&rport->sm_work);
>  
>  	return 0;
> @@ -354,6 +510,249 @@ static const struct phy_ops rockchip_usb2phy_ops = {
>  	.owner		= THIS_MODULE,
>  };
>  
> +static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
> +{
> +	struct rockchip_usb2phy_port *rport =
> +		container_of(work, struct rockchip_usb2phy_port,
> +			     otg_sm_work.work);
> +	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
> +	static unsigned int cable;
> +	unsigned long delay;
> +	bool vbus_attach, sch_work, notify_charger;
> +
> +	if (rport->utmi_avalid)
> +		vbus_attach =
> +			property_enabled(rphy, &rport->port_cfg->utmi_avalid);
> +	else
> +		vbus_attach =
> +			property_enabled(rphy, &rport->port_cfg->utmi_bvalid);
> +
> +	sch_work = false;
> +	notify_charger = false;
> +	delay = OTG_SCHEDULE_DELAY;
> +	dev_dbg(&rport->phy->dev, "%s otg sm work\n",
> +		usb_otg_state_string(rport->state));
> +
> +	switch (rport->state) {
> +	case OTG_STATE_UNDEFINED:
> +		rport->state = OTG_STATE_B_IDLE;
> +		if (!vbus_attach)
> +			rockchip_usb2phy_power_off(rport->phy);
> +		/* fall through */
> +	case OTG_STATE_B_IDLE:
> +		if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) > 0) {
> +			dev_dbg(&rport->phy->dev, "usb otg host connect\n");
> +			rport->state = OTG_STATE_A_HOST;
> +			rockchip_usb2phy_power_on(rport->phy);
> +			return;
> +		} else if (vbus_attach) {
> +			dev_dbg(&rport->phy->dev, "vbus_attach\n");
> +			switch (rphy->chg_state) {
> +			case USB_CHG_STATE_UNDEFINED:
> +				schedule_delayed_work(&rport->chg_work, 0);
> +				return;
> +			case USB_CHG_STATE_DETECTED:
> +				switch (rphy->chg_type) {
> +				case POWER_SUPPLY_TYPE_USB:
> +					dev_dbg(&rport->phy->dev,
> +						"sdp cable is connecetd\n");
> +					rockchip_usb2phy_power_on(rport->phy);
> +					rport->state = OTG_STATE_B_PERIPHERAL;
> +					notify_charger = true;
> +					sch_work = true;
> +					cable = EXTCON_CHG_USB_SDP;
> +					break;
> +				case POWER_SUPPLY_TYPE_USB_DCP:
> +					dev_dbg(&rport->phy->dev,
> +						"dcp cable is connecetd\n");
> +					rockchip_usb2phy_power_off(rport->phy);
> +					notify_charger = true;
> +					sch_work = true;
> +					cable = EXTCON_CHG_USB_DCP;
> +					break;
> +				case POWER_SUPPLY_TYPE_USB_CDP:
> +					dev_dbg(&rport->phy->dev,
> +						"cdp cable is connecetd\n");
> +					rockchip_usb2phy_power_on(rport->phy);
> +					rport->state = OTG_STATE_B_PERIPHERAL;
> +					notify_charger = true;
> +					sch_work = true;
> +					cable = EXTCON_CHG_USB_CDP;
> +					break;
> +				default:
> +					break;
> +				}
> +				break;
> +			default:
> +				break;
> +			}
> +		} else {
> +			notify_charger = true;
> +			rphy->chg_state = USB_CHG_STATE_UNDEFINED;
> +			rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
> +		}
> +
> +		if (rport->vbus_attached != vbus_attach) {
> +			rport->vbus_attached = vbus_attach;
> +
> +			if (notify_charger && rphy->edev)
> +				extcon_set_cable_state_(rphy->edev,
> +							cable, vbus_attach);
> +		}
> +		break;
> +	case OTG_STATE_B_PERIPHERAL:
> +		if (!vbus_attach) {
> +			dev_dbg(&rport->phy->dev, "usb disconnect\n");
> +			rphy->chg_state = USB_CHG_STATE_UNDEFINED;
> +			rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
> +			rport->state = OTG_STATE_B_IDLE;
> +			delay = 0;
> +			rockchip_usb2phy_power_off(rport->phy);
> +		}
> +		sch_work = true;
> +		break;
> +	case OTG_STATE_A_HOST:
> +		if (extcon_get_cable_state_(rphy->edev, EXTCON_USB_HOST) == 0) {
> +			dev_dbg(&rport->phy->dev, "usb otg host disconnect\n");
> +			rport->state = OTG_STATE_B_IDLE;
> +			rockchip_usb2phy_power_off(rport->phy);
> +		}
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	if (sch_work)
> +		schedule_delayed_work(&rport->otg_sm_work, delay);
> +}
> +
> +static const char *chg_to_string(enum power_supply_type chg_type)
> +{
> +	switch (chg_type) {
> +	case POWER_SUPPLY_TYPE_USB:
> +		return "USB_SDP_CHARGER";
> +	case POWER_SUPPLY_TYPE_USB_DCP:
> +		return "USB_DCP_CHARGER";
> +	case POWER_SUPPLY_TYPE_USB_CDP:
> +		return "USB_CDP_CHARGER";
> +	default:
> +		return "INVALID_CHARGER";
> +	}
> +}
> +
> +static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
> +				    bool en)
> +{
> +	property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
> +	property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en);
> +}
> +
> +static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
> +					    bool en)
> +{
> +	property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en);
> +	property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en);
> +}
> +
> +static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
> +					      bool en)
> +{
> +	property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en);
> +	property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en);
> +}
> +
> +#define CHG_DCD_POLL_TIME	(100 * HZ / 1000)
> +#define CHG_DCD_MAX_RETRIES	6
> +#define CHG_PRIMARY_DET_TIME	(40 * HZ / 1000)
> +#define CHG_SECONDARY_DET_TIME	(40 * HZ / 1000)
> +static void rockchip_chg_detect_work(struct work_struct *work)
> +{
> +	struct rockchip_usb2phy_port *rport =
> +		container_of(work, struct rockchip_usb2phy_port, chg_work.work);
> +	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
> +	bool is_dcd, tmout, vout;
> +	unsigned long delay;
> +
> +	dev_dbg(&rport->phy->dev, "chg detection work state = %d\n",
> +		rphy->chg_state);
> +	switch (rphy->chg_state) {
> +	case USB_CHG_STATE_UNDEFINED:
> +		if (!rport->suspended)
> +			rockchip_usb2phy_power_off(rport->phy);
> +		/* put the controller in non-driving mode */
> +		property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, false);
> +		/* Start DCD processing stage 1 */
> +		rockchip_chg_enable_dcd(rphy, true);
> +		rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
> +		rphy->dcd_retries = 0;
> +		delay = CHG_DCD_POLL_TIME;
> +		break;
> +	case USB_CHG_STATE_WAIT_FOR_DCD:
> +		/* get data contact detection status */
> +		is_dcd = property_enabled(rphy, &rphy->phy_cfg->chg_det.dp_det);
> +		tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES;
> +		/* stage 2 */
> +		if (is_dcd || tmout) {
> +			/* stage 4 */
> +			/* Turn off DCD circuitry */
> +			rockchip_chg_enable_dcd(rphy, false);
> +			/* Voltage Source on DP, Probe on DM */
> +			rockchip_chg_enable_primary_det(rphy, true);
> +			delay = CHG_PRIMARY_DET_TIME;
> +			rphy->chg_state = USB_CHG_STATE_DCD_DONE;
> +		} else {
> +			/* stage 3 */
> +			delay = CHG_DCD_POLL_TIME;
> +		}
> +		break;
> +	case USB_CHG_STATE_DCD_DONE:
> +		vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.cp_det);
> +		rockchip_chg_enable_primary_det(rphy, false);
> +		if (vout) {
> +			/* Voltage Source on DM, Probe on DP  */
> +			rockchip_chg_enable_secondary_det(rphy, true);
> +			delay = CHG_SECONDARY_DET_TIME;
> +			rphy->chg_state = USB_CHG_STATE_PRIMARY_DONE;
> +		} else {
> +			if (tmout) {
> +				/* floating charger found */
> +				rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
> +				rphy->chg_state = USB_CHG_STATE_DETECTED;
> +				delay = 0;
> +			} else {
> +				rphy->chg_type = POWER_SUPPLY_TYPE_USB;
> +				rphy->chg_state = USB_CHG_STATE_DETECTED;
> +				delay = 0;
> +			}
> +		}
> +		break;
> +	case USB_CHG_STATE_PRIMARY_DONE:
> +		vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.dcp_det);
> +		/* Turn off voltage source */
> +		rockchip_chg_enable_secondary_det(rphy, false);
> +		if (vout)
> +			rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP;
> +		else
> +			rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP;
> +		/* fall through */
> +	case USB_CHG_STATE_SECONDARY_DONE:
> +		rphy->chg_state = USB_CHG_STATE_DETECTED;
> +		delay = 0;
> +		/* fall through */
> +	case USB_CHG_STATE_DETECTED:
> +		/* put the controller in normal mode */
> +		property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, true);
> +		rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
> +		dev_info(&rport->phy->dev, "charger = %s\n",
> +			 chg_to_string(rphy->chg_type));
> +		return;
> +	default:
> +		return;
> +	}
> +
> +	schedule_delayed_work(&rport->chg_work, delay);
> +}
> +
>  /*
>   * The function manage host-phy port state and suspend/resume phy port
>   * to save power.
> @@ -485,6 +884,26 @@ static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
>  	return IRQ_HANDLED;
>  }
>  
> +static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
> +{
> +	struct rockchip_usb2phy_port *rport = data;
> +	struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
> +
> +	if (!property_enabled(rphy, &rport->port_cfg->bvalid_det_st))
> +		return IRQ_NONE;
> +
> +	mutex_lock(&rport->mutex);
> +
> +	/* clear bvalid detect irq pending status */
> +	property_enable(rphy, &rport->port_cfg->bvalid_det_clr, true);
> +
> +	mutex_unlock(&rport->mutex);
> +
> +	rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
> +
> +	return IRQ_HANDLED;
> +}
> +
>  static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
>  					   struct rockchip_usb2phy_port *rport,
>  					   struct device_node *child_np)
> @@ -509,13 +928,86 @@ static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
>  					IRQF_ONESHOT,
>  					"rockchip_usb2phy", rport);
>  	if (ret) {
> -		dev_err(rphy->dev, "failed to request irq handle\n");
> +		dev_err(rphy->dev, "failed to request linestate irq handle\n");
>  		return ret;
>  	}
>  
>  	return 0;
>  }
>  
> +static int rockchip_otg_event(struct notifier_block *nb,
> +			      unsigned long event, void *ptr)
> +{
> +	struct rockchip_usb2phy_port *rport =
> +		container_of(nb, struct rockchip_usb2phy_port, event_nb);
> +
> +	schedule_delayed_work(&rport->otg_sm_work, OTG_SCHEDULE_DELAY);
> +
> +	return NOTIFY_DONE;
> +}
> +
> +static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
> +					  struct rockchip_usb2phy_port *rport,
> +					  struct device_node *child_np)
> +{
> +	int ret;
> +
> +	rport->port_id = USB2PHY_PORT_OTG;
> +	rport->port_cfg = &rphy->phy_cfg->port_cfgs[USB2PHY_PORT_OTG];
> +	rport->state = OTG_STATE_UNDEFINED;
> +
> +	/*
> +	 * set suspended flag to true, but actually don't
> +	 * put phy in suspend mode, it aims to enable usb
> +	 * phy and clock in power_on() called by usb controller
> +	 * driver during probe.
> +	 */
> +	rport->suspended = true;
> +	rport->vbus_attached = false;
> +
> +	mutex_init(&rport->mutex);
> +
> +	rport->mode = of_usb_get_dr_mode_by_phy(child_np, -1);
> +	if (rport->mode == USB_DR_MODE_HOST) {
> +		ret = 0;
> +		goto out;
> +	}
> +
> +	INIT_DELAYED_WORK(&rport->chg_work, rockchip_chg_detect_work);
> +	INIT_DELAYED_WORK(&rport->otg_sm_work, rockchip_usb2phy_otg_sm_work);
> +
> +	rport->utmi_avalid =
> +		of_property_read_bool(child_np, "rockchip,utmi-avalid");
> +
> +	rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid");
> +	if (rport->bvalid_irq < 0) {
> +		dev_err(rphy->dev, "no vbus valid irq provided\n");
> +		ret = rport->bvalid_irq;
> +		goto out;
> +	}
> +
> +	ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, NULL,
> +					rockchip_usb2phy_bvalid_irq,
> +					IRQF_ONESHOT,
> +					"rockchip_usb2phy_bvalid", rport);
> +	if (ret) {
> +		dev_err(rphy->dev, "failed to request otg-bvalid irq handle\n");
> +		goto out;
> +	}
> +
> +	if (!IS_ERR(rphy->edev)) {
> +		rport->event_nb.notifier_call = rockchip_otg_event;
> +
> +		ret = extcon_register_notifier(rphy->edev, EXTCON_USB_HOST,
> +					       &rport->event_nb);
> +		if (ret)
> +			dev_err(rphy->dev, "register USB HOST notifier failed\n");
> +	}
> +
> +out:
> +	return ret;
> +}
> +
>  static int rockchip_usb2phy_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -553,8 +1045,14 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
>  
>  	rphy->dev = dev;
>  	phy_cfgs = match->data;
> +	rphy->chg_state = USB_CHG_STATE_UNDEFINED;
> +	rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN;
>  	platform_set_drvdata(pdev, rphy);
>  
> +	ret = rockchip_usb2phy_extcon_register(rphy);
> +	if (ret)
> +		return ret;
> +
>  	/* find out a proper config which can be matched with dt. */
>  	index = 0;
>  	while (phy_cfgs[index].reg) {
> @@ -591,13 +1089,9 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
>  		struct rockchip_usb2phy_port *rport = &rphy->ports[index];
>  		struct phy *phy;
>  
> -		/*
> -		 * This driver aim to support both otg-port and host-port,
> -		 * but unfortunately, the otg part is not ready in current,
> -		 * so this comments and below codes are interim, which should
> -		 * be changed after otg-port is supplied soon.
> -		 */
> -		if (of_node_cmp(child_np->name, "host-port"))
> +		/* This driver aims to support both otg-port and host-port */
> +		if (of_node_cmp(child_np->name, "host-port") &&
> +		    of_node_cmp(child_np->name, "otg-port"))
>  			goto next_child;
>  
>  		phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops);
> @@ -610,9 +1104,18 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
>  		rport->phy = phy;
>  		phy_set_drvdata(rport->phy, rport);
>  
> -		ret = rockchip_usb2phy_host_port_init(rphy, rport, child_np);
> -		if (ret)
> -			goto put_child;
> +		/* initialize otg/host port separately */
> +		if (!of_node_cmp(child_np->name, "host-port")) {
> +			ret = rockchip_usb2phy_host_port_init(rphy, rport,
> +							      child_np);
> +			if (ret)
> +				goto put_child;
> +		} else {
> +			ret = rockchip_usb2phy_otg_port_init(rphy, rport,
> +							     child_np);
> +			if (ret)
> +				goto put_child;
> +		}
>  
>  next_child:
>  		/* to prevent out of boundary */
> @@ -654,10 +1157,18 @@ static const struct rockchip_usb2phy_cfg rk3366_phy_cfgs[] = {
>  
>  static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
>  	{
> -		.reg = 0xe450,
> +		.reg		= 0xe450,
>  		.num_ports	= 2,
>  		.clkout_ctl	= { 0xe450, 4, 4, 1, 0 },
>  		.port_cfgs	= {
> +			[USB2PHY_PORT_OTG] = {
> +				.phy_sus	= { 0xe454, 1, 0, 2, 1 },
> +				.bvalid_det_en	= { 0xe3c0, 3, 3, 0, 1 },
> +				.bvalid_det_st	= { 0xe3e0, 3, 3, 0, 1 },
> +				.bvalid_det_clr	= { 0xe3d0, 3, 3, 0, 1 },
> +				.utmi_avalid	= { 0xe2ac, 7, 7, 0, 1 },
> +				.utmi_bvalid	= { 0xe2ac, 12, 12, 0, 1 },
> +			},
>  			[USB2PHY_PORT_HOST] = {
>  				.phy_sus	= { 0xe458, 1, 0, 0x2, 0x1 },
>  				.ls_det_en	= { 0xe3c0, 6, 6, 0, 1 },
> @@ -667,12 +1178,32 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
>  				.utmi_hstdet	= { 0xe2ac, 23, 23, 0, 1 }
>  			}
>  		},
> +		.chg_det = {
> +			.opmode		= { 0xe454, 3, 0, 5, 1 },
> +			.cp_det		= { 0xe2ac, 2, 2, 0, 1 },
> +			.dcp_det	= { 0xe2ac, 1, 1, 0, 1 },
> +			.dp_det		= { 0xe2ac, 0, 0, 0, 1 },
> +			.idm_sink_en	= { 0xe450, 8, 8, 0, 1 },
> +			.idp_sink_en	= { 0xe450, 7, 7, 0, 1 },
> +			.idp_src_en	= { 0xe450, 9, 9, 0, 1 },
> +			.rdm_pdwn_en	= { 0xe450, 10, 10, 0, 1 },
> +			.vdm_src_en	= { 0xe450, 12, 12, 0, 1 },
> +			.vdp_src_en	= { 0xe450, 11, 11, 0, 1 },
> +		},
>  	},
>  	{
> -		.reg = 0xe460,
> +		.reg		= 0xe460,
>  		.num_ports	= 2,
>  		.clkout_ctl	= { 0xe460, 4, 4, 1, 0 },
>  		.port_cfgs	= {
> +			[USB2PHY_PORT_OTG] = {
> +				.phy_sus        = { 0xe464, 1, 0, 2, 1 },
> +				.bvalid_det_en  = { 0xe3c0, 8, 8, 0, 1 },
> +				.bvalid_det_st  = { 0xe3e0, 8, 8, 0, 1 },
> +				.bvalid_det_clr = { 0xe3d0, 8, 8, 0, 1 },
> +				.utmi_avalid	= { 0xe2ac, 10, 10, 0, 1 },
> +				.utmi_bvalid    = { 0xe2ac, 16, 16, 0, 1 },
> +			},
>  			[USB2PHY_PORT_HOST] = {
>  				.phy_sus	= { 0xe468, 1, 0, 0x2, 0x1 },
>  				.ls_det_en	= { 0xe3c0, 11, 11, 0, 1 },
> 

^ permalink raw reply

* [PATCH] arm64: errata: Check for --fix-cortex-a53-843419 and --fix-cortex-a53
From: Florian Fainelli @ 2016-11-03 17:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161103141559.GQ22791@arm.com>

On 11/03/2016 07:16 AM, Will Deacon wrote:
> On Wed, Nov 02, 2016 at 02:57:26PM -0700, Florian Fainelli wrote:
>> On 11/02/2016 02:41 PM, Markus Mayer wrote:
>>> On 2 November 2016 at 14:27, Will Deacon <will.deacon@arm.com> wrote:
>>>> On Wed, Nov 02, 2016 at 02:07:17PM -0700, Markus Mayer wrote:
>>>>> The question I am asking is: What do we have to lose by supporting both options?
>>>>
>>>> We end up passing "--fix-cortex-a53" to the linker, without knowing what it
>>>> might do in the future.
>>>
>>> It seems highly unlikely that such a generic option would be added in
>>> the future, both, because the precedent has been set for topic
>>> specific options, and because they know it has been used in the past,
>>> so they wouldn't add a previously used option to do something
>>> completely different. (And if they really did, then that would be a
>>> huge binutils bug.)
>>>
>>> So, we have a trade-off between a real world problem that does
>>> currently exist and avoiding a theoretical issue that may never
>>> materialize.
>>
>> Agreed, also the way Markus' patch is designed makes it such that we
>> first try the full and current option name, and if not supported, try
>> the second (and earlier, now obsolete) option name, so I really don't
>> see a lot of room for things to go wrong here...
> 
> It's not beyond the realms of possibility that ld will grow a
> "fix-cortex-a53" option in the future, that enables all of the a53
> workarounds. Since ld is the linker supported by the kernel and gold isn't,
> I don't want to pass this option down.

No it's entirely reasonable to think this may happen, although:

- this has not happened yet, so once this happens, you will need to cook
a patch for this anyway, and you will be able to gate this catch all
linker option by an appropriate version check presumably

- you would supposedly want a fine grained set of linker options that
are specific to workarounds you have to have enabled, instead of a catch
all "enable all Cortex A53" workarounds

> 
> If you can't change toolchain and you want this worked around, why can't you
> either build gold with it enabled by default, or pass the extra flag on the
> command line to the kernel build system?

Because that creates a distribution problem and now we have to document
this for people who want to build a kernel on their own, without
necessarily understanding if this is something they might need, or why
this is needed, and why the kernel is not taking care of that on its
own? So yes, this comes down to who is responsible for what, in that
case the kernel's Makefile is the best place where to put such knowledge
as to which workaround needs to be enabled by the linker and it
simplifies things a lot for people.
-- 
Florian

^ permalink raw reply

* [PATCH 0/2] mm: fix the "counter.sh" failure for libhugetlbfs
From: Randy Dunlap @ 2016-11-03 17:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1478141499-13825-1-git-send-email-shijie.huang@arm.com>

On 11/02/16 19:51, Huang Shijie wrote:
> 
> (2) The bug   
>    After I tested the libhugetlbfs, I found the test case "counter.sh"
>    will fail with the gigantic page (32M page in arm64 board).
> 
>    This patch set adds support for gigantic surplus hugetlb pages,
>    allowing the counter.sh unit test to pass.   

Hi,
Where is the counter.sh test? Where can I find it?

thanks.
-- 
~Randy

^ permalink raw reply

* Applied "ASoC: sun4i-codec: Move data structures to add create_card call to quirks" to the asoc tree
From: Mark Brown @ 2016-11-03 17:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161103075556.29018-2-wens@csie.org>

The patch

   ASoC: sun4i-codec: Move data structures to add create_card call to quirks

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 2f2a3462bc15e9613412ca186bf8a6611afa66c7 Mon Sep 17 00:00:00 2001
From: Chen-Yu Tsai <wens@csie.org>
Date: Thu, 3 Nov 2016 15:55:43 +0800
Subject: [PATCH] ASoC: sun4i-codec: Move data structures to add create_card
 call to quirks

The audio codec on later Allwinner SoCs have a different layout and
audio path compared to the A10/A20. However the PCM parts are still
the same.

The different layout and audio paths mean we need a different
create_card function for different families, so they can create
DAPM endpoint widgets and routes.

This patch moves the regmap configs, quirks and of_device_id
structures to just before the probe function, so we can, among other
things, include a pointer for the create_card function. None of the
lines of code were changed.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/sunxi/sun4i-codec.c | 78 +++++++++++++++++++++----------------------
 1 file changed, 39 insertions(+), 39 deletions(-)

diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c
index a60707761abf..7b78f4045d38 100644
--- a/sound/soc/sunxi/sun4i-codec.c
+++ b/sound/soc/sunxi/sun4i-codec.c
@@ -678,45 +678,6 @@ static struct snd_soc_dai_driver dummy_cpu_dai = {
 	 },
 };
 
-static const struct regmap_config sun4i_codec_regmap_config = {
-	.reg_bits	= 32,
-	.reg_stride	= 4,
-	.val_bits	= 32,
-	.max_register	= SUN4I_CODEC_ADC_RXCNT,
-};
-
-static const struct regmap_config sun7i_codec_regmap_config = {
-	.reg_bits	= 32,
-	.reg_stride	= 4,
-	.val_bits	= 32,
-	.max_register	= SUN7I_CODEC_AC_MIC_PHONE_CAL,
-};
-
-struct sun4i_codec_quirks {
-	const struct regmap_config *regmap_config;
-};
-
-static const struct sun4i_codec_quirks sun4i_codec_quirks = {
-	.regmap_config = &sun4i_codec_regmap_config,
-};
-
-static const struct sun4i_codec_quirks sun7i_codec_quirks = {
-	.regmap_config = &sun7i_codec_regmap_config,
-};
-
-static const struct of_device_id sun4i_codec_of_match[] = {
-	{
-		.compatible = "allwinner,sun4i-a10-codec",
-		.data = &sun4i_codec_quirks,
-	},
-	{
-		.compatible = "allwinner,sun7i-a20-codec",
-		.data = &sun7i_codec_quirks,
-	},
-	{}
-};
-MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
-
 static struct snd_soc_dai_link *sun4i_codec_create_link(struct device *dev,
 							int *num_links)
 {
@@ -781,6 +742,45 @@ static struct snd_soc_card *sun4i_codec_create_card(struct device *dev)
 	return card;
 };
 
+static const struct regmap_config sun4i_codec_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= SUN4I_CODEC_ADC_RXCNT,
+};
+
+static const struct regmap_config sun7i_codec_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= SUN7I_CODEC_AC_MIC_PHONE_CAL,
+};
+
+struct sun4i_codec_quirks {
+	const struct regmap_config *regmap_config;
+};
+
+static const struct sun4i_codec_quirks sun4i_codec_quirks = {
+	.regmap_config	= &sun4i_codec_regmap_config,
+};
+
+static const struct sun4i_codec_quirks sun7i_codec_quirks = {
+	.regmap_config	= &sun7i_codec_regmap_config,
+};
+
+static const struct of_device_id sun4i_codec_of_match[] = {
+	{
+		.compatible = "allwinner,sun4i-a10-codec",
+		.data = &sun4i_codec_quirks,
+	},
+	{
+		.compatible = "allwinner,sun7i-a20-codec",
+		.data = &sun7i_codec_quirks,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, sun4i_codec_of_match);
+
 static int sun4i_codec_probe(struct platform_device *pdev)
 {
 	struct snd_soc_card *card;
-- 
2.10.1

^ permalink raw reply related


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