* [PATCH v3 1/8] clk: sunxi: Implement A31 USB clock
2014-05-12 19:34 [PATCH v3 0/8] Add Allwinner A31 USB support Maxime Ripard
@ 2014-05-12 19:34 ` Maxime Ripard
2014-05-13 1:32 ` Mike Turquette
2014-05-12 19:34 ` [PATCH v3 2/8] ARM: sun6i: Add the USB clocks to the DTSI Maxime Ripard
` (6 subsequent siblings)
7 siblings, 1 reply; 13+ messages in thread
From: Maxime Ripard @ 2014-05-12 19:34 UTC (permalink / raw)
To: linux-arm-kernel
The A31 USB clock slightly differ from its older counterparts, mostly because
it has a different gate for each PHY, while the older one had a single gate for
all the phy.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/clk/sunxi/clk-sunxi.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index bd7dc733c1ca..d9bab75f128b 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -972,6 +972,11 @@ static const struct gates_data sun5i_a13_usb_gates_data __initconst = {
.reset_mask = 0x03,
};
+static const struct gates_data sun6i_a31_usb_gates_data __initconst = {
+ .mask = { BIT(18) | BIT(17) | BIT(16) | BIT(10) | BIT(9) | BIT(8) },
+ .reset_mask = BIT(2) | BIT(1) | BIT(0),
+};
+
static void __init sunxi_gates_clk_setup(struct device_node *node,
struct gates_data *data)
{
@@ -1267,6 +1272,7 @@ static const struct of_device_id clk_gates_match[] __initconst = {
{.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
{.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
{.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,},
+ {.compatible = "allwinner,sun6i-a31-usb-clk", .data = &sun6i_a31_usb_gates_data,},
{}
};
--
1.9.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v3 1/8] clk: sunxi: Implement A31 USB clock
2014-05-12 19:34 ` [PATCH v3 1/8] clk: sunxi: Implement A31 USB clock Maxime Ripard
@ 2014-05-13 1:32 ` Mike Turquette
0 siblings, 0 replies; 13+ messages in thread
From: Mike Turquette @ 2014-05-13 1:32 UTC (permalink / raw)
To: linux-arm-kernel
Quoting Maxime Ripard (2014-05-12 12:34:27)
> The A31 USB clock slightly differ from its older counterparts, mostly because
> it has a different gate for each PHY, while the older one had a single gate for
> all the phy.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Mike Turquette <mturquette@linaro.org>
> ---
> drivers/clk/sunxi/clk-sunxi.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
> index bd7dc733c1ca..d9bab75f128b 100644
> --- a/drivers/clk/sunxi/clk-sunxi.c
> +++ b/drivers/clk/sunxi/clk-sunxi.c
> @@ -972,6 +972,11 @@ static const struct gates_data sun5i_a13_usb_gates_data __initconst = {
> .reset_mask = 0x03,
> };
>
> +static const struct gates_data sun6i_a31_usb_gates_data __initconst = {
> + .mask = { BIT(18) | BIT(17) | BIT(16) | BIT(10) | BIT(9) | BIT(8) },
> + .reset_mask = BIT(2) | BIT(1) | BIT(0),
> +};
> +
> static void __init sunxi_gates_clk_setup(struct device_node *node,
> struct gates_data *data)
> {
> @@ -1267,6 +1272,7 @@ static const struct of_device_id clk_gates_match[] __initconst = {
> {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
> {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
> {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,},
> + {.compatible = "allwinner,sun6i-a31-usb-clk", .data = &sun6i_a31_usb_gates_data,},
> {}
> };
>
> --
> 1.9.3
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 2/8] ARM: sun6i: Add the USB clocks to the DTSI.
2014-05-12 19:34 [PATCH v3 0/8] Add Allwinner A31 USB support Maxime Ripard
2014-05-12 19:34 ` [PATCH v3 1/8] clk: sunxi: Implement A31 USB clock Maxime Ripard
@ 2014-05-12 19:34 ` Maxime Ripard
2014-05-12 19:34 ` [PATCH v3 3/8] phy: sunxi: Rework phy initialization Maxime Ripard
` (5 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Maxime Ripard @ 2014-05-12 19:34 UTC (permalink / raw)
To: linux-arm-kernel
The USB clocks of the A31 seems to be parented to the 24MHz oscillator, and
handle the clocks for the USB phys and OHCI devices.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun6i-a31.dtsi | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index eec1afa257a5..13aa56ed5858 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -269,6 +269,17 @@
clocks = <&osc24M>, <&pll6>;
clock-output-names = "spi3";
};
+
+ usb_clk: clk at 01c200cc {
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ compatible = "allwinner,sun6i-a31-usb-clk";
+ reg = <0x01c200cc 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "usb_phy0", "usb_phy1", "usb_phy2",
+ "usb_ohci0", "usb_ohci1",
+ "usb_ohci2";
+ };
};
soc at 01c00000 {
--
1.9.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v3 3/8] phy: sunxi: Rework phy initialization
2014-05-12 19:34 [PATCH v3 0/8] Add Allwinner A31 USB support Maxime Ripard
2014-05-12 19:34 ` [PATCH v3 1/8] clk: sunxi: Implement A31 USB clock Maxime Ripard
2014-05-12 19:34 ` [PATCH v3 2/8] ARM: sun6i: Add the USB clocks to the DTSI Maxime Ripard
@ 2014-05-12 19:34 ` Maxime Ripard
2014-05-13 6:39 ` Hans de Goede
2014-05-12 19:34 ` [PATCH v3 4/8] phy: usb: sunxi: Introduce Allwinner A31 USB PHY support Maxime Ripard
` (4 subsequent siblings)
7 siblings, 1 reply; 13+ messages in thread
From: Maxime Ripard @ 2014-05-12 19:34 UTC (permalink / raw)
To: linux-arm-kernel
Move the phy initialization and variables declaration to the loop itself, since
it is where it really belongs. Also remove all the temporary variables, we can
use the structure members directly.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/phy/phy-sun4i-usb.c | 44 ++++++++++++++++++++------------------------
1 file changed, 20 insertions(+), 24 deletions(-)
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index e6e6c4ba7145..81896409c4bd 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -224,13 +224,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
struct sun4i_usb_phy_data *data;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
- void __iomem *pmu = NULL;
struct phy_provider *phy_provider;
- struct reset_control *reset;
- struct regulator *vbus;
struct resource *res;
- struct phy *phy;
- char name[16];
int i;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
@@ -262,42 +257,43 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
/* Skip 0, 0 is the phy for otg which is not yet supported. */
for (i = 1; i < data->num_phys; i++) {
+ struct sun4i_usb_phy *phy = data->phys + i;
+ char name[16];
+
snprintf(name, sizeof(name), "usb%d_vbus", i);
- vbus = devm_regulator_get_optional(dev, name);
- if (IS_ERR(vbus)) {
- if (PTR_ERR(vbus) == -EPROBE_DEFER)
+ phy->vbus = devm_regulator_get_optional(dev, name);
+ if (IS_ERR(phy->vbus)) {
+ if (PTR_ERR(phy->vbus) == -EPROBE_DEFER)
return -EPROBE_DEFER;
- vbus = NULL;
+ phy->vbus = NULL;
}
snprintf(name, sizeof(name), "usb%d_reset", i);
- reset = devm_reset_control_get(dev, name);
- if (IS_ERR(reset)) {
+ phy->reset = devm_reset_control_get(dev, name);
+ if (IS_ERR(phy->reset)) {
dev_err(dev, "failed to get reset %s\n", name);
- return PTR_ERR(reset);
+ return PTR_ERR(phy->reset);
}
if (i) { /* No pmu for usbc0 */
snprintf(name, sizeof(name), "pmu%d", i);
res = platform_get_resource_byname(pdev,
IORESOURCE_MEM, name);
- pmu = devm_ioremap_resource(dev, res);
- if (IS_ERR(pmu))
- return PTR_ERR(pmu);
+ phy->pmu = devm_ioremap_resource(dev, res);
+ if (IS_ERR(phy->pmu))
+ return PTR_ERR(phy->pmu);
+ } else {
+ phy->pmu = NULL;
}
- phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL);
- if (IS_ERR(phy)) {
+ phy->phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL);
+ if (IS_ERR(phy->phy)) {
dev_err(dev, "failed to create PHY %d\n", i);
- return PTR_ERR(phy);
+ return PTR_ERR(phy->phy);
}
- data->phys[i].phy = phy;
- data->phys[i].pmu = pmu;
- data->phys[i].vbus = vbus;
- data->phys[i].reset = reset;
- data->phys[i].index = i;
- phy_set_drvdata(phy, &data->phys[i]);
+ phy->index = i;
+ phy_set_drvdata(phy->phy, &data->phys[i]);
}
dev_set_drvdata(dev, data);
--
1.9.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v3 3/8] phy: sunxi: Rework phy initialization
2014-05-12 19:34 ` [PATCH v3 3/8] phy: sunxi: Rework phy initialization Maxime Ripard
@ 2014-05-13 6:39 ` Hans de Goede
0 siblings, 0 replies; 13+ messages in thread
From: Hans de Goede @ 2014-05-13 6:39 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
On 05/12/2014 09:34 PM, Maxime Ripard wrote:
> Move the phy initialization and variables declaration to the loop itself, since
> it is where it really belongs. Also remove all the temporary variables, we can
> use the structure members directly.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
> drivers/phy/phy-sun4i-usb.c | 44 ++++++++++++++++++++------------------------
> 1 file changed, 20 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
> index e6e6c4ba7145..81896409c4bd 100644
> --- a/drivers/phy/phy-sun4i-usb.c
> +++ b/drivers/phy/phy-sun4i-usb.c
> @@ -224,13 +224,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
> struct sun4i_usb_phy_data *data;
> struct device *dev = &pdev->dev;
> struct device_node *np = dev->of_node;
> - void __iomem *pmu = NULL;
> struct phy_provider *phy_provider;
> - struct reset_control *reset;
> - struct regulator *vbus;
> struct resource *res;
> - struct phy *phy;
> - char name[16];
> int i;
>
> data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> @@ -262,42 +257,43 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
>
> /* Skip 0, 0 is the phy for otg which is not yet supported. */
> for (i = 1; i < data->num_phys; i++) {
> + struct sun4i_usb_phy *phy = data->phys + i;
> + char name[16];
> +
> snprintf(name, sizeof(name), "usb%d_vbus", i);
> - vbus = devm_regulator_get_optional(dev, name);
> - if (IS_ERR(vbus)) {
> - if (PTR_ERR(vbus) == -EPROBE_DEFER)
> + phy->vbus = devm_regulator_get_optional(dev, name);
> + if (IS_ERR(phy->vbus)) {
> + if (PTR_ERR(phy->vbus) == -EPROBE_DEFER)
> return -EPROBE_DEFER;
> - vbus = NULL;
> + phy->vbus = NULL;
> }
>
> snprintf(name, sizeof(name), "usb%d_reset", i);
> - reset = devm_reset_control_get(dev, name);
> - if (IS_ERR(reset)) {
> + phy->reset = devm_reset_control_get(dev, name);
> + if (IS_ERR(phy->reset)) {
> dev_err(dev, "failed to get reset %s\n", name);
> - return PTR_ERR(reset);
> + return PTR_ERR(phy->reset);
> }
>
> if (i) { /* No pmu for usbc0 */
> snprintf(name, sizeof(name), "pmu%d", i);
> res = platform_get_resource_byname(pdev,
> IORESOURCE_MEM, name);
> - pmu = devm_ioremap_resource(dev, res);
> - if (IS_ERR(pmu))
> - return PTR_ERR(pmu);
> + phy->pmu = devm_ioremap_resource(dev, res);
> + if (IS_ERR(phy->pmu))
> + return PTR_ERR(phy->pmu);
> + } else {
> + phy->pmu = NULL;
> }
>
data is kzalloced, so there is no need for this else branch. Other then that
this patch is:
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Regards,
Hans
> - phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL);
> - if (IS_ERR(phy)) {
> + phy->phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL);
> + if (IS_ERR(phy->phy)) {
> dev_err(dev, "failed to create PHY %d\n", i);
> - return PTR_ERR(phy);
> + return PTR_ERR(phy->phy);
> }
>
> - data->phys[i].phy = phy;
> - data->phys[i].pmu = pmu;
> - data->phys[i].vbus = vbus;
> - data->phys[i].reset = reset;
> - data->phys[i].index = i;
> - phy_set_drvdata(phy, &data->phys[i]);
> + phy->index = i;
> + phy_set_drvdata(phy->phy, &data->phys[i]);
> }
>
> dev_set_drvdata(dev, data);
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 4/8] phy: usb: sunxi: Introduce Allwinner A31 USB PHY support
2014-05-12 19:34 [PATCH v3 0/8] Add Allwinner A31 USB support Maxime Ripard
` (2 preceding siblings ...)
2014-05-12 19:34 ` [PATCH v3 3/8] phy: sunxi: Rework phy initialization Maxime Ripard
@ 2014-05-12 19:34 ` Maxime Ripard
2014-05-12 19:34 ` [PATCH v3 5/8] usb: ehci-platform: add optional reset controller retrieval Maxime Ripard
` (3 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Maxime Ripard @ 2014-05-12 19:34 UTC (permalink / raw)
To: linux-arm-kernel
The USB phy controller in the A31 differs mostly from the older controllers
because it has a clock dedicated for each phy, while the older ones were having
a single clock for all the phys.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/phy/phy-sun4i-usb.c | 33 ++++++++++++++++++++++-----------
1 file changed, 22 insertions(+), 11 deletions(-)
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index 81896409c4bd..e15715aeec24 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -61,7 +61,6 @@
#define MAX_PHYS 3
struct sun4i_usb_phy_data {
- struct clk *clk;
void __iomem *base;
struct mutex mutex;
int num_phys;
@@ -71,6 +70,7 @@ struct sun4i_usb_phy_data {
void __iomem *pmu;
struct regulator *vbus;
struct reset_control *reset;
+ struct clk *clk;
int index;
} phys[MAX_PHYS];
};
@@ -146,13 +146,13 @@ static int sun4i_usb_phy_init(struct phy *_phy)
struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
int ret;
- ret = clk_prepare_enable(data->clk);
+ ret = clk_prepare_enable(phy->clk);
if (ret)
return ret;
ret = reset_control_deassert(phy->reset);
if (ret) {
- clk_disable_unprepare(data->clk);
+ clk_disable_unprepare(phy->clk);
return ret;
}
@@ -170,11 +170,10 @@ static int sun4i_usb_phy_init(struct phy *_phy)
static int sun4i_usb_phy_exit(struct phy *_phy)
{
struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
- struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
sun4i_usb_phy_passby(phy, 0);
reset_control_assert(phy->reset);
- clk_disable_unprepare(data->clk);
+ clk_disable_unprepare(phy->clk);
return 0;
}
@@ -225,6 +224,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct phy_provider *phy_provider;
+ bool dedicated_clocks;
struct resource *res;
int i;
@@ -244,17 +244,16 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
else
data->disc_thresh = 2;
+ if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy"))
+ dedicated_clocks = true;
+ else
+ dedicated_clocks = false;
+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
data->base = devm_ioremap_resource(dev, res);
if (IS_ERR(data->base))
return PTR_ERR(data->base);
- data->clk = devm_clk_get(dev, "usb_phy");
- if (IS_ERR(data->clk)) {
- dev_err(dev, "could not get usb_phy clock\n");
- return PTR_ERR(data->clk);
- }
-
/* Skip 0, 0 is the phy for otg which is not yet supported. */
for (i = 1; i < data->num_phys; i++) {
struct sun4i_usb_phy *phy = data->phys + i;
@@ -268,6 +267,17 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
phy->vbus = NULL;
}
+ if (dedicated_clocks)
+ snprintf(name, sizeof(name), "usb%d_phy", i);
+ else
+ strlcpy(name, "usb_phy", sizeof(name));
+
+ phy->clk = devm_clk_get(dev, name);
+ if (IS_ERR(phy->clk)) {
+ dev_err(dev, "failed to get clock %s\n", name);
+ return PTR_ERR(phy->clk);
+ }
+
snprintf(name, sizeof(name), "usb%d_reset", i);
phy->reset = devm_reset_control_get(dev, name);
if (IS_ERR(phy->reset)) {
@@ -307,6 +317,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
static const struct of_device_id sun4i_usb_phy_of_match[] = {
{ .compatible = "allwinner,sun4i-a10-usb-phy" },
{ .compatible = "allwinner,sun5i-a13-usb-phy" },
+ { .compatible = "allwinner,sun6i-a31-usb-phy" },
{ .compatible = "allwinner,sun7i-a20-usb-phy" },
{ },
};
--
1.9.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v3 5/8] usb: ehci-platform: add optional reset controller retrieval
2014-05-12 19:34 [PATCH v3 0/8] Add Allwinner A31 USB support Maxime Ripard
` (3 preceding siblings ...)
2014-05-12 19:34 ` [PATCH v3 4/8] phy: usb: sunxi: Introduce Allwinner A31 USB PHY support Maxime Ripard
@ 2014-05-12 19:34 ` Maxime Ripard
2014-05-12 20:06 ` Alan Stern
2014-05-12 19:34 ` [PATCH v3 6/8] usb: ohci-platform: Enable optional use of reset controller Maxime Ripard
` (2 subsequent siblings)
7 siblings, 1 reply; 13+ messages in thread
From: Maxime Ripard @ 2014-05-12 19:34 UTC (permalink / raw)
To: linux-arm-kernel
From: Boris BREZILLON <boris.brezillon@free-electrons.com>
On the Allwinner's A31 SoC the reset line connected to the EHCI IP has to
be deasserted for the EHCI block to be usable.
Add support for an optional reset controller that will be deasserted on
power off and asserted on power on.
Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
Documentation/devicetree/bindings/usb/usb-ehci.txt | 1 +
drivers/usb/host/ehci-platform.c | 17 +++++++++++++++++
2 files changed, 18 insertions(+)
diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt
index ff151ec084c4..43c1a4e06767 100644
--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
@@ -15,6 +15,7 @@ Optional properties:
- clocks : a list of phandle + clock specifier pairs
- phys : phandle + phy specifier pair
- phy-names : "usb"
+ - resets : phandle + reset specifier pair
Example (Sequoia 440EPx):
ehci at e0000300 {
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index c7dd93aad20c..8bb15eda9713 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -29,6 +29,7 @@
#include <linux/of.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
+#include <linux/reset.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/usb/ehci_pdriver.h>
@@ -41,6 +42,7 @@
struct ehci_platform_priv {
struct clk *clks[EHCI_MAX_CLKS];
+ struct reset_control *rst;
struct phy *phy;
};
@@ -208,6 +210,18 @@ static int ehci_platform_probe(struct platform_device *dev)
}
}
+ priv->rst = devm_reset_control_get_optional(&dev->dev, NULL);
+ if (IS_ERR(priv->rst)) {
+ err = PTR_ERR(priv->rst);
+ if (err == -EPROBE_DEFER)
+ goto err_put_clks;
+ priv->rst = NULL;
+ } else {
+ err = reset_control_deassert(priv->rst);
+ if (err)
+ goto err_put_clks;
+ }
+
if (pdata->big_endian_desc)
ehci->big_endian_desc = 1;
if (pdata->big_endian_mmio)
@@ -280,6 +294,9 @@ static int ehci_platform_remove(struct platform_device *dev)
if (pdata->power_off)
pdata->power_off(dev);
+ if (priv->rst)
+ reset_control_assert(priv->rst);
+
for (clk = 0; clk < EHCI_MAX_CLKS && priv->clks[clk]; clk++)
clk_put(priv->clks[clk]);
--
1.9.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v3 5/8] usb: ehci-platform: add optional reset controller retrieval
2014-05-12 19:34 ` [PATCH v3 5/8] usb: ehci-platform: add optional reset controller retrieval Maxime Ripard
@ 2014-05-12 20:06 ` Alan Stern
2014-05-13 7:51 ` Maxime Ripard
0 siblings, 1 reply; 13+ messages in thread
From: Alan Stern @ 2014-05-12 20:06 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, 12 May 2014, Maxime Ripard wrote:
> From: Boris BREZILLON <boris.brezillon@free-electrons.com>
>
> On the Allwinner's A31 SoC the reset line connected to the EHCI IP has to
> be deasserted for the EHCI block to be usable.
>
> Add support for an optional reset controller that will be deasserted on
> power off and asserted on power on.
>
> Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
...
> @@ -208,6 +210,18 @@ static int ehci_platform_probe(struct platform_device *dev)
> }
> }
>
> + priv->rst = devm_reset_control_get_optional(&dev->dev, NULL);
> + if (IS_ERR(priv->rst)) {
> + err = PTR_ERR(priv->rst);
> + if (err == -EPROBE_DEFER)
> + goto err_put_clks;
> + priv->rst = NULL;
> + } else {
> + err = reset_control_deassert(priv->rst);
> + if (err)
> + goto err_put_clks;
> + }
> +
> if (pdata->big_endian_desc)
> ehci->big_endian_desc = 1;
> if (pdata->big_endian_mmio)
You don't re-assert the reset control if an error happens later on
during probe. Was that intentional?
Alan Stern
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v3 5/8] usb: ehci-platform: add optional reset controller retrieval
2014-05-12 20:06 ` Alan Stern
@ 2014-05-13 7:51 ` Maxime Ripard
0 siblings, 0 replies; 13+ messages in thread
From: Maxime Ripard @ 2014-05-13 7:51 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, May 12, 2014 at 04:06:16PM -0400, Alan Stern wrote:
> On Mon, 12 May 2014, Maxime Ripard wrote:
>
> > From: Boris BREZILLON <boris.brezillon@free-electrons.com>
> >
> > On the Allwinner's A31 SoC the reset line connected to the EHCI IP has to
> > be deasserted for the EHCI block to be usable.
> >
> > Add support for an optional reset controller that will be deasserted on
> > power off and asserted on power on.
> >
> > Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > Reviewed-by: Hans de Goede <hdegoede@redhat.com>
>
> ...
>
> > @@ -208,6 +210,18 @@ static int ehci_platform_probe(struct platform_device *dev)
> > }
> > }
> >
> > + priv->rst = devm_reset_control_get_optional(&dev->dev, NULL);
> > + if (IS_ERR(priv->rst)) {
> > + err = PTR_ERR(priv->rst);
> > + if (err == -EPROBE_DEFER)
> > + goto err_put_clks;
> > + priv->rst = NULL;
> > + } else {
> > + err = reset_control_deassert(priv->rst);
> > + if (err)
> > + goto err_put_clks;
> > + }
> > +
> > if (pdata->big_endian_desc)
> > ehci->big_endian_desc = 1;
> > if (pdata->big_endian_mmio)
>
> You don't re-assert the reset control if an error happens later on
> during probe. Was that intentional?
No, it wasn't. I'll resubmit another version.
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: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140513/397a9394/attachment.sig>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 6/8] usb: ohci-platform: Enable optional use of reset controller
2014-05-12 19:34 [PATCH v3 0/8] Add Allwinner A31 USB support Maxime Ripard
` (4 preceding siblings ...)
2014-05-12 19:34 ` [PATCH v3 5/8] usb: ehci-platform: add optional reset controller retrieval Maxime Ripard
@ 2014-05-12 19:34 ` Maxime Ripard
2014-05-12 19:34 ` [PATCH v3 7/8] ARM: sun6i: dt: Add support for the USB controllers Maxime Ripard
2014-05-12 19:34 ` [PATCH v3 8/8] ARM: sunxi: dt: add APP4-EVB1 board support Maxime Ripard
7 siblings, 0 replies; 13+ messages in thread
From: Maxime Ripard @ 2014-05-12 19:34 UTC (permalink / raw)
To: linux-arm-kernel
The OHCI controllers used in the Allwinner A31 are asserted in reset using a
global reset controller.
Add optional support for such a controller in the OHCI platform driver.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
Documentation/devicetree/bindings/usb/usb-ohci.txt | 1 +
drivers/usb/host/ohci-platform.c | 18 ++++++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt
index 45f67d91e888..b968a1aea995 100644
--- a/Documentation/devicetree/bindings/usb/usb-ohci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
@@ -12,6 +12,7 @@ Optional properties:
- clocks : a list of phandle + clock specifier pairs
- phys : phandle + phy specifier pair
- phy-names : "usb"
+- resets : phandle + reset specifier pair
Example:
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index b6002c951c5c..806dbebdc1d4 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -24,6 +24,7 @@
#include <linux/err.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
+#include <linux/reset.h>
#include <linux/usb/ohci_pdriver.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
@@ -36,6 +37,7 @@
struct ohci_platform_priv {
struct clk *clks[OHCI_MAX_CLKS];
+ struct reset_control *rst;
struct phy *phy;
};
@@ -191,6 +193,19 @@ static int ohci_platform_probe(struct platform_device *dev)
break;
}
}
+
+ }
+
+ priv->rst = devm_reset_control_get_optional(&dev->dev, NULL);
+ if (IS_ERR(priv->rst)) {
+ err = PTR_ERR(priv->rst);
+ if (err == -EPROBE_DEFER)
+ goto err_put_clks;
+ priv->rst = NULL;
+ } else {
+ err = reset_control_deassert(priv->rst);
+ if (err)
+ goto err_put_clks;
}
if (pdata->big_endian_desc)
@@ -266,6 +281,9 @@ static int ohci_platform_remove(struct platform_device *dev)
if (pdata->power_off)
pdata->power_off(dev);
+ if (priv->rst)
+ reset_control_assert(priv->rst);
+
for (clk = 0; clk < OHCI_MAX_CLKS && priv->clks[clk]; clk++)
clk_put(priv->clks[clk]);
--
1.9.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v3 7/8] ARM: sun6i: dt: Add support for the USB controllers
2014-05-12 19:34 [PATCH v3 0/8] Add Allwinner A31 USB support Maxime Ripard
` (5 preceding siblings ...)
2014-05-12 19:34 ` [PATCH v3 6/8] usb: ohci-platform: Enable optional use of reset controller Maxime Ripard
@ 2014-05-12 19:34 ` Maxime Ripard
2014-05-12 19:34 ` [PATCH v3 8/8] ARM: sunxi: dt: add APP4-EVB1 board support Maxime Ripard
7 siblings, 0 replies; 13+ messages in thread
From: Maxime Ripard @ 2014-05-12 19:34 UTC (permalink / raw)
To: linux-arm-kernel
The A31 has two ECHI/OHCI controllers, and one OHCI-only phy-less controller.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/sun6i-a31.dtsi | 77 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 77 insertions(+)
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index 13aa56ed5858..5e9f01af6d99 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -341,6 +341,83 @@
status = "disabled";
};
+ usbphy: phy at 01c19400 {
+ compatible = "allwinner,sun6i-a31-usb-phy";
+ reg = <0x01c19400 0x10>,
+ <0x01c1a800 0x4>,
+ <0x01c1b800 0x4>;
+ reg-names = "phy_ctrl",
+ "pmu1",
+ "pmu2";
+ clocks = <&usb_clk 8>,
+ <&usb_clk 9>,
+ <&usb_clk 10>;
+ clock-names = "usb0_phy",
+ "usb1_phy",
+ "usb2_phy";
+ resets = <&usb_clk 0>,
+ <&usb_clk 1>,
+ <&usb_clk 2>;
+ reset-names = "usb0_reset",
+ "usb1_reset",
+ "usb2_reset";
+ status = "disabled";
+ #phy-cells = <1>;
+ };
+
+ ehci0: usb at 01c1a000 {
+ compatible = "allwinner,sun6i-a31-ehci", "generic-ehci";
+ reg = <0x01c1a000 0x100>;
+ interrupts = <0 72 4>;
+ clocks = <&ahb1_gates 26>;
+ resets = <&ahb1_rst 26>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci0: usb at 01c1a400 {
+ compatible = "allwinner,sun6i-a31-ohci", "generic-ohci";
+ reg = <0x01c1a400 0x100>;
+ interrupts = <0 73 4>;
+ clocks = <&ahb1_gates 29>, <&usb_clk 16>;
+ resets = <&ahb1_rst 29>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ehci1: usb at 01c1b000 {
+ compatible = "allwinner,sun6i-a31-ehci", "generic-ehci";
+ reg = <0x01c1b000 0x100>;
+ interrupts = <0 74 4>;
+ clocks = <&ahb1_gates 27>;
+ resets = <&ahb1_rst 27>;
+ phys = <&usbphy 2>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci1: usb at 01c1b400 {
+ compatible = "allwinner,sun6i-a31-ohci", "generic-ohci";
+ reg = <0x01c1b400 0x100>;
+ interrupts = <0 75 4>;
+ clocks = <&ahb1_gates 30>, <&usb_clk 17>;
+ resets = <&ahb1_rst 30>;
+ phys = <&usbphy 2>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci2: usb at 01c1c000 {
+ compatible = "allwinner,sun6i-a31-ohci", "generic-ohci";
+ reg = <0x01c1c400 0x100>;
+ interrupts = <0 77 4>;
+ clocks = <&ahb1_gates 31>, <&usb_clk 18>;
+ resets = <&ahb1_rst 31>;
+ status = "disabled";
+ };
+
pio: pinctrl at 01c20800 {
compatible = "allwinner,sun6i-a31-pinctrl";
reg = <0x01c20800 0x400>;
--
1.9.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v3 8/8] ARM: sunxi: dt: add APP4-EVB1 board support
2014-05-12 19:34 [PATCH v3 0/8] Add Allwinner A31 USB support Maxime Ripard
` (6 preceding siblings ...)
2014-05-12 19:34 ` [PATCH v3 7/8] ARM: sun6i: dt: Add support for the USB controllers Maxime Ripard
@ 2014-05-12 19:34 ` Maxime Ripard
7 siblings, 0 replies; 13+ messages in thread
From: Maxime Ripard @ 2014-05-12 19:34 UTC (permalink / raw)
To: linux-arm-kernel
From: Boris BREZILLON <boris.brezillon@free-electrons.com>
The APP4 EVB1 development boards embeds an A31, together with some NAND, one SD
card slot, and one SDIO + UART WiFi and Bluetooth chip, a few I2C buses, USB,
and a LCD display.
Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/sun6i-a31-app4-evb1.dts | 57 +++++++++++++++++++++++++++++++
2 files changed, 58 insertions(+)
create mode 100644 arch/arm/boot/dts/sun6i-a31-app4-evb1.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 8bc808cb7ce2..1d9c50dda655 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -344,6 +344,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += \
sun5i-a10s-r7-tv-dongle.dtb \
sun5i-a13-olinuxino.dtb \
sun5i-a13-olinuxino-micro.dtb \
+ sun6i-a31-app4-evb1.dtb \
sun6i-a31-colombus.dtb \
sun6i-a31-m9.dtb \
sun7i-a20-cubieboard2.dtb \
diff --git a/arch/arm/boot/dts/sun6i-a31-app4-evb1.dts b/arch/arm/boot/dts/sun6i-a31-app4-evb1.dts
new file mode 100644
index 000000000000..2bbf8867362b
--- /dev/null
+++ b/arch/arm/boot/dts/sun6i-a31-app4-evb1.dts
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2014 Boris Brezillon
+ *
+ * Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * 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
+ */
+
+/dts-v1/;
+/include/ "sun6i-a31.dtsi"
+/include/ "sunxi-common-regulators.dtsi"
+
+/ {
+ model = "Allwinner A31 APP4 EVB1 Evaluation Board";
+ compatible = "allwinner,app4-evb1", "allwinner,sun6i-a31";
+
+ chosen {
+ bootargs = "earlyprintk console=ttyS0,115200";
+ };
+
+ soc at 01c00000 {
+ pio: pinctrl at 01c20800 {
+ usb1_vbus_pin_a: usb1_vbus_pin at 0 {
+ allwinner,pins = "PH27";
+ allwinner,function = "gpio_out";
+ allwinner,drive = <0>;
+ allwinner,pull = <0>;
+ };
+ };
+
+ usbphy: phy at 01c19400 {
+ usb1_vbus-supply = <®_usb1_vbus>;
+ status = "okay";
+ };
+
+ ehci0: usb at 01c1a000 {
+ status = "okay";
+ };
+
+ uart0: serial at 01c28000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+ };
+ };
+
+ reg_usb1_vbus: usb1-vbus {
+ pinctrl-0 = <&usb1_vbus_pin_a>;
+ gpio = <&pio 7 27 0>;
+ status = "okay";
+ };
+};
--
1.9.3
^ permalink raw reply related [flat|nested] 13+ messages in thread