* [PATCH v4] usb: phy: samsung: Add support to set pmu isolation
@ 2012-12-26 12:28 Vivek Gautam
2012-12-26 12:28 ` Vivek Gautam
0 siblings, 1 reply; 12+ messages in thread
From: Vivek Gautam @ 2012-12-26 12:28 UTC (permalink / raw)
To: linux-usb
Cc: devicetree-discuss, linux-arm-kernel, linux-kernel,
linux-samsung-soc, gregkh, balbi, kgene.kim, sylvester.nawrocki,
thomas.abraham, t.figa, ben-linux, broonie, l.majewski,
kyungmin.park, grant.likely, heiko, dianders, p.paneri
Changes form v3:
- Removing the hostphy_en_mas since this gets used in forthcoming patches
only when host phy support is added.
- Resolving few nits:
- using 'const' specifier for driver data structures.
- using ARRAY_SIZE() instead of giving magic number
for of_property_read_u32_array()
Changes from v2:
- Removed the phandle type of device node properties, instead using
sub-nodes now.
- Removed the property 'samsung,enable-mask' since it is SoC dependent
(SoCs like S5PV210 and S3C64XX have different bits to enable/disable
phy controller in comparison to exysno4210 onwards).
- Maintaining the phy enable mask (which is SoC dependent) for device type phy
and host type phy in the driver data.
- Re-structuring to get device properties using sub-nodes for 'usbphy-pmu'
Changes from v1:
- Changed the name of property for phy handler from'samsung,usb-phyctrl'
to 'samsung,usb-phyhandle' to make it look more generic.
- Similarly 'samsung,phyctrl-reg' is changed to 'samsung,phyhandle-reg'
- Added a check for 'samsung,usb-phyhandle' before getting node from
phandle.
- Putting the node using 'of_node_put()' which had been missed.
- Adding necessary check for the pointer in 'samsung_usbphy_set_isolation()'
to avoid any NULL pointer dereferencing.
- Unmapping the register ioremapped in 'samsung_usbphy_parse_dt_param()'.
Based on usb-next branch with Praveen Paneri's patches on top of it.
- http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/134476.html
- http://lists.infradead.org/pipermail/linux-arm-kernel/2012-November/131763.html
Vivek Gautam (1):
usb: phy: samsung: Add support to set pmu isolation
.../devicetree/bindings/usb/samsung-usbphy.txt | 31 ++++
drivers/usb/phy/samsung-usbphy.c | 145 +++++++++++++++++---
2 files changed, 155 insertions(+), 21 deletions(-)
--
1.7.6.5
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v4] usb: phy: samsung: Add support to set pmu isolation
2012-12-26 12:28 [PATCH v4] usb: phy: samsung: Add support to set pmu isolation Vivek Gautam
@ 2012-12-26 12:28 ` Vivek Gautam
[not found] ` <1356524912-4736-2-git-send-email-gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Vivek Gautam @ 2012-12-26 12:28 UTC (permalink / raw)
To: linux-usb
Cc: devicetree-discuss, linux-arm-kernel, linux-kernel,
linux-samsung-soc, gregkh, balbi, kgene.kim, sylvester.nawrocki,
thomas.abraham, t.figa, ben-linux, broonie, l.majewski,
kyungmin.park, grant.likely, heiko, dianders, p.paneri
Adding support to parse device node data in order to get
required properties to set pmu isolation for usb-phy.
Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
---
.../devicetree/bindings/usb/samsung-usbphy.txt | 31 ++++
drivers/usb/phy/samsung-usbphy.c | 145 +++++++++++++++++---
2 files changed, 155 insertions(+), 21 deletions(-)
diff --git a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
index 7b26e2d..6b873fd 100644
--- a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
+++ b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
@@ -9,3 +9,34 @@ Required properties:
- compatible : should be "samsung,exynos4210-usbphy"
- reg : base physical address of the phy registers and length of memory mapped
region.
+
+Optional properties:
+- #address-cells: should be '1' when usbphy node has a child node with 'reg'
+ property.
+- #size-cells: should be '1' when usbphy node has a child node with 'reg'
+ property.
+
+- The child node 'usbphy-pmu' to the node usbphy should provide the following
+ information required by usb-phy controller to enable/disable the phy.
+ - reg : base physical address of PHY control register in PMU which
+ enables/disables the phy controller.
+ The size of this register is the total sum of size of all phy-control
+ registers that the SoC has. For example, the size will be
+ '0x4' in case we have only one phy-control register (like in S3C64XX) or
+ '0x8' in case we have two phy-control registers (like in Exynos4210)
+ and so on.
+
+Example:
+ - Exysno4210
+
+ usbphy@125B0000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "samsung,exynos4210-usbphy";
+ reg = <0x125B0000 0x100>;
+
+ usbphy-pmu {
+ /* USB device and host PHY_CONTROL registers */
+ reg = <0x10020704 0x8>;
+ };
+ };
diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/samsung-usbphy.c
index 5c5e1bb5..b9f4f42 100644
--- a/drivers/usb/phy/samsung-usbphy.c
+++ b/drivers/usb/phy/samsung-usbphy.c
@@ -60,20 +60,42 @@
#define MHZ (1000*1000)
#endif
+#define S3C64XX_USBPHY_ENABLE (0x1 << 16)
+#define EXYNOS_USBPHY_ENABLE (0x1 << 0)
+
enum samsung_cpu_type {
TYPE_S3C64XX,
TYPE_EXYNOS4210,
};
/*
+ * struct samsung_usbphy_drvdata - driver data for various SoC variants
+ * @cpu_type: machine identifier
+ * @devphy_en_mask: device phy enable mask for PHY CONTROL register
+ *
+ * Here we have a separate mask for device type phy.
+ * Having different masks for host and device type phy helps
+ * in setting independent masks in case of SoCs like S5PV210,
+ * in which PHY0 and PHY1 enable bits belong to same register
+ * placed at [0] and [1] respectively.
+ * Although for newer SoCs like exynos these bits belong to
+ * different registers altogether placed at [0].
+ */
+struct samsung_usbphy_drvdata {
+ int cpu_type;
+ int devphy_en_mask;
+};
+
+/*
* struct samsung_usbphy - transceiver driver state
* @phy: transceiver structure
* @plat: platform data
* @dev: The parent device supplied to the probe function
* @clk: usb phy clock
* @regs: usb phy register memory base
+ * @phyctrl_pmureg: usb device phy-control pmu register memory base
* @ref_clk_freq: reference clock frequency selection
- * @cpu_type: machine identifier
+ * @drv_data: driver data available for different cpu types
*/
struct samsung_usbphy {
struct usb_phy phy;
@@ -81,12 +103,67 @@ struct samsung_usbphy {
struct device *dev;
struct clk *clk;
void __iomem *regs;
+ void __iomem *phyctrl_pmureg;
int ref_clk_freq;
- int cpu_type;
+ const struct samsung_usbphy_drvdata *drv_data;
};
#define phy_to_sphy(x) container_of((x), struct samsung_usbphy, phy)
+static int samsung_usbphy_parse_dt_param(struct samsung_usbphy *sphy)
+{
+ struct device_node *usbphy_pmu;
+ u32 reg[2];
+ int ret;
+
+ if (!sphy->dev->of_node) {
+ dev_err(sphy->dev, "Can't get usb-phy node\n");
+ return -ENODEV;
+ }
+
+ usbphy_pmu = of_get_child_by_name(sphy->dev->of_node, "usbphy-pmu");
+ if (!usbphy_pmu)
+ dev_warn(sphy->dev, "Can't get usb-phy pmu control node\n");
+
+ ret = of_property_read_u32_array(usbphy_pmu, "reg", reg,
+ ARRAY_SIZE(reg));
+ if (!ret)
+ sphy->phyctrl_pmureg = ioremap(reg[0], reg[1]);
+
+ of_node_put(usbphy_pmu);
+
+ if (IS_ERR_OR_NULL(sphy->phyctrl_pmureg)) {
+ dev_err(sphy->dev, "Can't get usb-phy pmu control register\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/*
+ * Set isolation here for phy.
+ * SOCs control this by controlling corresponding PMU registers
+ */
+static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, int on)
+{
+ u32 reg;
+ int en_mask;
+
+ if (!sphy->phyctrl_pmureg) {
+ dev_warn(sphy->dev, "Can't set pmu isolation\n");
+ return;
+ }
+
+ reg = readl(sphy->phyctrl_pmureg);
+
+ en_mask = sphy->drv_data->devphy_en_mask;
+
+ if (on)
+ writel(reg & ~en_mask, sphy->phyctrl_pmureg);
+ else
+ writel(reg | en_mask, sphy->phyctrl_pmureg);
+}
+
/*
* Returns reference clock frequency selection value
*/
@@ -112,7 +189,7 @@ static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
refclk_freq = PHYCLK_CLKSEL_48M;
break;
default:
- if (sphy->cpu_type == TYPE_S3C64XX)
+ if (sphy->drv_data->cpu_type == TYPE_S3C64XX)
refclk_freq = PHYCLK_CLKSEL_48M;
else
refclk_freq = PHYCLK_CLKSEL_24M;
@@ -135,7 +212,7 @@ static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
phypwr = readl(regs + SAMSUNG_PHYPWR);
rstcon = readl(regs + SAMSUNG_RSTCON);
- switch (sphy->cpu_type) {
+ switch (sphy->drv_data->cpu_type) {
case TYPE_S3C64XX:
phyclk &= ~PHYCLK_COMMON_ON_N;
phypwr &= ~PHYPWR_NORMAL_MASK;
@@ -165,7 +242,7 @@ static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
phypwr = readl(regs + SAMSUNG_PHYPWR);
- switch (sphy->cpu_type) {
+ switch (sphy->drv_data->cpu_type) {
case TYPE_S3C64XX:
phypwr |= PHYPWR_NORMAL_MASK;
break;
@@ -199,6 +276,8 @@ static int samsung_usbphy_init(struct usb_phy *phy)
/* Disable phy isolation */
if (sphy->plat && sphy->plat->pmu_isolation)
sphy->plat->pmu_isolation(false);
+ else
+ samsung_usbphy_set_isolation(sphy, false);
/* Initialize usb phy registers */
samsung_usbphy_enable(sphy);
@@ -228,38 +307,37 @@ static void samsung_usbphy_shutdown(struct usb_phy *phy)
/* Enable phy isolation */
if (sphy->plat && sphy->plat->pmu_isolation)
sphy->plat->pmu_isolation(true);
+ else
+ samsung_usbphy_set_isolation(sphy, true);
clk_disable_unprepare(sphy->clk);
}
static const struct of_device_id samsung_usbphy_dt_match[];
-static inline int samsung_usbphy_get_driver_data(struct platform_device *pdev)
+static inline struct samsung_usbphy_drvdata
+*samsung_usbphy_get_driver_data(struct platform_device *pdev)
{
if (pdev->dev.of_node) {
const struct of_device_id *match;
match = of_match_node(samsung_usbphy_dt_match,
pdev->dev.of_node);
- return (int) match->data;
+ return (struct samsung_usbphy_drvdata *) match->data;
}
- return platform_get_device_id(pdev)->driver_data;
+ return (struct samsung_usbphy_drvdata *)
+ platform_get_device_id(pdev)->driver_data;
}
static int __devinit samsung_usbphy_probe(struct platform_device *pdev)
{
struct samsung_usbphy *sphy;
- struct samsung_usbphy_data *pdata;
+ struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
struct device *dev = &pdev->dev;
struct resource *phy_mem;
void __iomem *phy_base;
struct clk *clk;
-
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_err(&pdev->dev, "%s: no platform data defined\n", __func__);
- return -EINVAL;
- }
+ int ret;
phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!phy_mem) {
@@ -283,7 +361,19 @@ static int __devinit samsung_usbphy_probe(struct platform_device *pdev)
return PTR_ERR(clk);
}
- sphy->dev = &pdev->dev;
+ sphy->dev = dev;
+
+ if (dev->of_node) {
+ ret = samsung_usbphy_parse_dt_param(sphy);
+ if (ret < 0)
+ return ret;
+ } else {
+ if (!pdata) {
+ dev_err(dev, "no platform data specified\n");
+ return -EINVAL;
+ }
+ }
+
sphy->plat = pdata;
sphy->regs = phy_base;
sphy->clk = clk;
@@ -291,7 +381,7 @@ static int __devinit samsung_usbphy_probe(struct platform_device *pdev)
sphy->phy.label = "samsung-usbphy";
sphy->phy.init = samsung_usbphy_init;
sphy->phy.shutdown = samsung_usbphy_shutdown;
- sphy->cpu_type = samsung_usbphy_get_driver_data(pdev);
+ sphy->drv_data = samsung_usbphy_get_driver_data(pdev);
sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy);
platform_set_drvdata(pdev, sphy);
@@ -305,17 +395,30 @@ static int __exit samsung_usbphy_remove(struct platform_device *pdev)
usb_remove_phy(&sphy->phy);
+ if (sphy->phyctrl_pmureg)
+ iounmap(sphy->phyctrl_pmureg);
+
return 0;
}
+static const struct samsung_usbphy_drvdata usbphy_s3c64xx = {
+ .cpu_type = TYPE_S3C64XX,
+ .devphy_en_mask = S3C64XX_USBPHY_ENABLE,
+};
+
+static const struct samsung_usbphy_drvdata usbphy_exynos4 = {
+ .cpu_type = TYPE_EXYNOS4210,
+ .devphy_en_mask = EXYNOS_USBPHY_ENABLE,
+};
+
#ifdef CONFIG_OF
static const struct of_device_id samsung_usbphy_dt_match[] = {
{
.compatible = "samsung,s3c64xx-usbphy",
- .data = (void *)TYPE_S3C64XX,
+ .data = (void *)&usbphy_s3c64xx,
}, {
.compatible = "samsung,exynos4210-usbphy",
- .data = (void *)TYPE_EXYNOS4210,
+ .data = (void *)&usbphy_exynos4,
},
{},
};
@@ -325,10 +428,10 @@ MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
static struct platform_device_id samsung_usbphy_driver_ids[] = {
{
.name = "s3c64xx-usbphy",
- .driver_data = TYPE_S3C64XX,
+ .driver_data = (unsigned long)&usbphy_s3c64xx,
}, {
.name = "exynos4210-usbphy",
- .driver_data = TYPE_EXYNOS4210,
+ .driver_data = (unsigned long)&usbphy_exynos4,
},
{},
};
--
1.7.6.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v4] usb: phy: samsung: Add support to set pmu isolation
[not found] ` <1356524912-4736-2-git-send-email-gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
@ 2012-12-26 13:56 ` Vivek Gautam
[not found] ` <CAFp+6iEoy-d6gHBMAiNi0n+tE8iS7Hk=k92w8EWfT_r3eeN_UA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
0 siblings, 1 reply; 12+ messages in thread
From: Vivek Gautam @ 2012-12-26 13:56 UTC (permalink / raw)
To: sylvester.nawrocki-Re5JQEeQqe8AvxtiuMwx3w
Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r, balbi-l0cyMroinI0,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ,
thomas.abraham-QSEj5FYQhm4dnm+yROfE0A,
t.figa-Sze3O3UU22JBDgjK7y7TUQ, ben-linux-elnMNo+KYs3YtjvyW6yDsg,
broonie-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
l.majewski-Sze3O3UU22JBDgjK7y7TUQ,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
grant.likely-s3s/WqlpOiPyB63q8FvJNQ, heiko-4mtYJXux2i+zQB+pC5nmwQ,
dianders-F7+t8E8rja9g9hUCZPvPmw, p.paneri-Sze3O3UU22JBDgjK7y7TUQ,
Vivek Gautam
Hi Sylwester,
On Wed, Dec 26, 2012 at 5:58 PM, Vivek Gautam <gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> wrote:
> Adding support to parse device node data in order to get
> required properties to set pmu isolation for usb-phy.
>
> Signed-off-by: Vivek Gautam <gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> ---
Hope these changes align with what architectural changes you had suggested ?
--
Thanks & Regards
Vivek
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v4] usb: phy: samsung: Add support to set pmu isolation
2012-12-26 12:28 ` Vivek Gautam
[not found] ` <1356524912-4736-2-git-send-email-gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
@ 2012-12-26 22:30 ` Sylwester Nawrocki
2012-12-27 12:01 ` Vivek Gautam
2012-12-27 0:26 ` [PATCH v4] " Russell King - ARM Linux
2 siblings, 1 reply; 12+ messages in thread
From: Sylwester Nawrocki @ 2012-12-26 22:30 UTC (permalink / raw)
To: Vivek Gautam
Cc: l.majewski, linux-samsung-soc, heiko, p.paneri, gregkh,
devicetree-discuss, linux-usb, linux-kernel, balbi, dianders,
grant.likely, kyungmin.park, kgene.kim, thomas.abraham, ben-linux,
broonie, t.figa, linux-arm-kernel
On 12/26/2012 01:28 PM, Vivek Gautam wrote:
> Adding support to parse device node data in order to get
> required properties to set pmu isolation for usb-phy.
>
> Signed-off-by: Vivek Gautam<gautam.vivek@samsung.com>
> ---
> .../devicetree/bindings/usb/samsung-usbphy.txt | 31 ++++
> drivers/usb/phy/samsung-usbphy.c | 145 +++++++++++++++++---
> 2 files changed, 155 insertions(+), 21 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
> index 7b26e2d..6b873fd 100644
> --- a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
> +++ b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
> @@ -9,3 +9,34 @@ Required properties:
> - compatible : should be "samsung,exynos4210-usbphy"
> - reg : base physical address of the phy registers and length of memory mapped
> region.
> +
> +Optional properties:
> +- #address-cells: should be '1' when usbphy node has a child node with 'reg'
> + property.
> +- #size-cells: should be '1' when usbphy node has a child node with 'reg'
> + property.
> +
> +- The child node 'usbphy-pmu' to the node usbphy should provide the following
> + information required by usb-phy controller to enable/disable the phy.
> + - reg : base physical address of PHY control register in PMU which
> + enables/disables the phy controller.
> + The size of this register is the total sum of size of all phy-control
> + registers that the SoC has. For example, the size will be
> + '0x4' in case we have only one phy-control register (like in S3C64XX) or
> + '0x8' in case we have two phy-control registers (like in Exynos4210)
> + and so on.
> +
> +Example:
> + - Exysno4210
s/Exysno/Exynos
> +
> + usbphy@125B0000 {
> + #address-cells =<1>;
> + #size-cells =<1>;
> + compatible = "samsung,exynos4210-usbphy";
> + reg =<0x125B0000 0x100>;
> +
> + usbphy-pmu {
> + /* USB device and host PHY_CONTROL registers */
> + reg =<0x10020704 0x8>;
> + };
> + };
> diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/samsung-usbphy.c
> index 5c5e1bb5..b9f4f42 100644
> --- a/drivers/usb/phy/samsung-usbphy.c
> +++ b/drivers/usb/phy/samsung-usbphy.c
> @@ -60,20 +60,42 @@
> #define MHZ (1000*1000)
> #endif
>
> +#define S3C64XX_USBPHY_ENABLE (0x1<< 16)
> +#define EXYNOS_USBPHY_ENABLE (0x1<< 0)
> +
> enum samsung_cpu_type {
> TYPE_S3C64XX,
> TYPE_EXYNOS4210,
> };
>
> /*
> + * struct samsung_usbphy_drvdata - driver data for various SoC variants
> + * @cpu_type: machine identifier
> + * @devphy_en_mask: device phy enable mask for PHY CONTROL register
> + *
> + * Here we have a separate mask for device type phy.
> + * Having different masks for host and device type phy helps
> + * in setting independent masks in case of SoCs like S5PV210,
> + * in which PHY0 and PHY1 enable bits belong to same register
> + * placed at [0] and [1] respectively.
"and are placed at positions 0 and 1 respectively" ?
> + * Although for newer SoCs like exynos these bits belong to
> + * different registers altogether placed at [0].
> + */
> +struct samsung_usbphy_drvdata {
> + int cpu_type;
> + int devphy_en_mask;
> +};
> +
> +/*
> * struct samsung_usbphy - transceiver driver state
> * @phy: transceiver structure
> * @plat: platform data
> * @dev: The parent device supplied to the probe function
> * @clk: usb phy clock
> * @regs: usb phy register memory base
> + * @phyctrl_pmureg: usb device phy-control pmu register memory base
nit: Perhaps we could just call it "pmureg' ?
> * @ref_clk_freq: reference clock frequency selection
> - * @cpu_type: machine identifier
> + * @drv_data: driver data available for different cpu types
Actually it's for different SoCs, not CPUs, right ?
> */
> struct samsung_usbphy {
> struct usb_phy phy;
> @@ -81,12 +103,67 @@ struct samsung_usbphy {
> struct device *dev;
> struct clk *clk;
> void __iomem *regs;
> + void __iomem *phyctrl_pmureg;
> int ref_clk_freq;
> - int cpu_type;
> + const struct samsung_usbphy_drvdata *drv_data;
> };
>
> #define phy_to_sphy(x) container_of((x), struct samsung_usbphy, phy)
>
> +static int samsung_usbphy_parse_dt_param(struct samsung_usbphy *sphy)
nit: s/samsung_usbphy_parse_dt_param/samsung_usbphy_parse_dt ?
> +{
> + struct device_node *usbphy_pmu;
> + u32 reg[2];
> + int ret;
> +
> + if (!sphy->dev->of_node) {
> + dev_err(sphy->dev, "Can't get usb-phy node\n");
> + return -ENODEV;
The function is called only when dev->of_node is not NULL, so this path
is never executed, AFAICS. I would just drop this redundant check.
> + }
> +
> + usbphy_pmu = of_get_child_by_name(sphy->dev->of_node, "usbphy-pmu");
> + if (!usbphy_pmu)
> + dev_warn(sphy->dev, "Can't get usb-phy pmu control node\n");
> + ret = of_property_read_u32_array(usbphy_pmu, "reg", reg,
> + ARRAY_SIZE(reg));
> + if (!ret)
> + sphy->phyctrl_pmureg = ioremap(reg[0], reg[1]);
I don't think this is correct. reg is not really an array of u32 type,
it's an array of address/size tuples. I thought you would use of_iomap()
here. Any reason why you didn't do so ? It would also make it easier to
handle multiple address/size pairs if required.
> +
> + of_node_put(usbphy_pmu);
> +
> + if (IS_ERR_OR_NULL(sphy->phyctrl_pmureg)) {
When is sphy->phyctrl_pmureg assigned a ERR_PTR() value ? Wouldn't it
be enough to simply check for NULL ?
> + dev_err(sphy->dev, "Can't get usb-phy pmu control register\n");
> + return -ENODEV;
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * Set isolation here for phy.
> + * SOCs control this by controlling corresponding PMU registers
> + */
> +static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, int on)
> +{
> + u32 reg;
> + int en_mask;
> +
> + if (!sphy->phyctrl_pmureg) {
> + dev_warn(sphy->dev, "Can't set pmu isolation\n");
> + return;
> + }
> +
> + reg = readl(sphy->phyctrl_pmureg);
To make it more generic maybe it's worth to store an offset to the actual
register somewhere, e.g. in the driver_data struct ? This function is
supposed to handle both device and host PHYs, isn't it ?
> + en_mask = sphy->drv_data->devphy_en_mask;
> +
> + if (on)
> + writel(reg& ~en_mask, sphy->phyctrl_pmureg);
> + else
> + writel(reg | en_mask, sphy->phyctrl_pmureg);
nit: This could be also written as:
reg = on ? reg & ~mask : reg | mask;
writel(reg, sphy->phyctrl_pmureg);
> +}
> +
> /*
> * Returns reference clock frequency selection value
> */
> @@ -112,7 +189,7 @@ static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
> refclk_freq = PHYCLK_CLKSEL_48M;
> break;
> default:
> - if (sphy->cpu_type == TYPE_S3C64XX)
> + if (sphy->drv_data->cpu_type == TYPE_S3C64XX)
> refclk_freq = PHYCLK_CLKSEL_48M;
> else
> refclk_freq = PHYCLK_CLKSEL_24M;
> @@ -135,7 +212,7 @@ static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
> phypwr = readl(regs + SAMSUNG_PHYPWR);
> rstcon = readl(regs + SAMSUNG_RSTCON);
>
> - switch (sphy->cpu_type) {
> + switch (sphy->drv_data->cpu_type) {
> case TYPE_S3C64XX:
> phyclk&= ~PHYCLK_COMMON_ON_N;
> phypwr&= ~PHYPWR_NORMAL_MASK;
> @@ -165,7 +242,7 @@ static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
>
> phypwr = readl(regs + SAMSUNG_PHYPWR);
>
> - switch (sphy->cpu_type) {
> + switch (sphy->drv_data->cpu_type) {
> case TYPE_S3C64XX:
> phypwr |= PHYPWR_NORMAL_MASK;
> break;
> @@ -199,6 +276,8 @@ static int samsung_usbphy_init(struct usb_phy *phy)
> /* Disable phy isolation */
> if (sphy->plat&& sphy->plat->pmu_isolation)
> sphy->plat->pmu_isolation(false);
> + else
> + samsung_usbphy_set_isolation(sphy, false);
>
> /* Initialize usb phy registers */
> samsung_usbphy_enable(sphy);
> @@ -228,38 +307,37 @@ static void samsung_usbphy_shutdown(struct usb_phy *phy)
> /* Enable phy isolation */
> if (sphy->plat&& sphy->plat->pmu_isolation)
> sphy->plat->pmu_isolation(true);
> + else
> + samsung_usbphy_set_isolation(sphy, true);
>
> clk_disable_unprepare(sphy->clk);
> }
>
> static const struct of_device_id samsung_usbphy_dt_match[];
>
> -static inline int samsung_usbphy_get_driver_data(struct platform_device *pdev)
> +static inline struct samsung_usbphy_drvdata
> +*samsung_usbphy_get_driver_data(struct platform_device *pdev)
> {
> if (pdev->dev.of_node) {
> const struct of_device_id *match;
> match = of_match_node(samsung_usbphy_dt_match,
> pdev->dev.of_node);
> - return (int) match->data;
> + return (struct samsung_usbphy_drvdata *) match->data;
> }
>
> - return platform_get_device_id(pdev)->driver_data;
> + return (struct samsung_usbphy_drvdata *)
> + platform_get_device_id(pdev)->driver_data;
> }
>
> static int __devinit samsung_usbphy_probe(struct platform_device *pdev)
> {
> struct samsung_usbphy *sphy;
> - struct samsung_usbphy_data *pdata;
> + struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
> struct device *dev =&pdev->dev;
> struct resource *phy_mem;
> void __iomem *phy_base;
> struct clk *clk;
> -
> - pdata = pdev->dev.platform_data;
> - if (!pdata) {
> - dev_err(&pdev->dev, "%s: no platform data defined\n", __func__);
> - return -EINVAL;
> - }
> + int ret;
>
> phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> if (!phy_mem) {
> @@ -283,7 +361,19 @@ static int __devinit samsung_usbphy_probe(struct platform_device *pdev)
> return PTR_ERR(clk);
> }
>
> - sphy->dev =&pdev->dev;
> + sphy->dev = dev;
> +
> + if (dev->of_node) {
> + ret = samsung_usbphy_parse_dt_param(sphy);
> + if (ret< 0)
> + return ret;
> + } else {
> + if (!pdata) {
> + dev_err(dev, "no platform data specified\n");
> + return -EINVAL;
> + }
> + }
> +
> sphy->plat = pdata;
> sphy->regs = phy_base;
> sphy->clk = clk;
--
Thanks,
Sylwester
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v4] usb: phy: samsung: Add support to set pmu isolation
[not found] ` <CAFp+6iEoy-d6gHBMAiNi0n+tE8iS7Hk=k92w8EWfT_r3eeN_UA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2012-12-26 23:05 ` Sylwester Nawrocki
0 siblings, 0 replies; 12+ messages in thread
From: Sylwester Nawrocki @ 2012-12-26 23:05 UTC (permalink / raw)
To: Vivek Gautam
Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA, Praveen Paneri,
Vivek Gautam
Hi,
On 12/26/2012 02:56 PM, Vivek Gautam wrote:
> On Wed, Dec 26, 2012 at 5:58 PM, Vivek Gautam<gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> wrote:
>> Adding support to parse device node data in order to get
>> required properties to set pmu isolation for usb-phy.
>>
>> Signed-off-by: Vivek Gautam<gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
>> ---
>
> Hope these changes align with what architectural changes you had suggested ?
It looks much better now, thanks! I had a few additional comments, please
see my other reply.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v4] usb: phy: samsung: Add support to set pmu isolation
2012-12-26 12:28 ` Vivek Gautam
[not found] ` <1356524912-4736-2-git-send-email-gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2012-12-26 22:30 ` Sylwester Nawrocki
@ 2012-12-27 0:26 ` Russell King - ARM Linux
2012-12-27 9:20 ` Vivek Gautam
2 siblings, 1 reply; 12+ messages in thread
From: Russell King - ARM Linux @ 2012-12-27 0:26 UTC (permalink / raw)
To: Vivek Gautam
Cc: linux-usb, l.majewski, linux-samsung-soc, heiko, p.paneri, gregkh,
devicetree-discuss, broonie, linux-kernel, balbi, dianders,
grant.likely, kyungmin.park, kgene.kim, thomas.abraham, ben-linux,
sylvester.nawrocki, t.figa, linux-arm-kernel
On Wed, Dec 26, 2012 at 05:58:32PM +0530, Vivek Gautam wrote:
> + if (!ret)
> + sphy->phyctrl_pmureg = ioremap(reg[0], reg[1]);
> +
> + of_node_put(usbphy_pmu);
> +
> + if (IS_ERR_OR_NULL(sphy->phyctrl_pmureg)) {
No. Learn what the error return values are from functions. Using the
wrong ones is buggy. ioremap() only ever returns NULL on error. You
must check against NULL, and not use the IS_ERR stuff.
> +/*
> + * Set isolation here for phy.
> + * SOCs control this by controlling corresponding PMU registers
> + */
> +static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, int on)
> +{
> + u32 reg;
> + int en_mask;
> +
> + if (!sphy->phyctrl_pmureg) {
> + dev_warn(sphy->dev, "Can't set pmu isolation\n");
> + return;
> + }
> +
> + reg = readl(sphy->phyctrl_pmureg);
> +
> + en_mask = sphy->drv_data->devphy_en_mask;
> +
> + if (on)
> + writel(reg & ~en_mask, sphy->phyctrl_pmureg);
> + else
> + writel(reg | en_mask, sphy->phyctrl_pmureg);
What guarantees that this read-modify-write sequence of this register safe?
And, btw, this can't be optimised very well because of the barrier inside
writel(). This would be better:
if (on)
reg &= ~en_mask;
else
reg |= en_mask;
writel(reg, sphy->phyctrl_pmureg);
> +static inline struct samsung_usbphy_drvdata
> +*samsung_usbphy_get_driver_data(struct platform_device *pdev)
> {
> if (pdev->dev.of_node) {
> const struct of_device_id *match;
> match = of_match_node(samsung_usbphy_dt_match,
> pdev->dev.of_node);
> - return (int) match->data;
> + return (struct samsung_usbphy_drvdata *) match->data;
match->data is a const void pointer. Is there a reason you need this
cast here? What if you made the returned pointer from this function
also const and fixed up all its users (no user should modify this
data.)
> #ifdef CONFIG_OF
> static const struct of_device_id samsung_usbphy_dt_match[] = {
> {
> .compatible = "samsung,s3c64xx-usbphy",
> - .data = (void *)TYPE_S3C64XX,
> + .data = (void *)&usbphy_s3c64xx,
Why do you need this cast?
> }, {
> .compatible = "samsung,exynos4210-usbphy",
> - .data = (void *)TYPE_EXYNOS4210,
> + .data = (void *)&usbphy_exynos4,
Ditto.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v4] usb: phy: samsung: Add support to set pmu isolation
2012-12-27 0:26 ` [PATCH v4] " Russell King - ARM Linux
@ 2012-12-27 9:20 ` Vivek Gautam
0 siblings, 0 replies; 12+ messages in thread
From: Vivek Gautam @ 2012-12-27 9:20 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: Vivek Gautam, linux-usb, l.majewski, linux-samsung-soc, heiko,
p.paneri, gregkh, devicetree-discuss, broonie, linux-kernel,
balbi, dianders, grant.likely, kyungmin.park, kgene.kim,
thomas.abraham, ben-linux, sylvester.nawrocki, t.figa,
linux-arm-kernel
Hi Russell,
On Thu, Dec 27, 2012 at 5:56 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Wed, Dec 26, 2012 at 05:58:32PM +0530, Vivek Gautam wrote:
>> + if (!ret)
>> + sphy->phyctrl_pmureg = ioremap(reg[0], reg[1]);
>> +
>> + of_node_put(usbphy_pmu);
>> +
>> + if (IS_ERR_OR_NULL(sphy->phyctrl_pmureg)) {
>
> No. Learn what the error return values are from functions. Using the
> wrong ones is buggy. ioremap() only ever returns NULL on error. You
> must check against NULL, and not use the IS_ERR stuff.
>
True, i should have checked the things. :-(
ioremap() won't return error. Will amend this to check against NULL.
>> +/*
>> + * Set isolation here for phy.
>> + * SOCs control this by controlling corresponding PMU registers
>> + */
>> +static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, int on)
>> +{
>> + u32 reg;
>> + int en_mask;
>> +
>> + if (!sphy->phyctrl_pmureg) {
>> + dev_warn(sphy->dev, "Can't set pmu isolation\n");
>> + return;
>> + }
>> +
>> + reg = readl(sphy->phyctrl_pmureg);
>> +
>> + en_mask = sphy->drv_data->devphy_en_mask;
>> +
>> + if (on)
>> + writel(reg & ~en_mask, sphy->phyctrl_pmureg);
>> + else
>> + writel(reg | en_mask, sphy->phyctrl_pmureg);
>
> What guarantees that this read-modify-write sequence of this register safe?
> And, btw, this can't be optimised very well because of the barrier inside
> writel(). This would be better:
>
> if (on)
> reg &= ~en_mask;
> else
> reg |= en_mask;
>
> writel(reg, sphy->phyctrl_pmureg);
>
Sure will amend this.
A similar way suggested by Sylwester in the earlier mail in this thread:
reg = on ? reg & ~mask : reg | mask;
writel(reg, sphy->phyctrl_pmureg);
Does this look fine ?
>> +static inline struct samsung_usbphy_drvdata
>> +*samsung_usbphy_get_driver_data(struct platform_device *pdev)
>> {
>> if (pdev->dev.of_node) {
>> const struct of_device_id *match;
>> match = of_match_node(samsung_usbphy_dt_match,
>> pdev->dev.of_node);
>> - return (int) match->data;
>> + return (struct samsung_usbphy_drvdata *) match->data;
>
> match->data is a const void pointer. Is there a reason you need this
> cast here? What if you made the returned pointer from this function
> also const and fixed up all its users (no user should modify this
> data.)
>
Right, we won't need this cast since match->data is a void pointer.
Will also make the returned pointer const.
>> #ifdef CONFIG_OF
>> static const struct of_device_id samsung_usbphy_dt_match[] = {
>> {
>> .compatible = "samsung,s3c64xx-usbphy",
>> - .data = (void *)TYPE_S3C64XX,
>> + .data = (void *)&usbphy_s3c64xx,
>
> Why do you need this cast?
>
True we don't need this cast. Will remove this one.
>> }, {
>> .compatible = "samsung,exynos4210-usbphy",
>> - .data = (void *)TYPE_EXYNOS4210,
>> + .data = (void *)&usbphy_exynos4,
>
> Ditto.
True we don't need this cast. Will remove this one.
Thanks for the review :-)
--
Regards
Vivek
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v4] usb: phy: samsung: Add support to set pmu isolation
2012-12-26 22:30 ` Sylwester Nawrocki
@ 2012-12-27 12:01 ` Vivek Gautam
2012-12-28 9:13 ` [PATCH v5] " Vivek Gautam
0 siblings, 1 reply; 12+ messages in thread
From: Vivek Gautam @ 2012-12-27 12:01 UTC (permalink / raw)
To: Sylwester Nawrocki
Cc: Vivek Gautam, l.majewski, linux-samsung-soc, p.paneri, gregkh,
devicetree-discuss, linux-usb, linux-kernel, balbi, kyungmin.park,
kgene.kim, ben-linux, broonie, linux-arm-kernel
Hi Sylwester,
On Thu, Dec 27, 2012 at 4:00 AM, Sylwester Nawrocki
<sylvester.nawrocki@gmail.com> wrote:
> On 12/26/2012 01:28 PM, Vivek Gautam wrote:
>>
>> Adding support to parse device node data in order to get
>> required properties to set pmu isolation for usb-phy.
>>
>> Signed-off-by: Vivek Gautam<gautam.vivek@samsung.com>
>> ---
>> .../devicetree/bindings/usb/samsung-usbphy.txt | 31 ++++
>> drivers/usb/phy/samsung-usbphy.c | 145
>> +++++++++++++++++---
>> 2 files changed, 155 insertions(+), 21 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
>> b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
>> index 7b26e2d..6b873fd 100644
>> --- a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
>> +++ b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
>> @@ -9,3 +9,34 @@ Required properties:
>> - compatible : should be "samsung,exynos4210-usbphy"
>> - reg : base physical address of the phy registers and length of memory
>> mapped
>> region.
>> +
>> +Optional properties:
>> +- #address-cells: should be '1' when usbphy node has a child node with
>> 'reg'
>> + property.
>> +- #size-cells: should be '1' when usbphy node has a child node with 'reg'
>> + property.
>> +
>> +- The child node 'usbphy-pmu' to the node usbphy should provide the
>> following
>> + information required by usb-phy controller to enable/disable the phy.
>> + - reg : base physical address of PHY control register in PMU which
>> + enables/disables the phy controller.
>> + The size of this register is the total sum of size of all
>> phy-control
>> + registers that the SoC has. For example, the size will be
>> + '0x4' in case we have only one phy-control register (like in
>> S3C64XX) or
>> + '0x8' in case we have two phy-control registers (like in
>> Exynos4210)
>> + and so on.
>> +
>> +Example:
>> + - Exysno4210
>
>
> s/Exysno/Exynos
>
Sure will amend this.
>
>> +
>> + usbphy@125B0000 {
>> + #address-cells =<1>;
>> + #size-cells =<1>;
>> + compatible = "samsung,exynos4210-usbphy";
>> + reg =<0x125B0000 0x100>;
>> +
>> + usbphy-pmu {
>> + /* USB device and host PHY_CONTROL registers */
>> + reg =<0x10020704 0x8>;
>> + };
>> + };
>> diff --git a/drivers/usb/phy/samsung-usbphy.c
>> b/drivers/usb/phy/samsung-usbphy.c
>> index 5c5e1bb5..b9f4f42 100644
>> --- a/drivers/usb/phy/samsung-usbphy.c
>> +++ b/drivers/usb/phy/samsung-usbphy.c
>> @@ -60,20 +60,42 @@
>> #define MHZ (1000*1000)
>> #endif
>>
>> +#define S3C64XX_USBPHY_ENABLE (0x1<< 16)
>> +#define EXYNOS_USBPHY_ENABLE (0x1<< 0)
>> +
>> enum samsung_cpu_type {
>> TYPE_S3C64XX,
>> TYPE_EXYNOS4210,
>> };
>>
>> /*
>> + * struct samsung_usbphy_drvdata - driver data for various SoC variants
>> + * @cpu_type: machine identifier
>> + * @devphy_en_mask: device phy enable mask for PHY CONTROL register
>> + *
>> + * Here we have a separate mask for device type phy.
>> + * Having different masks for host and device type phy helps
>> + * in setting independent masks in case of SoCs like S5PV210,
>> + * in which PHY0 and PHY1 enable bits belong to same register
>> + * placed at [0] and [1] respectively.
>
>
> "and are placed at positions 0 and 1 respectively" ?
>
Ok, will change this.
>
>> + * Although for newer SoCs like exynos these bits belong to
>> + * different registers altogether placed at [0].
>> + */
>> +struct samsung_usbphy_drvdata {
>> + int cpu_type;
>> + int devphy_en_mask;
>> +};
>> +
>> +/*
>> * struct samsung_usbphy - transceiver driver state
>> * @phy: transceiver structure
>> * @plat: platform data
>> * @dev: The parent device supplied to the probe function
>> * @clk: usb phy clock
>> * @regs: usb phy register memory base
>> + * @phyctrl_pmureg: usb device phy-control pmu register memory base
>
>
> nit: Perhaps we could just call it "pmureg' ?
>
Sure we can use the name 'pmureg'.
>
>> * @ref_clk_freq: reference clock frequency selection
>> - * @cpu_type: machine identifier
>> + * @drv_data: driver data available for different cpu types
>
>
> Actually it's for different SoCs, not CPUs, right ?
>
Right, will change this.
>
>> */
>> struct samsung_usbphy {
>> struct usb_phy phy;
>> @@ -81,12 +103,67 @@ struct samsung_usbphy {
>> struct device *dev;
>> struct clk *clk;
>> void __iomem *regs;
>> + void __iomem *phyctrl_pmureg;
>> int ref_clk_freq;
>> - int cpu_type;
>> + const struct samsung_usbphy_drvdata *drv_data;
>> };
>>
>> #define phy_to_sphy(x) container_of((x), struct
>> samsung_usbphy, phy)
>>
>> +static int samsung_usbphy_parse_dt_param(struct samsung_usbphy *sphy)
>
>
> nit: s/samsung_usbphy_parse_dt_param/samsung_usbphy_parse_dt ?
>
Ok, will change this.
>
>> +{
>> + struct device_node *usbphy_pmu;
>> + u32 reg[2];
>> + int ret;
>> +
>> + if (!sphy->dev->of_node) {
>> + dev_err(sphy->dev, "Can't get usb-phy node\n");
>> + return -ENODEV;
>
>
> The function is called only when dev->of_node is not NULL, so this path
> is never executed, AFAICS. I would just drop this redundant check.
>
Yes, thanks for pointing out. I missed that. Will remove this check.
>
>> + }
>> +
>> + usbphy_pmu = of_get_child_by_name(sphy->dev->of_node,
>> "usbphy-pmu");
>> + if (!usbphy_pmu)
>> + dev_warn(sphy->dev, "Can't get usb-phy pmu control
>> node\n");
>
>
>> + ret = of_property_read_u32_array(usbphy_pmu, "reg", reg,
>>
>> + ARRAY_SIZE(reg));
>> + if (!ret)
>> + sphy->phyctrl_pmureg = ioremap(reg[0], reg[1]);
>
>
> I don't think this is correct. reg is not really an array of u32 type,
> it's an array of address/size tuples. I thought you would use of_iomap()
> here. Any reason why you didn't do so ? It would also make it easier to
> handle multiple address/size pairs if required.
>
True we should in fact be using of_iomap. Will change this accordingly.
>
>> +
>> + of_node_put(usbphy_pmu);
>> +
>> + if (IS_ERR_OR_NULL(sphy->phyctrl_pmureg)) {
>
>
> When is sphy->phyctrl_pmureg assigned a ERR_PTR() value ? Wouldn't it
> be enough to simply check for NULL ?
>
Yes, true no error returned here, will check this against NULL.
>
>> + dev_err(sphy->dev, "Can't get usb-phy pmu control
>> register\n");
>> + return -ENODEV;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +/*
>> + * Set isolation here for phy.
>> + * SOCs control this by controlling corresponding PMU registers
>> + */
>> +static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, int
>> on)
>> +{
>> + u32 reg;
>> + int en_mask;
>> +
>> + if (!sphy->phyctrl_pmureg) {
>> + dev_warn(sphy->dev, "Can't set pmu isolation\n");
>> + return;
>> + }
>> +
>> + reg = readl(sphy->phyctrl_pmureg);
>
>
> To make it more generic maybe it's worth to store an offset to the actual
> register somewhere, e.g. in the driver_data struct ? This function is
> supposed to handle both device and host PHYs, isn't it ?
>
True we can make put an offset for host and device PHYs.
So we iomap the memory base address of the first register (i.e. device
PHY in exynos4210),
and then use an offset for other register (i.e.host PHY). Right?
>> + en_mask = sphy->drv_data->devphy_en_mask;
>> +
>> + if (on)
>> + writel(reg& ~en_mask, sphy->phyctrl_pmureg);
>>
>> + else
>> + writel(reg | en_mask, sphy->phyctrl_pmureg);
>
>
> nit: This could be also written as:
>
> reg = on ? reg & ~mask : reg | mask;
> writel(reg, sphy->phyctrl_pmureg);
Sure will amend this.
--
Thanks & Regards
Vivek
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v5] usb: phy: samsung: Add support to set pmu isolation
2012-12-27 12:01 ` Vivek Gautam
@ 2012-12-28 9:13 ` Vivek Gautam
[not found] ` <1356686018-18586-1-git-send-email-gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2013-01-09 21:42 ` Sylwester Nawrocki
0 siblings, 2 replies; 12+ messages in thread
From: Vivek Gautam @ 2012-12-28 9:13 UTC (permalink / raw)
To: linux-usb
Cc: devicetree-discuss, linux-arm-kernel, linux-kernel,
linux-samsung-soc, linux, gregkh, balbi, kgene.kim,
sylvester.nawrocki, thomas.abraham, t.figa, ben-linux, broonie,
l.majewski, kyungmin.park, grant.likely, heiko, dianders,
p.paneri
Adding support to parse device node data in order to get
required properties to set pmu isolation for usb-phy.
Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
---
Changes from v4:
- Added 'ranges' property to usbphy node, to iomap the child nodes's
address space.
- Using offset for device phy control register to make it more generic.
- Using of_iomap() to map register for child node.
- Removing buggy check for IS_ERR_OR_NULL for ioremapped address, instead
checking it against NULL.
- Adding spin_lock around read-modify-write block in
samsung_usbphy_set_isolation().
- removing unnecessary casting for match->data.
.../devicetree/bindings/usb/samsung-usbphy.txt | 35 +++++
drivers/usb/phy/samsung-usbphy.c | 145 +++++++++++++++++---
2 files changed, 159 insertions(+), 21 deletions(-)
diff --git a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
index 7b26e2d..1b97765 100644
--- a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
+++ b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
@@ -9,3 +9,38 @@ Required properties:
- compatible : should be "samsung,exynos4210-usbphy"
- reg : base physical address of the phy registers and length of memory mapped
region.
+
+Optional properties:
+- #address-cells: should be '1' when usbphy node has a child node with 'reg'
+ property.
+- #size-cells: should be '1' when usbphy node has a child node with 'reg'
+ property.
+- ranges: allows valid translation between child's address space and parent's
+ address space.
+
+- The child node 'usbphy-sys' to the node 'usbphy' is for the system controller
+ interface for usb-phy. It should provide the following information required by
+ usb-phy controller to control phy.
+ - reg : base physical address of PHY control register in PMU which
+ enables/disables the phy controller.
+ The size of this register is the total sum of size of all phy-control
+ registers that the SoC has. For example, the size will be
+ '0x4' in case we have only one phy-control register (like in S3C64XX) or
+ '0x8' in case we have two phy-control registers (like in Exynos4210)
+ and so on.
+
+Example:
+ - Exynos4210
+
+ usbphy@125B0000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "samsung,exynos4210-usbphy";
+ reg = <0x125B0000 0x100>;
+ ranges;
+
+ usbphy-sys {
+ /* USB device and host PHY_CONTROL registers */
+ reg = <0x10020704 0x8>;
+ };
+ };
diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/samsung-usbphy.c
index 5c5e1bb5..99e16e9 100644
--- a/drivers/usb/phy/samsung-usbphy.c
+++ b/drivers/usb/phy/samsung-usbphy.c
@@ -24,6 +24,7 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/usb/otg.h>
#include <linux/platform_data/samsung-usbphy.h>
@@ -60,20 +61,45 @@
#define MHZ (1000*1000)
#endif
+#define S3C64XX_USBPHY_ENABLE (0x1 << 16)
+#define EXYNOS_USBPHY_ENABLE (0x1 << 0)
+
enum samsung_cpu_type {
TYPE_S3C64XX,
TYPE_EXYNOS4210,
};
/*
+ * struct samsung_usbphy_drvdata - driver data for various SoC variants
+ * @cpu_type: machine identifier
+ * @devphy_en_mask: device phy enable mask for PHY CONTROL register
+ * @pmureg_devphy_offset: offset to DEVICE PHY CONTROL register from
+ * mapped address of system controller.
+ *
+ * Here we have a separate mask for device type phy.
+ * Having different masks for host and device type phy helps
+ * in setting independent masks in case of SoCs like S5PV210,
+ * in which PHY0 and PHY1 enable bits belong to same register
+ * placed at position 0 and 1 respectively.
+ * Although for newer SoCs like exynos these bits belong to
+ * different registers altogether placed at position 0.
+ */
+struct samsung_usbphy_drvdata {
+ int cpu_type;
+ int devphy_en_mask;
+ u32 pmureg_devphy_offset;
+};
+
+/*
* struct samsung_usbphy - transceiver driver state
* @phy: transceiver structure
* @plat: platform data
* @dev: The parent device supplied to the probe function
* @clk: usb phy clock
* @regs: usb phy register memory base
+ * @pmureg: usb device phy-control pmu register memory base
* @ref_clk_freq: reference clock frequency selection
- * @cpu_type: machine identifier
+ * @drv_data: driver data available for different SoCs
*/
struct samsung_usbphy {
struct usb_phy phy;
@@ -81,12 +107,63 @@ struct samsung_usbphy {
struct device *dev;
struct clk *clk;
void __iomem *regs;
+ void __iomem *pmureg;
int ref_clk_freq;
- int cpu_type;
+ const struct samsung_usbphy_drvdata *drv_data;
};
#define phy_to_sphy(x) container_of((x), struct samsung_usbphy, phy)
+static int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
+{
+ struct device_node *usbphy_sys;
+
+ /* Getting node for system controller interface for usb-phy */
+ usbphy_sys = of_get_child_by_name(sphy->dev->of_node, "usbphy-sys");
+ if (!usbphy_sys)
+ dev_warn(sphy->dev, "No sys-controller interface for usb-phy\n");
+
+ sphy->pmureg = of_iomap(usbphy_sys, 0);
+
+ of_node_put(usbphy_sys);
+
+ if (sphy->pmureg == NULL) {
+ dev_err(sphy->dev, "Can't get usb-phy pmu control register\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/*
+ * Set isolation here for phy.
+ * SOCs control this by controlling corresponding PMU registers
+ */
+static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, int on)
+{
+ static DEFINE_SPINLOCK(lock);
+ unsigned long flags;
+ void __iomem *reg;
+ u32 reg_val;
+ u32 en_mask;
+
+ if (!sphy->pmureg) {
+ dev_warn(sphy->dev, "Can't set pmu isolation\n");
+ return;
+ }
+
+ reg = sphy->pmureg + sphy->drv_data->pmureg_devphy_offset;
+ en_mask = sphy->drv_data->devphy_en_mask;
+
+ spin_lock_irqsave(&lock, flags);
+
+ reg_val = readl(reg);
+ reg_val = on ? (reg_val & ~en_mask) : (reg_val | en_mask);
+ writel(reg_val, reg);
+
+ spin_unlock_irqrestore(&lock, flags);
+}
+
/*
* Returns reference clock frequency selection value
*/
@@ -112,7 +189,7 @@ static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
refclk_freq = PHYCLK_CLKSEL_48M;
break;
default:
- if (sphy->cpu_type == TYPE_S3C64XX)
+ if (sphy->drv_data->cpu_type == TYPE_S3C64XX)
refclk_freq = PHYCLK_CLKSEL_48M;
else
refclk_freq = PHYCLK_CLKSEL_24M;
@@ -135,7 +212,7 @@ static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
phypwr = readl(regs + SAMSUNG_PHYPWR);
rstcon = readl(regs + SAMSUNG_RSTCON);
- switch (sphy->cpu_type) {
+ switch (sphy->drv_data->cpu_type) {
case TYPE_S3C64XX:
phyclk &= ~PHYCLK_COMMON_ON_N;
phypwr &= ~PHYPWR_NORMAL_MASK;
@@ -165,7 +242,7 @@ static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
phypwr = readl(regs + SAMSUNG_PHYPWR);
- switch (sphy->cpu_type) {
+ switch (sphy->drv_data->cpu_type) {
case TYPE_S3C64XX:
phypwr |= PHYPWR_NORMAL_MASK;
break;
@@ -199,6 +276,8 @@ static int samsung_usbphy_init(struct usb_phy *phy)
/* Disable phy isolation */
if (sphy->plat && sphy->plat->pmu_isolation)
sphy->plat->pmu_isolation(false);
+ else
+ samsung_usbphy_set_isolation(sphy, false);
/* Initialize usb phy registers */
samsung_usbphy_enable(sphy);
@@ -228,38 +307,37 @@ static void samsung_usbphy_shutdown(struct usb_phy *phy)
/* Enable phy isolation */
if (sphy->plat && sphy->plat->pmu_isolation)
sphy->plat->pmu_isolation(true);
+ else
+ samsung_usbphy_set_isolation(sphy, true);
clk_disable_unprepare(sphy->clk);
}
static const struct of_device_id samsung_usbphy_dt_match[];
-static inline int samsung_usbphy_get_driver_data(struct platform_device *pdev)
+static inline const struct samsung_usbphy_drvdata
+*samsung_usbphy_get_driver_data(struct platform_device *pdev)
{
if (pdev->dev.of_node) {
const struct of_device_id *match;
match = of_match_node(samsung_usbphy_dt_match,
pdev->dev.of_node);
- return (int) match->data;
+ return match->data;
}
- return platform_get_device_id(pdev)->driver_data;
+ return (struct samsung_usbphy_drvdata *)
+ platform_get_device_id(pdev)->driver_data;
}
static int __devinit samsung_usbphy_probe(struct platform_device *pdev)
{
struct samsung_usbphy *sphy;
- struct samsung_usbphy_data *pdata;
+ struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
struct device *dev = &pdev->dev;
struct resource *phy_mem;
void __iomem *phy_base;
struct clk *clk;
-
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_err(&pdev->dev, "%s: no platform data defined\n", __func__);
- return -EINVAL;
- }
+ int ret;
phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!phy_mem) {
@@ -283,7 +361,19 @@ static int __devinit samsung_usbphy_probe(struct platform_device *pdev)
return PTR_ERR(clk);
}
- sphy->dev = &pdev->dev;
+ sphy->dev = dev;
+
+ if (dev->of_node) {
+ ret = samsung_usbphy_parse_dt(sphy);
+ if (ret < 0)
+ return ret;
+ } else {
+ if (!pdata) {
+ dev_err(dev, "no platform data specified\n");
+ return -EINVAL;
+ }
+ }
+
sphy->plat = pdata;
sphy->regs = phy_base;
sphy->clk = clk;
@@ -291,7 +381,7 @@ static int __devinit samsung_usbphy_probe(struct platform_device *pdev)
sphy->phy.label = "samsung-usbphy";
sphy->phy.init = samsung_usbphy_init;
sphy->phy.shutdown = samsung_usbphy_shutdown;
- sphy->cpu_type = samsung_usbphy_get_driver_data(pdev);
+ sphy->drv_data = samsung_usbphy_get_driver_data(pdev);
sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy);
platform_set_drvdata(pdev, sphy);
@@ -305,17 +395,30 @@ static int __exit samsung_usbphy_remove(struct platform_device *pdev)
usb_remove_phy(&sphy->phy);
+ if (sphy->pmureg)
+ iounmap(sphy->pmureg);
+
return 0;
}
+static const struct samsung_usbphy_drvdata usbphy_s3c64xx = {
+ .cpu_type = TYPE_S3C64XX,
+ .devphy_en_mask = S3C64XX_USBPHY_ENABLE,
+};
+
+static const struct samsung_usbphy_drvdata usbphy_exynos4 = {
+ .cpu_type = TYPE_EXYNOS4210,
+ .devphy_en_mask = EXYNOS_USBPHY_ENABLE,
+};
+
#ifdef CONFIG_OF
static const struct of_device_id samsung_usbphy_dt_match[] = {
{
.compatible = "samsung,s3c64xx-usbphy",
- .data = (void *)TYPE_S3C64XX,
+ .data = &usbphy_s3c64xx,
}, {
.compatible = "samsung,exynos4210-usbphy",
- .data = (void *)TYPE_EXYNOS4210,
+ .data = &usbphy_exynos4,
},
{},
};
@@ -325,10 +428,10 @@ MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
static struct platform_device_id samsung_usbphy_driver_ids[] = {
{
.name = "s3c64xx-usbphy",
- .driver_data = TYPE_S3C64XX,
+ .driver_data = (unsigned long)&usbphy_s3c64xx,
}, {
.name = "exynos4210-usbphy",
- .driver_data = TYPE_EXYNOS4210,
+ .driver_data = (unsigned long)&usbphy_exynos4,
},
{},
};
--
1.7.6.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v5] usb: phy: samsung: Add support to set pmu isolation
[not found] ` <1356686018-18586-1-git-send-email-gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
@ 2013-01-04 6:29 ` Vivek Gautam
0 siblings, 0 replies; 12+ messages in thread
From: Vivek Gautam @ 2013-01-04 6:29 UTC (permalink / raw)
To: linux-usb-u79uwXL29TY76Z2rM5mHXA
Cc: l.majewski-Sze3O3UU22JBDgjK7y7TUQ,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-lFZ/pmaqli7XmaaqVzeoHQ, Praveen Paneri,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
broonie-yzvPICuk2AATkU/dhu1WVueM+bqZidxxQQ4Iyu8u01E,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, balbi-l0cyMroinI0,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ, Vivek Gautam,
ben-linux-elnMNo+KYs3YtjvyW6yDsg,
sylvester.nawrocki-Re5JQEeQqe8AvxtiuMwx3w,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Hi,
On Fri, Dec 28, 2012 at 2:43 PM, Vivek Gautam <gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> wrote:
> Adding support to parse device node data in order to get
> required properties to set pmu isolation for usb-phy.
>
> Signed-off-by: Vivek Gautam <gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> ---
>
Any further comments on this ? Or does this seem fine ?
--
Thanks & Regards
Vivek
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v5] usb: phy: samsung: Add support to set pmu isolation
2012-12-28 9:13 ` [PATCH v5] " Vivek Gautam
[not found] ` <1356686018-18586-1-git-send-email-gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
@ 2013-01-09 21:42 ` Sylwester Nawrocki
2013-01-10 8:48 ` Vivek Gautam
1 sibling, 1 reply; 12+ messages in thread
From: Sylwester Nawrocki @ 2013-01-09 21:42 UTC (permalink / raw)
To: Vivek Gautam
Cc: linux-usb, devicetree-discuss, linux-arm-kernel, linux-kernel,
linux-samsung-soc, linux, gregkh, balbi, kgene.kim,
thomas.abraham, t.figa, ben-linux, broonie, l.majewski,
kyungmin.park, grant.likely, heiko, dianders, p.paneri
Hi,
On 12/28/2012 10:13 AM, Vivek Gautam wrote:
> Adding support to parse device node data in order to get
> required properties to set pmu isolation for usb-phy.
>
> Signed-off-by: Vivek Gautam<gautam.vivek@samsung.com>
...
> --- a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
> +++ b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
> @@ -9,3 +9,38 @@ Required properties:
> - compatible : should be "samsung,exynos4210-usbphy"
> - reg : base physical address of the phy registers and length of memory mapped
> region.
> +
> +Optional properties:
> +- #address-cells: should be '1' when usbphy node has a child node with 'reg'
> + property.
> +- #size-cells: should be '1' when usbphy node has a child node with 'reg'
> + property.
> +- ranges: allows valid translation between child's address space and parent's
> + address space.
> +
> +- The child node 'usbphy-sys' to the node 'usbphy' is for the system controller
> + interface for usb-phy. It should provide the following information required by
> + usb-phy controller to control phy.
> + - reg : base physical address of PHY control register in PMU which
> + enables/disables the phy controller.
On some SoCs USB_PHY_CONTROL registers don't belong to PMU. So maybe you
should
drop references to PMU, or list all SoC entities where USB_PHY_CONTROL
appears:
PMU, "MISC REGISTER", etc.
I would just rephrase this to:
- reg : base physical address of PHY_CONTROL registers
"phy controller" might be confusing, since PHY CONTROLLER is an entity
separate
from PHY 0 and PHY 1 ?
> + The size of this register is the total sum of size of all phy-control
And what about using PHY_CONTROL name as per the User Manuals ? That would
perhaps make it a bit easier to follow.
> + registers that the SoC has. For example, the size will be
> + '0x4' in case we have only one phy-control register (like in S3C64XX) or
> + '0x8' in case we have two phy-control registers (like in Exynos4210)
> + and so on.
> +
> +Example:
> + - Exynos4210
> +
> + usbphy@125B0000 {
> + #address-cells =<1>;
> + #size-cells =<1>;
> + compatible = "samsung,exynos4210-usbphy";
> + reg =<0x125B0000 0x100>;
> + ranges;
> +
> + usbphy-sys {
> + /* USB device and host PHY_CONTROL registers */
> + reg =<0x10020704 0x8>;
> + };
> + };
...
> /*
> + * struct samsung_usbphy_drvdata - driver data for various SoC variants
> + * @cpu_type: machine identifier
> + * @devphy_en_mask: device phy enable mask for PHY CONTROL register
> + * @pmureg_devphy_offset: offset to DEVICE PHY CONTROL register from
> + * mapped address of system controller.
> + *
> + * Here we have a separate mask for device type phy.
> + * Having different masks for host and device type phy helps
> + * in setting independent masks in case of SoCs like S5PV210,
> + * in which PHY0 and PHY1 enable bits belong to same register
> + * placed at position 0 and 1 respectively.
> + * Although for newer SoCs like exynos these bits belong to
> + * different registers altogether placed at position 0.
> + */
> +struct samsung_usbphy_drvdata {
> + int cpu_type;
> + int devphy_en_mask;
> + u32 pmureg_devphy_offset;
Perhaps just "devphy_reg_offset" would do ?
> +};
> +
> +/*
> * struct samsung_usbphy - transceiver driver state
> * @phy: transceiver structure
> * @plat: platform data
> * @dev: The parent device supplied to the probe function
> * @clk: usb phy clock
> * @regs: usb phy register memory base
Is this more precisely:
* @regs: usb phy controller registers memory base
?
> + * @pmureg: usb device phy-control pmu register memory base
Maybe something like this would be more clear:
@pmureg: USB device PHY_CONTROL registers memory region base
Note, that not on all SoCs USB_PHY_CONTROL registers belong to PMU.
Haven't you considered changing "pmureg" to ctrl_regs or something
else more generic ?
> * @ref_clk_freq: reference clock frequency selection
> - * @cpu_type: machine identifier
> + * @drv_data: driver data available for different SoCs
> */
> struct samsung_usbphy {
> struct usb_phy phy;
> @@ -81,12 +107,63 @@ struct samsung_usbphy {
> struct device *dev;
> struct clk *clk;
> void __iomem *regs;
> + void __iomem *pmureg;
> int ref_clk_freq;
> - int cpu_type;
> + const struct samsung_usbphy_drvdata *drv_data;
> };
...
> +/*
> + * Set isolation here for phy.
> + * SOCs control this by controlling corresponding PMU registers
Hmm, it's not always PMU registers. I would remove this sentence and
instead explain what's the meaning of 'on' argument, so it is clear
the PHY is deactivated when on != 0.
> + */
> +static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, int on)
> +{
> + static DEFINE_SPINLOCK(lock);
You probably don't need a global spinlock. Couldn't the spinlock be added
as struct samsung_usbhy field instead ?
> + unsigned long flags;
> + void __iomem *reg;
> + u32 reg_val;
> + u32 en_mask;
> +
> + if (!sphy->pmureg) {
> + dev_warn(sphy->dev, "Can't set pmu isolation\n");
> + return;
> + }
> +
> + reg = sphy->pmureg + sphy->drv_data->pmureg_devphy_offset;
> + en_mask = sphy->drv_data->devphy_en_mask;
> +
> + spin_lock_irqsave(&lock, flags);
> +
> + reg_val = readl(reg);
> + reg_val = on ? (reg_val& ~en_mask) : (reg_val | en_mask);
Might be a good idea to use in this case plain if/else instead..
> + writel(reg_val, reg);
> +
> + spin_unlock_irqrestore(&lock, flags);
> +}
Thanks,
Sylwester
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v5] usb: phy: samsung: Add support to set pmu isolation
2013-01-09 21:42 ` Sylwester Nawrocki
@ 2013-01-10 8:48 ` Vivek Gautam
0 siblings, 0 replies; 12+ messages in thread
From: Vivek Gautam @ 2013-01-10 8:48 UTC (permalink / raw)
To: Sylwester Nawrocki
Cc: Vivek Gautam, linux-usb, devicetree-discuss, linux-arm-kernel,
linux-kernel, linux-samsung-soc, linux, gregkh, balbi, kgene.kim,
thomas.abraham, t.figa, ben-linux, broonie, l.majewski,
kyungmin.park, grant.likely, heiko, dianders, p.paneri
Hi Sylwester,
On Thu, Jan 10, 2013 at 3:12 AM, Sylwester Nawrocki
<sylvester.nawrocki@gmail.com> wrote:
> Hi,
>
>
> On 12/28/2012 10:13 AM, Vivek Gautam wrote:
>>
>> Adding support to parse device node data in order to get
>> required properties to set pmu isolation for usb-phy.
>>
>> Signed-off-by: Vivek Gautam<gautam.vivek@samsung.com>
>
> ...
>
>> --- a/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
>> +++ b/Documentation/devicetree/bindings/usb/samsung-usbphy.txt
>> @@ -9,3 +9,38 @@ Required properties:
>> - compatible : should be "samsung,exynos4210-usbphy"
>> - reg : base physical address of the phy registers and length of memory
>> mapped
>> region.
>> +
>> +Optional properties:
>> +- #address-cells: should be '1' when usbphy node has a child node with
>> 'reg'
>> + property.
>> +- #size-cells: should be '1' when usbphy node has a child node with 'reg'
>> + property.
>> +- ranges: allows valid translation between child's address space and
>> parent's
>> + address space.
>> +
>> +- The child node 'usbphy-sys' to the node 'usbphy' is for the system
>> controller
>> + interface for usb-phy. It should provide the following information
>> required by
>> + usb-phy controller to control phy.
>> + - reg : base physical address of PHY control register in PMU which
>> + enables/disables the phy controller.
>
>
> On some SoCs USB_PHY_CONTROL registers don't belong to PMU. So maybe you
> should
> drop references to PMU, or list all SoC entities where USB_PHY_CONTROL
> appears:
> PMU, "MISC REGISTER", etc.
>
On S3C64XX "USB_SIG_MASK" bit is in "OTHERS" register, which is actually part of
system controller register map (clock controller + PM controller), and
then S5P64XX onward
this falls under PM controller's memory map. So, i thought of using
reference to PMU.
May be i am missing something here ?
Will change this if you suggest.
> I would just rephrase this to:
>
> - reg : base physical address of PHY_CONTROL registers
>
> "phy controller" might be confusing, since PHY CONTROLLER is an entity
> separate
> from PHY 0 and PHY 1 ?
>
Ok, will change this as suggested.
>
>> + The size of this register is the total sum of size of all
>> phy-control
>
>
> And what about using PHY_CONTROL name as per the User Manuals ? That would
> perhaps make it a bit easier to follow.
>
Sure this is better. We can use PHY_CONTROL to align with user manuals and avoid
any confusions.
>
>> + registers that the SoC has. For example, the size will be
>> + '0x4' in case we have only one phy-control register (like in
>> S3C64XX) or
>> + '0x8' in case we have two phy-control registers (like in
>> Exynos4210)
>> + and so on.
>> +
>> +Example:
>> + - Exynos4210
>> +
>> + usbphy@125B0000 {
>> + #address-cells =<1>;
>> + #size-cells =<1>;
>> + compatible = "samsung,exynos4210-usbphy";
>> + reg =<0x125B0000 0x100>;
>> + ranges;
>> +
>> + usbphy-sys {
>> + /* USB device and host PHY_CONTROL registers */
>> + reg =<0x10020704 0x8>;
>> + };
>> + };
>
> ...
>
>> /*
>> + * struct samsung_usbphy_drvdata - driver data for various SoC variants
>> + * @cpu_type: machine identifier
>> + * @devphy_en_mask: device phy enable mask for PHY CONTROL register
>> + * @pmureg_devphy_offset: offset to DEVICE PHY CONTROL register from
>> + * mapped address of system controller.
>> + *
>> + * Here we have a separate mask for device type phy.
>> + * Having different masks for host and device type phy helps
>> + * in setting independent masks in case of SoCs like S5PV210,
>> + * in which PHY0 and PHY1 enable bits belong to same register
>> + * placed at position 0 and 1 respectively.
>> + * Although for newer SoCs like exynos these bits belong to
>> + * different registers altogether placed at position 0.
>> + */
>> +struct samsung_usbphy_drvdata {
>> + int cpu_type;
>> + int devphy_en_mask;
>> + u32 pmureg_devphy_offset;
>
>
> Perhaps just "devphy_reg_offset" would do ?
>
Sure, will amend this as suggested.
>
>> +};
>> +
>> +/*
>> * struct samsung_usbphy - transceiver driver state
>> * @phy: transceiver structure
>> * @plat: platform data
>> * @dev: The parent device supplied to the probe function
>> * @clk: usb phy clock
>> * @regs: usb phy register memory base
>
>
> Is this more precisely:
>
> * @regs: usb phy controller registers memory base
>
> ?
this had been a part of Praveen's work submitted for initial
samsung-usbphy driver,
so didn't change anything in that. ;-)
Will amend this as suggested.
>>
>> + * @pmureg: usb device phy-control pmu register memory base
>
>
> Maybe something like this would be more clear:
>
> @pmureg: USB device PHY_CONTROL registers memory region base
>
Sure, will amend this.
> Note, that not on all SoCs USB_PHY_CONTROL registers belong to PMU.
> Haven't you considered changing "pmureg" to ctrl_regs or something
> else more generic ?
>
Same as mentioned in above comment in this context for PMU register.
Thought this could be self-explanatory for pmu interface to control phy.
Will change this if you suggest.
>
>> * @ref_clk_freq: reference clock frequency selection
>> - * @cpu_type: machine identifier
>> + * @drv_data: driver data available for different SoCs
>> */
>> struct samsung_usbphy {
>> struct usb_phy phy;
>> @@ -81,12 +107,63 @@ struct samsung_usbphy {
>> struct device *dev;
>> struct clk *clk;
>> void __iomem *regs;
>> + void __iomem *pmureg;
>> int ref_clk_freq;
>> - int cpu_type;
>> + const struct samsung_usbphy_drvdata *drv_data;
>> };
>
> ...
>
>> +/*
>> + * Set isolation here for phy.
>> + * SOCs control this by controlling corresponding PMU registers
>
>
> Hmm, it's not always PMU registers. I would remove this sentence and
> instead explain what's the meaning of 'on' argument, so it is clear
> the PHY is deactivated when on != 0.
>
Ditto for PMU register comment,
Will put an explanation for 'on' argument.
>
>> + */
>> +static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, int
>> on)
>> +{
>> + static DEFINE_SPINLOCK(lock);
>
>
> You probably don't need a global spinlock. Couldn't the spinlock be added
> as struct samsung_usbhy field instead ?
>
True, will add a spinlock in the samsung_usbphy structure.
>
>> + unsigned long flags;
>> + void __iomem *reg;
>> + u32 reg_val;
>> + u32 en_mask;
>> +
>> + if (!sphy->pmureg) {
>> + dev_warn(sphy->dev, "Can't set pmu isolation\n");
>> + return;
>> + }
>> +
>> + reg = sphy->pmureg + sphy->drv_data->pmureg_devphy_offset;
>> + en_mask = sphy->drv_data->devphy_en_mask;
>> +
>> + spin_lock_irqsave(&lock, flags);
>> +
>> + reg_val = readl(reg);
>> + reg_val = on ? (reg_val& ~en_mask) : (reg_val | en_mask);
>
>
> Might be a good idea to use in this case plain if/else instead..
>
ok, will amend this.
--
Thanks & Regards
Vivek
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2013-01-10 8:48 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-26 12:28 [PATCH v4] usb: phy: samsung: Add support to set pmu isolation Vivek Gautam
2012-12-26 12:28 ` Vivek Gautam
[not found] ` <1356524912-4736-2-git-send-email-gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2012-12-26 13:56 ` Vivek Gautam
[not found] ` <CAFp+6iEoy-d6gHBMAiNi0n+tE8iS7Hk=k92w8EWfT_r3eeN_UA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2012-12-26 23:05 ` Sylwester Nawrocki
2012-12-26 22:30 ` Sylwester Nawrocki
2012-12-27 12:01 ` Vivek Gautam
2012-12-28 9:13 ` [PATCH v5] " Vivek Gautam
[not found] ` <1356686018-18586-1-git-send-email-gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2013-01-04 6:29 ` Vivek Gautam
2013-01-09 21:42 ` Sylwester Nawrocki
2013-01-10 8:48 ` Vivek Gautam
2012-12-27 0:26 ` [PATCH v4] " Russell King - ARM Linux
2012-12-27 9:20 ` Vivek Gautam
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).