Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1200079 > unrolled thread
| Started by | Kishon Vijay Abraham I <kishon@ti.com> |
|---|---|
| First post | 2015-08-04 17:30 +0200 |
| Last post | 2015-08-04 17:30 +0200 |
| Articles | 5 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH 0/7] phy: use syscon framework APIs to set ctrl mod reg Kishon Vijay Abraham I <kishon@ti.com> - 2015-08-04 17:30 +0200
[PATCH 7/7] phy: omap-usb2: use *syscon* framework API to power on/off the PHY Kishon Vijay Abraham I <kishon@ti.com> - 2015-08-04 17:30 +0200
Re: [PATCH 7/7] phy: omap-usb2: use *syscon* framework API to power on/off the PHY Roger Quadros <rogerq@ti.com> - 2015-08-05 10:40 +0200
Re: [PATCH 7/7] phy: omap-usb2: use *syscon* framework API to power on/off the PHY Kishon Vijay Abraham I <kishon@ti.com> - 2015-08-05 16:30 +0200
[PATCH 3/7] phy: ti-pipe3: use *syscon* framework API to power on/off the PHY Kishon Vijay Abraham I <kishon@ti.com> - 2015-08-04 17:30 +0200
| From | Kishon Vijay Abraham I <kishon@ti.com> |
|---|---|
| Date | 2015-08-04 17:30 +0200 |
| Subject | [PATCH 0/7] phy: use syscon framework APIs to set ctrl mod reg |
| Message-ID | <pTMk9-65J-3@gated-at.bofh.it> |
This series is split from [1] to include only the PHY patches.
This series is basically to deprecate using phy-omap-control and use
syscon APIs to program the control module registers.
Changes from [1] in PHY patches include
*) cleanup ti_pipe3_probe
*) have mask, power_on and power_off values in usb_phy_data for
omap-usb2 phy
Did basic enumeration testing in the below platforms.
*) Tested PCIe, SATA and USB in dra7
*) Tested SATA and USB in omap5
*) Tested USB(dwc3) in am43xx_evm
*) Tested USB(musb) in omap4 panda after including [2]
All the testing was done both before applying the dt patches and after
applying the dt patches (dt patches will be posted shortly).
[1] -> https://lkml.org/lkml/2015/6/23/189
[2] -> http://permalink.gmane.org/gmane.linux.kernel/2012427
Kishon Vijay Abraham I (7):
phy: ti-pipe3: cleanup ti_pipe3_probe()
phy: ti-pipe3: use ti_pipe3_power_off to power off the PHY during
probe
phy: ti-pipe3: use *syscon* framework API to power on/off the PHY
phy: ti-pipe3: use *syscon* framework API to set PCS value of the PHY
phy: omap-usb2: use omap_usb_power_off to power off the PHY during
probe
phy: omap-usb2: Add a new compatible string for USB2 PHY2
phy: omap-usb2: use *syscon* framework API to power on/off the PHY
Documentation/devicetree/bindings/phy/ti-phy.txt | 20 +-
drivers/phy/phy-omap-usb2.c | 96 ++++++--
drivers/phy/phy-ti-pipe3.c | 283 ++++++++++++++++------
include/linux/phy/omap_usb.h | 23 ++
4 files changed, 329 insertions(+), 93 deletions(-)
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Kishon Vijay Abraham I <kishon@ti.com> |
|---|---|
| Date | 2015-08-04 17:30 +0200 |
| Subject | [PATCH 7/7] phy: omap-usb2: use *syscon* framework API to power on/off the PHY |
| Message-ID | <pTMkb-65J-33@gated-at.bofh.it> |
| In reply to | #1200079 |
Deprecate using phy-omap-control driver to power on/off the PHY,
and use *syscon* framework to do the same. This handles
powering on/off the PHY for the USB2 PHYs used in various TI SoCs.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
Documentation/devicetree/bindings/phy/ti-phy.txt | 6 +-
drivers/phy/phy-omap-usb2.c | 85 +++++++++++++++++-----
include/linux/phy/omap_usb.h | 23 ++++++
3 files changed, 96 insertions(+), 18 deletions(-)
diff --git a/Documentation/devicetree/bindings/phy/ti-phy.txt b/Documentation/devicetree/bindings/phy/ti-phy.txt
index a061077..a3b3945 100644
--- a/Documentation/devicetree/bindings/phy/ti-phy.txt
+++ b/Documentation/devicetree/bindings/phy/ti-phy.txt
@@ -42,10 +42,14 @@ Required properties:
* "wkupclk" - wakeup clock.
* "refclk" - reference clock (optional).
-Optional properties:
+Deprecated properties:
- ctrl-module : phandle of the control module used by PHY driver to power on
the PHY.
+Recommended properies:
+- syscon-phy-power : phandle/offset pair. Phandle to the system control
+ module and the register offset to power on/off the PHY.
+
This is usually a subnode of ocp2scp to which it is connected.
usb2phy@4a0ad080 {
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
index 2f7220f..531fe04 100644
--- a/drivers/phy/phy-omap-usb2.c
+++ b/drivers/phy/phy-omap-usb2.c
@@ -29,6 +29,8 @@
#include <linux/delay.h>
#include <linux/phy/omap_control_phy.h>
#include <linux/phy/phy.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
#include <linux/of_platform.h>
#define USB2PHY_DISCON_BYP_LATCH (1 << 31)
@@ -97,22 +99,40 @@ static int omap_usb_set_peripheral(struct usb_otg *otg,
return 0;
}
-static int omap_usb_power_off(struct phy *x)
+static int omap_usb_phy_power(struct omap_usb *phy, int on)
{
- struct omap_usb *phy = phy_get_drvdata(x);
+ u32 val = 0;
+ int ret;
- omap_control_phy_power(phy->control_dev, 0);
+ if (phy->syscon_phy_power) {
+ if (on)
+ val = phy->power_on;
+ else
+ val = phy->power_off;
+
+ ret = regmap_update_bits(phy->syscon_phy_power, phy->power_reg,
+ phy->mask, val);
+ if (ret < 0)
+ return ret;
+ } else {
+ omap_control_phy_power(phy->control_dev, on);
+ }
return 0;
}
-static int omap_usb_power_on(struct phy *x)
+static int omap_usb_power_off(struct phy *x)
{
struct omap_usb *phy = phy_get_drvdata(x);
- omap_control_phy_power(phy->control_dev, 1);
+ return omap_usb_phy_power(phy, false);
+}
- return 0;
+static int omap_usb_power_on(struct phy *x)
+{
+ struct omap_usb *phy = phy_get_drvdata(x);
+
+ return omap_usb_phy_power(phy, true);
}
static int omap_usb_init(struct phy *x)
@@ -147,26 +167,38 @@ static struct phy_ops ops = {
static const struct usb_phy_data omap_usb2_data = {
.label = "omap_usb2",
.flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS,
+ .mask = OMAP_DEV_PHY_PD,
+ .power_off = OMAP_DEV_PHY_PD,
};
static const struct usb_phy_data omap5_usb2_data = {
.label = "omap5_usb2",
.flags = 0,
+ .mask = OMAP_DEV_PHY_PD,
+ .power_off = OMAP_DEV_PHY_PD,
};
static const struct usb_phy_data dra7x_usb2_data = {
.label = "dra7x_usb2",
.flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
+ .mask = OMAP_DEV_PHY_PD,
+ .power_off = OMAP_DEV_PHY_PD,
};
static const struct usb_phy_data dra7x_usb2_phy2_data = {
.label = "dra7x_usb2_phy2",
.flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
+ .mask = OMAP_USB2_PHY_PD,
+ .power_off = OMAP_USB2_PHY_PD,
};
static const struct usb_phy_data am437x_usb2_data = {
.label = "am437x_usb2",
.flags = 0,
+ .mask = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD |
+ AM437X_USB2_OTGVDET_EN | AM437X_USB2_OTGSESSEND_EN,
+ .power_on = AM437X_USB2_OTGVDET_EN | AM437X_USB2_OTGSESSEND_EN,
+ .power_off = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD,
};
static const struct of_device_id omap_usb2_id_table[] = {
@@ -228,6 +260,9 @@ static int omap_usb2_probe(struct platform_device *pdev)
phy->phy.label = phy_data->label;
phy->phy.otg = otg;
phy->phy.type = USB_PHY_TYPE_USB2;
+ phy->mask = phy_data->mask;
+ phy->power_on = phy_data->power_on;
+ phy->power_off = phy_data->power_off;
if (phy_data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -237,20 +272,36 @@ static int omap_usb2_probe(struct platform_device *pdev)
phy->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT;
}
- control_node = of_parse_phandle(node, "ctrl-module", 0);
- if (!control_node) {
- dev_err(&pdev->dev, "Failed to get control device phandle\n");
- return -EINVAL;
- }
+ phy->syscon_phy_power = syscon_regmap_lookup_by_phandle(node,
+ "syscon-phy-power");
+ if (IS_ERR(phy->syscon_phy_power)) {
+ dev_info(&pdev->dev,
+ "can't get syscon-phy-power, using control device\n");
+ phy->syscon_phy_power = NULL;
+
+ control_node = of_parse_phandle(node, "ctrl-module", 0);
+ if (!control_node) {
+ dev_err(&pdev->dev,
+ "Failed to get control device phandle\n");
+ return -EINVAL;
+ }
- control_pdev = of_find_device_by_node(control_node);
- if (!control_pdev) {
- dev_err(&pdev->dev, "Failed to get control device\n");
- return -EINVAL;
+ control_pdev = of_find_device_by_node(control_node);
+ if (!control_pdev) {
+ dev_err(&pdev->dev, "Failed to get control device\n");
+ return -EINVAL;
+ }
+ phy->control_dev = &control_pdev->dev;
+ } else {
+ if (of_property_read_u32_index(node,
+ "syscon-phy-power", 1,
+ &phy->power_reg)) {
+ dev_err(&pdev->dev,
+ "couldn't get power reg. offset\n");
+ return -EINVAL;
+ }
}
- phy->control_dev = &control_pdev->dev;
-
otg->set_host = omap_usb_set_host;
otg->set_peripheral = omap_usb_set_peripheral;
if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS)
diff --git a/include/linux/phy/omap_usb.h b/include/linux/phy/omap_usb.h
index dc2c541..2e5fb87 100644
--- a/include/linux/phy/omap_usb.h
+++ b/include/linux/phy/omap_usb.h
@@ -30,6 +30,12 @@ struct usb_dpll_params {
u32 mf;
};
+enum omap_usb_phy_type {
+ TYPE_USB2, /* USB2_PHY, power down in CONTROL_DEV_CONF */
+ TYPE_DRA7USB2, /* USB2 PHY, power and power_aux e.g. DRA7 */
+ TYPE_AM437USB2, /* USB2 PHY, power e.g. AM437x */
+};
+
struct omap_usb {
struct usb_phy phy;
struct phy_companion *comparator;
@@ -40,11 +46,20 @@ struct omap_usb {
struct clk *wkupclk;
struct clk *optclk;
u8 flags;
+ enum omap_usb_phy_type type;
+ struct regmap *syscon_phy_power; /* ctrl. reg. acces */
+ unsigned int power_reg; /* power reg. index within syscon */
+ u32 mask;
+ u32 power_on;
+ u32 power_off;
};
struct usb_phy_data {
const char *label;
u8 flags;
+ u32 mask;
+ u32 power_on;
+ u32 power_off;
};
/* Driver Flags */
@@ -52,6 +67,14 @@ struct usb_phy_data {
#define OMAP_USB2_HAS_SET_VBUS (1 << 1)
#define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT (1 << 2)
+#define OMAP_DEV_PHY_PD BIT(0)
+#define OMAP_USB2_PHY_PD BIT(28)
+
+#define AM437X_USB2_PHY_PD BIT(0)
+#define AM437X_USB2_OTG_PD BIT(1)
+#define AM437X_USB2_OTGVDET_EN BIT(19)
+#define AM437X_USB2_OTGSESSEND_EN BIT(20)
+
#define phy_to_omapusb(x) container_of((x), struct omap_usb, phy)
#if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE)
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Roger Quadros <rogerq@ti.com> |
|---|---|
| Date | 2015-08-05 10:40 +0200 |
| Subject | Re: [PATCH 7/7] phy: omap-usb2: use *syscon* framework API to power on/off the PHY |
| Message-ID | <pU2oV-4nL-3@gated-at.bofh.it> |
| In reply to | #1200082 |
On 04/08/15 18:20, Kishon Vijay Abraham I wrote:
> Deprecate using phy-omap-control driver to power on/off the PHY,
> and use *syscon* framework to do the same. This handles
> powering on/off the PHY for the USB2 PHYs used in various TI SoCs.
>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---
> Documentation/devicetree/bindings/phy/ti-phy.txt | 6 +-
> drivers/phy/phy-omap-usb2.c | 85 +++++++++++++++++-----
> include/linux/phy/omap_usb.h | 23 ++++++
> 3 files changed, 96 insertions(+), 18 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/phy/ti-phy.txt b/Documentation/devicetree/bindings/phy/ti-phy.txt
> index a061077..a3b3945 100644
> --- a/Documentation/devicetree/bindings/phy/ti-phy.txt
> +++ b/Documentation/devicetree/bindings/phy/ti-phy.txt
> @@ -42,10 +42,14 @@ Required properties:
> * "wkupclk" - wakeup clock.
> * "refclk" - reference clock (optional).
>
> -Optional properties:
> +Deprecated properties:
> - ctrl-module : phandle of the control module used by PHY driver to power on
> the PHY.
>
> +Recommended properies:
> +- syscon-phy-power : phandle/offset pair. Phandle to the system control
> + module and the register offset to power on/off the PHY.
> +
> This is usually a subnode of ocp2scp to which it is connected.
>
> usb2phy@4a0ad080 {
> diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
> index 2f7220f..531fe04 100644
> --- a/drivers/phy/phy-omap-usb2.c
> +++ b/drivers/phy/phy-omap-usb2.c
> @@ -29,6 +29,8 @@
> #include <linux/delay.h>
> #include <linux/phy/omap_control_phy.h>
> #include <linux/phy/phy.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> #include <linux/of_platform.h>
>
> #define USB2PHY_DISCON_BYP_LATCH (1 << 31)
> @@ -97,22 +99,40 @@ static int omap_usb_set_peripheral(struct usb_otg *otg,
> return 0;
> }
>
> -static int omap_usb_power_off(struct phy *x)
> +static int omap_usb_phy_power(struct omap_usb *phy, int on)
> {
> - struct omap_usb *phy = phy_get_drvdata(x);
> + u32 val = 0;
No need to initialize val.
> + int ret;
>
> - omap_control_phy_power(phy->control_dev, 0);
> + if (phy->syscon_phy_power) {
> + if (on)
> + val = phy->power_on;
> + else
> + val = phy->power_off;
> +
> + ret = regmap_update_bits(phy->syscon_phy_power, phy->power_reg,
> + phy->mask, val);
> + if (ret < 0)
> + return ret;
> + } else {
> + omap_control_phy_power(phy->control_dev, on);
> + }
>
> return 0;
> }
>
> -static int omap_usb_power_on(struct phy *x)
> +static int omap_usb_power_off(struct phy *x)
> {
> struct omap_usb *phy = phy_get_drvdata(x);
>
> - omap_control_phy_power(phy->control_dev, 1);
> + return omap_usb_phy_power(phy, false);
> +}
>
> - return 0;
> +static int omap_usb_power_on(struct phy *x)
> +{
> + struct omap_usb *phy = phy_get_drvdata(x);
> +
> + return omap_usb_phy_power(phy, true);
> }
>
> static int omap_usb_init(struct phy *x)
> @@ -147,26 +167,38 @@ static struct phy_ops ops = {
> static const struct usb_phy_data omap_usb2_data = {
> .label = "omap_usb2",
> .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS,
> + .mask = OMAP_DEV_PHY_PD,
> + .power_off = OMAP_DEV_PHY_PD,
> };
>
> static const struct usb_phy_data omap5_usb2_data = {
> .label = "omap5_usb2",
> .flags = 0,
> + .mask = OMAP_DEV_PHY_PD,
> + .power_off = OMAP_DEV_PHY_PD,
> };
>
> static const struct usb_phy_data dra7x_usb2_data = {
> .label = "dra7x_usb2",
> .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
> + .mask = OMAP_DEV_PHY_PD,
> + .power_off = OMAP_DEV_PHY_PD,
> };
>
> static const struct usb_phy_data dra7x_usb2_phy2_data = {
> .label = "dra7x_usb2_phy2",
> .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
> + .mask = OMAP_USB2_PHY_PD,
> + .power_off = OMAP_USB2_PHY_PD,
> };
>
> static const struct usb_phy_data am437x_usb2_data = {
> .label = "am437x_usb2",
> .flags = 0,
> + .mask = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD |
> + AM437X_USB2_OTGVDET_EN | AM437X_USB2_OTGSESSEND_EN,
> + .power_on = AM437X_USB2_OTGVDET_EN | AM437X_USB2_OTGSESSEND_EN,
> + .power_off = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD,
We're combining some OTG operations with PHY on/off. This is probably OK
for now but looks like we need a OTG phy driver for this?
> };
>
> static const struct of_device_id omap_usb2_id_table[] = {
> @@ -228,6 +260,9 @@ static int omap_usb2_probe(struct platform_device *pdev)
> phy->phy.label = phy_data->label;
> phy->phy.otg = otg;
> phy->phy.type = USB_PHY_TYPE_USB2;
> + phy->mask = phy_data->mask;
> + phy->power_on = phy_data->power_on;
> + phy->power_off = phy_data->power_off;
>
> if (phy_data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> @@ -237,20 +272,36 @@ static int omap_usb2_probe(struct platform_device *pdev)
> phy->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT;
> }
>
> - control_node = of_parse_phandle(node, "ctrl-module", 0);
> - if (!control_node) {
> - dev_err(&pdev->dev, "Failed to get control device phandle\n");
> - return -EINVAL;
> - }
> + phy->syscon_phy_power = syscon_regmap_lookup_by_phandle(node,
> + "syscon-phy-power");
> + if (IS_ERR(phy->syscon_phy_power)) {
> + dev_info(&pdev->dev,
> + "can't get syscon-phy-power, using control device\n");
dev_dbg()?
> + phy->syscon_phy_power = NULL;
> +
> + control_node = of_parse_phandle(node, "ctrl-module", 0);
> + if (!control_node) {
> + dev_err(&pdev->dev,
> + "Failed to get control device phandle\n");
> + return -EINVAL;
> + }
>
> - control_pdev = of_find_device_by_node(control_node);
> - if (!control_pdev) {
> - dev_err(&pdev->dev, "Failed to get control device\n");
> - return -EINVAL;
> + control_pdev = of_find_device_by_node(control_node);
> + if (!control_pdev) {
> + dev_err(&pdev->dev, "Failed to get control device\n");
> + return -EINVAL;
> + }
> + phy->control_dev = &control_pdev->dev;
> + } else {
> + if (of_property_read_u32_index(node,
> + "syscon-phy-power", 1,
> + &phy->power_reg)) {
> + dev_err(&pdev->dev,
> + "couldn't get power reg. offset\n");
> + return -EINVAL;
> + }
> }
>
> - phy->control_dev = &control_pdev->dev;
> -
> otg->set_host = omap_usb_set_host;
> otg->set_peripheral = omap_usb_set_peripheral;
> if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS)
> diff --git a/include/linux/phy/omap_usb.h b/include/linux/phy/omap_usb.h
> index dc2c541..2e5fb87 100644
> --- a/include/linux/phy/omap_usb.h
> +++ b/include/linux/phy/omap_usb.h
> @@ -30,6 +30,12 @@ struct usb_dpll_params {
> u32 mf;
> };
>
> +enum omap_usb_phy_type {
> + TYPE_USB2, /* USB2_PHY, power down in CONTROL_DEV_CONF */
> + TYPE_DRA7USB2, /* USB2 PHY, power and power_aux e.g. DRA7 */
> + TYPE_AM437USB2, /* USB2 PHY, power e.g. AM437x */
> +};
> +
> struct omap_usb {
> struct usb_phy phy;
> struct phy_companion *comparator;
> @@ -40,11 +46,20 @@ struct omap_usb {
> struct clk *wkupclk;
> struct clk *optclk;
> u8 flags;
> + enum omap_usb_phy_type type;
> + struct regmap *syscon_phy_power; /* ctrl. reg. acces */
> + unsigned int power_reg; /* power reg. index within syscon */
> + u32 mask;
> + u32 power_on;
> + u32 power_off;
> };
>
> struct usb_phy_data {
> const char *label;
> u8 flags;
> + u32 mask;
> + u32 power_on;
> + u32 power_off;
> };
>
> /* Driver Flags */
> @@ -52,6 +67,14 @@ struct usb_phy_data {
> #define OMAP_USB2_HAS_SET_VBUS (1 << 1)
> #define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT (1 << 2)
>
> +#define OMAP_DEV_PHY_PD BIT(0)
> +#define OMAP_USB2_PHY_PD BIT(28)
> +
> +#define AM437X_USB2_PHY_PD BIT(0)
> +#define AM437X_USB2_OTG_PD BIT(1)
> +#define AM437X_USB2_OTGVDET_EN BIT(19)
> +#define AM437X_USB2_OTGSESSEND_EN BIT(20)
> +
Is all this used by anyone other than the phy driver?
If not we should move whatever possible into the .c file.
Could be a separate patch of course.
> #define phy_to_omapusb(x) container_of((x), struct omap_usb, phy)
>
> #if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE)
>
cheers,
-roger
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Kishon Vijay Abraham I <kishon@ti.com> |
|---|---|
| Date | 2015-08-05 16:30 +0200 |
| Subject | Re: [PATCH 7/7] phy: omap-usb2: use *syscon* framework API to power on/off the PHY |
| Message-ID | <pU7RD-3W5-1@gated-at.bofh.it> |
| In reply to | #1200532 |
Hi,
On Wednesday 05 August 2015 02:05 PM, Roger Quadros wrote:
> On 04/08/15 18:20, Kishon Vijay Abraham I wrote:
>> Deprecate using phy-omap-control driver to power on/off the PHY,
>> and use *syscon* framework to do the same. This handles
>> powering on/off the PHY for the USB2 PHYs used in various TI SoCs.
>>
>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>> ---
>> Documentation/devicetree/bindings/phy/ti-phy.txt | 6 +-
>> drivers/phy/phy-omap-usb2.c | 85 +++++++++++++++++-----
>> include/linux/phy/omap_usb.h | 23 ++++++
>> 3 files changed, 96 insertions(+), 18 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/phy/ti-phy.txt b/Documentation/devicetree/bindings/phy/ti-phy.txt
>> index a061077..a3b3945 100644
>> --- a/Documentation/devicetree/bindings/phy/ti-phy.txt
>> +++ b/Documentation/devicetree/bindings/phy/ti-phy.txt
>> @@ -42,10 +42,14 @@ Required properties:
>> * "wkupclk" - wakeup clock.
>> * "refclk" - reference clock (optional).
>>
>> -Optional properties:
>> +Deprecated properties:
>> - ctrl-module : phandle of the control module used by PHY driver to power on
>> the PHY.
>>
>> +Recommended properies:
>> +- syscon-phy-power : phandle/offset pair. Phandle to the system control
>> + module and the register offset to power on/off the PHY.
>> +
>> This is usually a subnode of ocp2scp to which it is connected.
>>
>> usb2phy@4a0ad080 {
>> diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
>> index 2f7220f..531fe04 100644
>> --- a/drivers/phy/phy-omap-usb2.c
>> +++ b/drivers/phy/phy-omap-usb2.c
>> @@ -29,6 +29,8 @@
>> #include <linux/delay.h>
>> #include <linux/phy/omap_control_phy.h>
>> #include <linux/phy/phy.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/regmap.h>
>> #include <linux/of_platform.h>
>>
>> #define USB2PHY_DISCON_BYP_LATCH (1 << 31)
>> @@ -97,22 +99,40 @@ static int omap_usb_set_peripheral(struct usb_otg *otg,
>> return 0;
>> }
>>
>> -static int omap_usb_power_off(struct phy *x)
>> +static int omap_usb_phy_power(struct omap_usb *phy, int on)
>> {
>> - struct omap_usb *phy = phy_get_drvdata(x);
>> + u32 val = 0;
>
> No need to initialize val.
indeed.
>
>> + int ret;
>>
>> - omap_control_phy_power(phy->control_dev, 0);
>> + if (phy->syscon_phy_power) {
>> + if (on)
>> + val = phy->power_on;
>> + else
>> + val = phy->power_off;
>> +
>> + ret = regmap_update_bits(phy->syscon_phy_power, phy->power_reg,
>> + phy->mask, val);
>> + if (ret < 0)
>> + return ret;
>> + } else {
>> + omap_control_phy_power(phy->control_dev, on);
>> + }
>>
>> return 0;
>> }
>>
>> -static int omap_usb_power_on(struct phy *x)
>> +static int omap_usb_power_off(struct phy *x)
>> {
>> struct omap_usb *phy = phy_get_drvdata(x);
>>
>> - omap_control_phy_power(phy->control_dev, 1);
>> + return omap_usb_phy_power(phy, false);
>> +}
>>
>> - return 0;
>> +static int omap_usb_power_on(struct phy *x)
>> +{
>> + struct omap_usb *phy = phy_get_drvdata(x);
>> +
>> + return omap_usb_phy_power(phy, true);
>> }
>>
>> static int omap_usb_init(struct phy *x)
>> @@ -147,26 +167,38 @@ static struct phy_ops ops = {
>> static const struct usb_phy_data omap_usb2_data = {
>> .label = "omap_usb2",
>> .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS,
>> + .mask = OMAP_DEV_PHY_PD,
>> + .power_off = OMAP_DEV_PHY_PD,
>> };
>>
>> static const struct usb_phy_data omap5_usb2_data = {
>> .label = "omap5_usb2",
>> .flags = 0,
>> + .mask = OMAP_DEV_PHY_PD,
>> + .power_off = OMAP_DEV_PHY_PD,
>> };
>>
>> static const struct usb_phy_data dra7x_usb2_data = {
>> .label = "dra7x_usb2",
>> .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
>> + .mask = OMAP_DEV_PHY_PD,
>> + .power_off = OMAP_DEV_PHY_PD,
>> };
>>
>> static const struct usb_phy_data dra7x_usb2_phy2_data = {
>> .label = "dra7x_usb2_phy2",
>> .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
>> + .mask = OMAP_USB2_PHY_PD,
>> + .power_off = OMAP_USB2_PHY_PD,
>> };
>>
>> static const struct usb_phy_data am437x_usb2_data = {
>> .label = "am437x_usb2",
>> .flags = 0,
>> + .mask = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD |
>> + AM437X_USB2_OTGVDET_EN | AM437X_USB2_OTGSESSEND_EN,
>> + .power_on = AM437X_USB2_OTGVDET_EN | AM437X_USB2_OTGSESSEND_EN,
>> + .power_off = AM437X_USB2_PHY_PD | AM437X_USB2_OTG_PD,
>
> We're combining some OTG operations with PHY on/off. This is probably OK
> for now but looks like we need a OTG phy driver for this?
Yes. Once we have that we can stop using the USB PHY library from this driver.
>
>> };
>>
>> static const struct of_device_id omap_usb2_id_table[] = {
>> @@ -228,6 +260,9 @@ static int omap_usb2_probe(struct platform_device *pdev)
>> phy->phy.label = phy_data->label;
>> phy->phy.otg = otg;
>> phy->phy.type = USB_PHY_TYPE_USB2;
>> + phy->mask = phy_data->mask;
>> + phy->power_on = phy_data->power_on;
>> + phy->power_off = phy_data->power_off;
>>
>> if (phy_data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
>> res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> @@ -237,20 +272,36 @@ static int omap_usb2_probe(struct platform_device *pdev)
>> phy->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT;
>> }
>>
>> - control_node = of_parse_phandle(node, "ctrl-module", 0);
>> - if (!control_node) {
>> - dev_err(&pdev->dev, "Failed to get control device phandle\n");
>> - return -EINVAL;
>> - }
>> + phy->syscon_phy_power = syscon_regmap_lookup_by_phandle(node,
>> + "syscon-phy-power");
>> + if (IS_ERR(phy->syscon_phy_power)) {
>> + dev_info(&pdev->dev,
>> + "can't get syscon-phy-power, using control device\n");
>
> dev_dbg()?
okay.
>
>> + phy->syscon_phy_power = NULL;
>> +
>> + control_node = of_parse_phandle(node, "ctrl-module", 0);
>> + if (!control_node) {
>> + dev_err(&pdev->dev,
>> + "Failed to get control device phandle\n");
>> + return -EINVAL;
>> + }
>>
>> - control_pdev = of_find_device_by_node(control_node);
>> - if (!control_pdev) {
>> - dev_err(&pdev->dev, "Failed to get control device\n");
>> - return -EINVAL;
>> + control_pdev = of_find_device_by_node(control_node);
>> + if (!control_pdev) {
>> + dev_err(&pdev->dev, "Failed to get control device\n");
>> + return -EINVAL;
>> + }
>> + phy->control_dev = &control_pdev->dev;
>> + } else {
>> + if (of_property_read_u32_index(node,
>> + "syscon-phy-power", 1,
>> + &phy->power_reg)) {
>> + dev_err(&pdev->dev,
>> + "couldn't get power reg. offset\n");
>> + return -EINVAL;
>> + }
>> }
>>
>> - phy->control_dev = &control_pdev->dev;
>> -
>> otg->set_host = omap_usb_set_host;
>> otg->set_peripheral = omap_usb_set_peripheral;
>> if (phy_data->flags & OMAP_USB2_HAS_SET_VBUS)
>> diff --git a/include/linux/phy/omap_usb.h b/include/linux/phy/omap_usb.h
>> index dc2c541..2e5fb87 100644
>> --- a/include/linux/phy/omap_usb.h
>> +++ b/include/linux/phy/omap_usb.h
>> @@ -30,6 +30,12 @@ struct usb_dpll_params {
>> u32 mf;
>> };
>>
>> +enum omap_usb_phy_type {
>> + TYPE_USB2, /* USB2_PHY, power down in CONTROL_DEV_CONF */
>> + TYPE_DRA7USB2, /* USB2 PHY, power and power_aux e.g. DRA7 */
>> + TYPE_AM437USB2, /* USB2 PHY, power e.g. AM437x */
>> +};
>> +
>> struct omap_usb {
>> struct usb_phy phy;
>> struct phy_companion *comparator;
>> @@ -40,11 +46,20 @@ struct omap_usb {
>> struct clk *wkupclk;
>> struct clk *optclk;
>> u8 flags;
>> + enum omap_usb_phy_type type;
>> + struct regmap *syscon_phy_power; /* ctrl. reg. acces */
>> + unsigned int power_reg; /* power reg. index within syscon */
>> + u32 mask;
>> + u32 power_on;
>> + u32 power_off;
>> };
>>
>> struct usb_phy_data {
>> const char *label;
>> u8 flags;
>> + u32 mask;
>> + u32 power_on;
>> + u32 power_off;
>> };
>>
>> /* Driver Flags */
>> @@ -52,6 +67,14 @@ struct usb_phy_data {
>> #define OMAP_USB2_HAS_SET_VBUS (1 << 1)
>> #define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT (1 << 2)
>>
>> +#define OMAP_DEV_PHY_PD BIT(0)
>> +#define OMAP_USB2_PHY_PD BIT(28)
>> +
>> +#define AM437X_USB2_PHY_PD BIT(0)
>> +#define AM437X_USB2_OTG_PD BIT(1)
>> +#define AM437X_USB2_OTGVDET_EN BIT(19)
>> +#define AM437X_USB2_OTGSESSEND_EN BIT(20)
>> +
>
> Is all this used by anyone other than the phy driver?
> If not we should move whatever possible into the .c file.
>
> Could be a separate patch of course.
sure.
Thanks
Kishon
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Kishon Vijay Abraham I <kishon@ti.com> |
|---|---|
| Date | 2015-08-04 17:30 +0200 |
| Subject | [PATCH 3/7] phy: ti-pipe3: use *syscon* framework API to power on/off the PHY |
| Message-ID | <pTMkb-65J-39@gated-at.bofh.it> |
| In reply to | #1200079 |
Deprecate using phy-omap-control driver to power on/off the PHY and
use *syscon* framework to do the same.
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
Documentation/devicetree/bindings/phy/ti-phy.txt | 10 ++-
drivers/phy/phy-ti-pipe3.c | 90 ++++++++++++++++++----
2 files changed, 85 insertions(+), 15 deletions(-)
diff --git a/Documentation/devicetree/bindings/phy/ti-phy.txt b/Documentation/devicetree/bindings/phy/ti-phy.txt
index 9cf9446..e06f980 100644
--- a/Documentation/devicetree/bindings/phy/ti-phy.txt
+++ b/Documentation/devicetree/bindings/phy/ti-phy.txt
@@ -77,8 +77,6 @@ Required properties:
* "div-clk" - apll clock
Optional properties:
- - ctrl-module : phandle of the control module used by PHY driver to power on
- the PHY.
- id: If there are multiple instance of the same type, in order to
differentiate between each instance "id" can be used (e.g., multi-lane PCIe
PHY). If "id" is not provided, it is set to default value of '1'.
@@ -86,6 +84,14 @@ Optional properties:
CTRL_CORE_SMA_SW_0 register and register offset to the CTRL_CORE_SMA_SW_0
register that contains the SATA_PLL_SOFT_RESET bit. Only valid for sata_phy.
+Deprecated properties:
+ - ctrl-module : phandle of the control module used by PHY driver to power on
+ the PHY.
+
+Recommended properies:
+ - syscon-phy-power : phandle/offset pair. Phandle to the system control
+ module and the register offset to power on/off the PHY.
+
This is usually a subnode of ocp2scp to which it is connected.
usb3phy@4a084400 {
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
index 9782c16..a7c20e8 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -56,6 +56,15 @@
#define SATA_PLL_SOFT_RESET BIT(18)
+#define PIPE3_PHY_PWRCTL_CLK_CMD_MASK 0x003FC000
+#define PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT 14
+
+#define PIPE3_PHY_PWRCTL_CLK_FREQ_MASK 0xFFC00000
+#define PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT 22
+
+#define PIPE3_PHY_TX_RX_POWERON 0x3
+#define PIPE3_PHY_TX_RX_POWEROFF 0x0
+
/*
* This is an Empirical value that works, need to confirm the actual
* value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
@@ -86,8 +95,10 @@ struct ti_pipe3 {
struct clk *refclk;
struct clk *div_clk;
struct pipe3_dpll_map *dpll_map;
+ struct regmap *phy_power_syscon; /* ctrl. reg. acces */
struct regmap *dpll_reset_syscon; /* ctrl. reg. acces */
unsigned int dpll_reset_reg; /* reg. index within syscon */
+ unsigned int power_reg; /* power reg. index within syscon */
bool sata_refclk_enabled;
};
@@ -144,18 +155,53 @@ static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy);
static int ti_pipe3_power_off(struct phy *x)
{
+ u32 val;
+ int ret;
struct ti_pipe3 *phy = phy_get_drvdata(x);
- omap_control_phy_power(phy->control_dev, 0);
+ if (phy->phy_power_syscon) {
+ val = PIPE3_PHY_TX_RX_POWEROFF <<
+ PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
+
+ ret = regmap_update_bits(phy->phy_power_syscon, phy->power_reg,
+ PIPE3_PHY_PWRCTL_CLK_CMD_MASK, val);
+ if (ret < 0)
+ return ret;
+ } else {
+ omap_control_phy_power(phy->control_dev, 0);
+ }
return 0;
}
static int ti_pipe3_power_on(struct phy *x)
{
+ u32 val;
+ u32 mask;
+ int ret;
+ unsigned long rate;
struct ti_pipe3 *phy = phy_get_drvdata(x);
- omap_control_phy_power(phy->control_dev, 1);
+ if (phy->phy_power_syscon) {
+ rate = clk_get_rate(phy->sys_clk);
+ if (!rate) {
+ dev_err(phy->dev, "Invalid clock rate\n");
+ return -EINVAL;
+ }
+ rate = rate / 1000000;
+ mask = OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_CMD_MASK |
+ OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_MASK;
+ val = PIPE3_PHY_TX_RX_POWERON <<
+ PIPE3_PHY_PWRCTL_CLK_CMD_SHIFT;
+ val |= rate << OMAP_CTRL_PIPE3_PHY_PWRCTL_CLK_FREQ_SHIFT;
+
+ ret = regmap_update_bits(phy->phy_power_syscon, phy->power_reg,
+ mask, val);
+ if (ret < 0)
+ return ret;
+ } else {
+ omap_control_phy_power(phy->control_dev, 1);
+ }
return 0;
}
@@ -364,7 +410,8 @@ static int ti_pipe3_get_clk(struct ti_pipe3 *phy)
phy->wkupclk = ERR_PTR(-ENODEV);
}
- if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
+ if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie") ||
+ phy->phy_power_syscon) {
phy->sys_clk = devm_clk_get(dev, "sysclk");
if (IS_ERR(phy->sys_clk)) {
dev_err(dev, "unable to get sysclk\n");
@@ -413,19 +460,36 @@ static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy)
struct device_node *control_node;
struct platform_device *control_pdev;
- control_node = of_parse_phandle(node, "ctrl-module", 0);
- if (!control_node) {
- dev_err(dev, "Failed to get control device phandle\n");
- return -EINVAL;
+ phy->phy_power_syscon = syscon_regmap_lookup_by_phandle(node,
+ "syscon-phy-power");
+ if (IS_ERR(phy->phy_power_syscon)) {
+ dev_dbg(dev,
+ "can't get syscon-phy-power, using control device\n");
+ phy->phy_power_syscon = NULL;
+ } else {
+ if (of_property_read_u32_index(node,
+ "syscon-phy-power", 1,
+ &phy->power_reg)) {
+ dev_err(dev, "couldn't get power reg. offset\n");
+ return -EINVAL;
+ }
}
- control_pdev = of_find_device_by_node(control_node);
- if (!control_pdev) {
- dev_err(dev, "Failed to get control device\n");
- return -EINVAL;
- }
+ if (!phy->phy_power_syscon) {
+ control_node = of_parse_phandle(node, "ctrl-module", 0);
+ if (!control_node) {
+ dev_err(dev, "Failed to get control device phandle\n");
+ return -EINVAL;
+ }
- phy->control_dev = &control_pdev->dev;
+ control_pdev = of_find_device_by_node(control_node);
+ if (!control_pdev) {
+ dev_err(dev, "Failed to get control device\n");
+ return -EINVAL;
+ }
+
+ phy->control_dev = &control_pdev->dev;
+ }
if (of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
phy->dpll_reset_syscon = syscon_regmap_lookup_by_phandle(node,
--
1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web