From 82ffb676c820629b7f1b62d15f6bc546f29a7025 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sun, 1 Mar 2015 22:31:34 +0800 Subject: phy: berlin-usb: Use PTR_ERR_OR_ZERO PTR_ERR_OR_ZERO simplifies the code. Signed-off-by: Axel Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-berlin-usb.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c index c8a8d53a6ece..9f7cc7eed292 100644 --- a/drivers/phy/phy-berlin-usb.c +++ b/drivers/phy/phy-berlin-usb.c @@ -202,10 +202,7 @@ static int phy_berlin_usb_probe(struct platform_device *pdev) phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - - return 0; + return PTR_ERR_OR_ZERO(phy_provider); } static struct platform_driver phy_berlin_usb_driver = { -- cgit v1.2.3 From 8fd0ea395f96b1419083f850190f175d5ddd98e9 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Mar 2015 09:33:38 +0800 Subject: phy: xgene: Use PTR_ERR_OR_ZERO Also remove unneeded goto and rc variable. Signed-off-by: Axel Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-xgene.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-xgene.c b/drivers/phy/phy-xgene.c index 29214a36ea28..bae9cccc08f0 100644 --- a/drivers/phy/phy-xgene.c +++ b/drivers/phy/phy-xgene.c @@ -1657,7 +1657,6 @@ static int xgene_phy_probe(struct platform_device *pdev) struct phy_provider *phy_provider; struct xgene_phy_ctx *ctx; struct resource *res; - int rc = 0; u32 default_spd[] = DEFAULT_SATA_SPD_SEL; u32 default_txboost_gain[] = DEFAULT_SATA_TXBOOST_GAIN; u32 default_txeye_direction[] = DEFAULT_SATA_TXEYEDIRECTION; @@ -1676,10 +1675,8 @@ static int xgene_phy_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ctx->sds_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(ctx->sds_base)) { - rc = PTR_ERR(ctx->sds_base); - goto error; - } + if (IS_ERR(ctx->sds_base)) + return PTR_ERR(ctx->sds_base); /* Retrieve optional clock */ ctx->clk = clk_get(&pdev->dev, NULL); @@ -1710,22 +1707,12 @@ static int xgene_phy_probe(struct platform_device *pdev) ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops); if (IS_ERR(ctx->phy)) { dev_dbg(&pdev->dev, "Failed to create PHY\n"); - rc = PTR_ERR(ctx->phy); - goto error; + return PTR_ERR(ctx->phy); } phy_set_drvdata(ctx->phy, ctx); - phy_provider = devm_of_phy_provider_register(ctx->dev, - xgene_phy_xlate); - if (IS_ERR(phy_provider)) { - rc = PTR_ERR(phy_provider); - goto error; - } - - return 0; - -error: - return rc; + phy_provider = devm_of_phy_provider_register(ctx->dev, xgene_phy_xlate); + return PTR_ERR_OR_ZERO(phy_provider); } static const struct of_device_id xgene_phy_of_match[] = { -- cgit v1.2.3 From f8f55393b2860a2a5c97ff3b18c6ee02cef021c4 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Mar 2015 09:40:41 +0800 Subject: phy: berlin-sata: Use devm_kcalloc at appropriate place Prefer devm_kcalloc over devm_kzalloc with multiply. Signed-off-by: Axel Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-berlin-sata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c index 099eee8851e5..6f3e06d687de 100644 --- a/drivers/phy/phy-berlin-sata.c +++ b/drivers/phy/phy-berlin-sata.c @@ -218,7 +218,7 @@ static int phy_berlin_sata_probe(struct platform_device *pdev) if (priv->nphys == 0) return -ENODEV; - priv->phys = devm_kzalloc(dev, priv->nphys * sizeof(*priv->phys), + priv->phys = devm_kcalloc(dev, priv->nphys, sizeof(*priv->phys), GFP_KERNEL); if (!priv->phys) return -ENOMEM; -- cgit v1.2.3 From 320c3fcec64a9e115a3d8a5d005d2fb21c15ef01 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Mar 2015 09:44:06 +0800 Subject: phy: miphy28lp: Use PTR_ERR_OR_ZERO PTR_ERR_OR_ZERO simplifies the code. Signed-off-by: Axel Lin Acked-by: Gabriel Fernandez Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-miphy28lp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c index 9b2848e6115d..174ffd037ef7 100644 --- a/drivers/phy/phy-miphy28lp.c +++ b/drivers/phy/phy-miphy28lp.c @@ -1258,10 +1258,7 @@ static int miphy28lp_probe(struct platform_device *pdev) } provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate); - if (IS_ERR(provider)) - return PTR_ERR(provider); - - return 0; + return PTR_ERR_OR_ZERO(provider); } static const struct of_device_id miphy28lp_of_match[] = { -- cgit v1.2.3 From 1f9ba767d5918796c7f32724777087f321fde30d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Mar 2015 18:18:45 +0800 Subject: phy: omap-control: Remove unneeded ifdef CONFIG_OF guard and of_match_ptr if !CONFIG_OF, the probe fails. This is a dt-only driver, so the ifdef CONFIG_OF guard and of_match_ptr are not needed. Signed-off-by: Axel Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-omap-control.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c index efe724f97e02..a7653d930e6b 100644 --- a/drivers/phy/phy-omap-control.c +++ b/drivers/phy/phy-omap-control.c @@ -216,7 +216,6 @@ void omap_control_usb_set_mode(struct device *dev, return; ctrl_phy = dev_get_drvdata(dev); - if (!ctrl_phy) { dev_err(dev, "Invalid control phy device\n"); return; @@ -241,8 +240,6 @@ void omap_control_usb_set_mode(struct device *dev, } EXPORT_SYMBOL_GPL(omap_control_usb_set_mode); -#ifdef CONFIG_OF - static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS; static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2; static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3; @@ -278,8 +275,6 @@ static const struct of_device_id omap_control_phy_id_table[] = { {}, }; MODULE_DEVICE_TABLE(of, omap_control_phy_id_table); -#endif - static int omap_control_phy_probe(struct platform_device *pdev) { @@ -287,8 +282,7 @@ static int omap_control_phy_probe(struct platform_device *pdev) const struct of_device_id *of_id; struct omap_control_phy *control_phy; - of_id = of_match_device(of_match_ptr(omap_control_phy_id_table), - &pdev->dev); + of_id = of_match_device(omap_control_phy_id_table, &pdev->dev); if (!of_id) return -EINVAL; @@ -344,7 +338,7 @@ static struct platform_driver omap_control_phy_driver = { .probe = omap_control_phy_probe, .driver = { .name = "omap-control-phy", - .of_match_table = of_match_ptr(omap_control_phy_id_table), + .of_match_table = omap_control_phy_id_table, }, }; -- cgit v1.2.3 From 52a4a72a1ad675b66ec241c0e33ee6e50df63a93 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Mar 2015 18:20:07 +0800 Subject: phy: omap-usb2: Remove unneeded ifdef CONFIG_OF guard and of_match_ptr if !CONFIG_OF, the probe fails. This is a dt-only driver, so the ifdef CONFIG_OF guard and of_match_ptr are not needed. Signed-off-by: Axel Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-omap-usb2.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c index 6f4aef3db248..18b33cedadba 100644 --- a/drivers/phy/phy-omap-usb2.c +++ b/drivers/phy/phy-omap-usb2.c @@ -144,7 +144,6 @@ static struct phy_ops ops = { .owner = THIS_MODULE, }; -#ifdef CONFIG_OF static const struct usb_phy_data omap_usb2_data = { .label = "omap_usb2", .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS, @@ -185,7 +184,6 @@ static const struct of_device_id omap_usb2_id_table[] = { {}, }; MODULE_DEVICE_TABLE(of, omap_usb2_id_table); -#endif static int omap_usb2_probe(struct platform_device *pdev) { @@ -200,7 +198,7 @@ static int omap_usb2_probe(struct platform_device *pdev) const struct of_device_id *of_id; struct usb_phy_data *phy_data; - of_id = of_match_device(of_match_ptr(omap_usb2_id_table), &pdev->dev); + of_id = of_match_device(omap_usb2_id_table, &pdev->dev); if (!of_id) return -EINVAL; @@ -377,7 +375,7 @@ static struct platform_driver omap_usb2_driver = { .driver = { .name = "omap-usb2", .pm = DEV_PM_OPS, - .of_match_table = of_match_ptr(omap_usb2_id_table), + .of_match_table = omap_usb2_id_table, }, }; -- cgit v1.2.3 From 298fe56ee2b9551ca8cd675e7a6ebaf1c03632f8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 5 Mar 2015 18:20:53 +0800 Subject: phy: ti-pipe3: Remove unneeded ifdef CONFIG_OF guard and of_match_ptr if !CONFIG_OF, the probe fails. This is a dt-only driver, so the ifdef CONFIG_OF guard and of_match_ptr are not needed. Signed-off-by: Axel Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-ti-pipe3.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c index 95c88f929f27..ad3fbc80e044 100644 --- a/drivers/phy/phy-ti-pipe3.c +++ b/drivers/phy/phy-ti-pipe3.c @@ -291,9 +291,7 @@ static struct phy_ops ops = { .owner = THIS_MODULE, }; -#ifdef CONFIG_OF static const struct of_device_id ti_pipe3_id_table[]; -#endif static int ti_pipe3_probe(struct platform_device *pdev) { @@ -315,8 +313,7 @@ static int ti_pipe3_probe(struct platform_device *pdev) spin_lock_init(&phy->lock); if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { - match = of_match_device(of_match_ptr(ti_pipe3_id_table), - &pdev->dev); + match = of_match_device(ti_pipe3_id_table, &pdev->dev); if (!match) return -EINVAL; @@ -574,7 +571,6 @@ static const struct dev_pm_ops ti_pipe3_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(ti_pipe3_suspend, ti_pipe3_resume) }; -#ifdef CONFIG_OF static const struct of_device_id ti_pipe3_id_table[] = { { .compatible = "ti,phy-usb3", @@ -594,7 +590,6 @@ static const struct of_device_id ti_pipe3_id_table[] = { {} }; MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); -#endif static struct platform_driver ti_pipe3_driver = { .probe = ti_pipe3_probe, @@ -602,7 +597,7 @@ static struct platform_driver ti_pipe3_driver = { .driver = { .name = "ti-pipe3", .pm = &ti_pipe3_pm_ops, - .of_match_table = of_match_ptr(ti_pipe3_id_table), + .of_match_table = ti_pipe3_id_table, }, }; -- cgit v1.2.3 From 739ae3452d0ee199b3cfe5e52214d9ccd8e358ea Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 10 Mar 2015 17:05:33 +0800 Subject: phy: berlin-usb: Set drvdata for phy and use it At the context where we have pointer to struct phy, it's useful to call phy_get_drvdata() to get the address of priv. With this change, we can remove the to_phy_berlin_usb_priv() macro and remove *phy from struct phy_berlin_usb_priv. Signed-off-by: Axel Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-berlin-usb.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c index 9f7cc7eed292..c6fc95b53083 100644 --- a/drivers/phy/phy-berlin-usb.c +++ b/drivers/phy/phy-berlin-usb.c @@ -103,9 +103,6 @@ #define MODE_TEST_EN BIT(11) #define ANA_TEST_DC_CTRL(x) ((x) << 12) -#define to_phy_berlin_usb_priv(p) \ - container_of((p), struct phy_berlin_usb_priv, phy) - static const u32 phy_berlin_pll_dividers[] = { /* Berlin 2 */ CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54), @@ -115,14 +112,13 @@ static const u32 phy_berlin_pll_dividers[] = { struct phy_berlin_usb_priv { void __iomem *base; - struct phy *phy; struct reset_control *rst_ctrl; u32 pll_divider; }; static int phy_berlin_usb_power_on(struct phy *phy) { - struct phy_berlin_usb_priv *priv = dev_get_drvdata(phy->dev.parent); + struct phy_berlin_usb_priv *priv = phy_get_drvdata(phy); reset_control_reset(priv->rst_ctrl); @@ -175,6 +171,7 @@ static int phy_berlin_usb_probe(struct platform_device *pdev) of_match_device(phy_berlin_sata_of_match, &pdev->dev); struct phy_berlin_usb_priv *priv; struct resource *res; + struct phy *phy; struct phy_provider *phy_provider; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); @@ -192,13 +189,14 @@ static int phy_berlin_usb_probe(struct platform_device *pdev) priv->pll_divider = *((u32 *)match->data); - priv->phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops); - if (IS_ERR(priv->phy)) { + phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops); + if (IS_ERR(phy)) { dev_err(&pdev->dev, "failed to create PHY\n"); - return PTR_ERR(priv->phy); + return PTR_ERR(phy); } platform_set_drvdata(pdev, priv); + phy_set_drvdata(phy, priv); phy_provider = devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate); -- cgit v1.2.3 From 080de5ba390c54b7504c43b36ae21911acf66b30 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Mar 2015 08:39:01 +0800 Subject: phy: stih41x-usb: Fixup stih41x_usb_phy_power_on failure path If stih41x_usb_phy_power_on() fails, we need to call clk_disable_unprepare() before return error. This is to ensure we have balanced clk_enable/disable calls. Signed-off-by: Axel Lin Acked-by: Patrice Chotard Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-stih41x-usb.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-stih41x-usb.c b/drivers/phy/phy-stih41x-usb.c index a603801293ff..c093b472b57d 100644 --- a/drivers/phy/phy-stih41x-usb.c +++ b/drivers/phy/phy-stih41x-usb.c @@ -87,8 +87,12 @@ static int stih41x_usb_phy_power_on(struct phy *phy) return ret; } - return regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, - phy_dev->cfg->oscok, phy_dev->cfg->oscok); + ret = regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, + phy_dev->cfg->oscok, phy_dev->cfg->oscok); + if (ret) + clk_disable_unprepare(phy_dev->clk); + + return ret; } static int stih41x_usb_phy_power_off(struct phy *phy) -- cgit v1.2.3 From d89a7f69d69409ffafad7affc1cc3085d2cd0dd8 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 3 Mar 2015 09:05:55 +0800 Subject: phy: qcom-ufs: Catch devm_phy_create failure in ufs_qcom_phy_generic_probe Current code does NULL test against return value of ufs_qcom_phy_generic_probe. However, in the case of devm_phy_create() failure, ufs_qcom_phy_generic_probe does not return NULL. Fix it. Signed-off-by: Axel Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-qcom-ufs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index 44ee983d57fe..d95effe3cdc1 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -101,6 +101,7 @@ struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, if (IS_ERR(generic_phy)) { err = PTR_ERR(generic_phy); dev_err(dev, "%s: failed to create phy %d\n", __func__, err); + generic_phy = NULL; goto out; } -- cgit v1.2.3 From 2be608561abfcceda4b35b71a0c1ec5088bb39b9 Mon Sep 17 00:00:00 2001 From: Jaewon Kim Date: Thu, 12 Mar 2015 19:11:13 +0900 Subject: phy: exynos5-usbdrd: Add to support for Exynos5433 SoC This patch adds driver data to support for Exynos5433 SoC. The Exynos5433 has one USB3.0 Host and USB3.0 DRD(Dual Role Device). Exynos5433 is simplar to Eyxnos7 but Exynos5433 have one more USB3.0 Host controller. Signed-off-by: Jaewon Kim Signed-off-by: Kishon Vijay Abraham I --- Documentation/devicetree/bindings/phy/samsung-phy.txt | 3 ++- drivers/phy/phy-exynos5-usbdrd.c | 10 ++++++++++ include/linux/mfd/syscon/exynos5-pmu.h | 3 +++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/phy') diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt index 91e38cfe1f8f..60c6f2a633e0 100644 --- a/Documentation/devicetree/bindings/phy/samsung-phy.txt +++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt @@ -128,6 +128,7 @@ Required properties: - compatible : Should be set to one of the following supported values: - "samsung,exynos5250-usbdrd-phy" - for exynos5250 SoC, - "samsung,exynos5420-usbdrd-phy" - for exynos5420 SoC. + - "samsung,exynos5433-usbdrd-phy" - for exynos5433 SoC. - "samsung,exynos7-usbdrd-phy" - for exynos7 SoC. - reg : Register offset and length of USB DRD PHY register set; - clocks: Clock IDs array as required by the controller @@ -139,7 +140,7 @@ Required properties: PHY operations, associated by phy name. It is used to determine bit values for clock settings register. For Exynos5420 this is given as 'sclk_usbphy30' in CMU. - - optional clocks: Exynos7 SoC has now following additional + - optional clocks: Exynos5433 & Exynos7 SoC has now following additional gate clocks available: - phy_pipe: for PIPE3 phy - phy_utmi: for UTMI+ phy diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c index 04374018425f..597e7dd3782a 100644 --- a/drivers/phy/phy-exynos5-usbdrd.c +++ b/drivers/phy/phy-exynos5-usbdrd.c @@ -624,6 +624,13 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = { .has_common_clk_gate = true, }; +static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = { + .phy_cfg = phy_cfg_exynos5, + .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, + .pmu_offset_usbdrd1_phy = EXYNOS5433_USBHOST30_PHY_CONTROL, + .has_common_clk_gate = false, +}; + static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = { .phy_cfg = phy_cfg_exynos5, .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, @@ -637,6 +644,9 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = { }, { .compatible = "samsung,exynos5420-usbdrd-phy", .data = &exynos5420_usbdrd_phy + }, { + .compatible = "samsung,exynos5433-usbdrd-phy", + .data = &exynos5433_usbdrd_phy }, { .compatible = "samsung,exynos7-usbdrd-phy", .data = &exynos7_usbdrd_phy diff --git a/include/linux/mfd/syscon/exynos5-pmu.h b/include/linux/mfd/syscon/exynos5-pmu.h index 00ef24bf6ede..9352adc95de6 100644 --- a/include/linux/mfd/syscon/exynos5-pmu.h +++ b/include/linux/mfd/syscon/exynos5-pmu.h @@ -36,6 +36,9 @@ #define EXYNOS5420_MTCADC_PHY_CONTROL (0x724) #define EXYNOS5420_DPTX_PHY_CONTROL (0x728) +/* Exynos5433 specific register definitions */ +#define EXYNOS5433_USBHOST30_PHY_CONTROL (0x728) + #define EXYNOS5_PHY_ENABLE BIT(0) #define EXYNOS5_MIPI_PHY_S_RESETN BIT(1) -- cgit v1.2.3 From 7a504c935e42737e5ad40ea2f6f2d21b4dc27e81 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 17 Mar 2015 08:42:38 +0800 Subject: phy: samsung_usb2: Fixup samsung_usb2_phy_power_on/off paths Ensure we have balanced clk_prepare_enable/clk_disable_unprepare calls if .power_on or .power_off callbacks return error. Signed-off-by: Axel Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-samsung-usb2.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c index 4a12f66b7fb5..55b6994932e3 100644 --- a/drivers/phy/phy-samsung-usb2.c +++ b/drivers/phy/phy-samsung-usb2.c @@ -37,10 +37,14 @@ static int samsung_usb2_phy_power_on(struct phy *phy) spin_lock(&drv->lock); ret = inst->cfg->power_on(inst); spin_unlock(&drv->lock); + if (ret) + goto err_power_on; } return 0; +err_power_on: + clk_disable_unprepare(drv->ref_clk); err_instance_clk: clk_disable_unprepare(drv->clk); err_main_clk: @@ -51,7 +55,7 @@ static int samsung_usb2_phy_power_off(struct phy *phy) { struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy); struct samsung_usb2_phy_driver *drv = inst->drv; - int ret = 0; + int ret; dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n", inst->cfg->label); @@ -59,10 +63,12 @@ static int samsung_usb2_phy_power_off(struct phy *phy) spin_lock(&drv->lock); ret = inst->cfg->power_off(inst); spin_unlock(&drv->lock); + if (ret) + return ret; } clk_disable_unprepare(drv->ref_clk); clk_disable_unprepare(drv->clk); - return ret; + return 0; } static struct phy_ops samsung_usb2_phy_ops = { -- cgit v1.2.3 From 358d6c87e73310c8e6564153cb556c0cd9e523fc Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 23 Mar 2015 11:54:50 +0800 Subject: phy: qcom-ufs: Fix build error due to missing export symbols Fix below build error when compile the driver as a module. ERROR: "ufs_qcom_phy_power_off" [drivers/phy/phy-qcom-ufs-qmp-20nm.ko] undefined! ERROR: "ufs_qcom_phy_power_on" [drivers/phy/phy-qcom-ufs-qmp-20nm.ko] undefined! ERROR: "ufs_qcom_phy_exit" [drivers/phy/phy-qcom-ufs-qmp-20nm.ko] undefined! ERROR: "ufs_qcom_phy_calibrate" [drivers/phy/phy-qcom-ufs-qmp-20nm.ko] undefined! ERROR: "ufs_qcom_phy_generic_probe" [drivers/phy/phy-qcom-ufs-qmp-20nm.ko] undefined! ERROR: "ufs_qcom_phy_init_vregulators" [drivers/phy/phy-qcom-ufs-qmp-20nm.ko] undefined! ERROR: "ufs_qcom_phy_init_clks" [drivers/phy/phy-qcom-ufs-qmp-20nm.ko] undefined! ERROR: "ufs_qcom_phy_remove" [drivers/phy/phy-qcom-ufs-qmp-20nm.ko] undefined! ERROR: "get_ufs_qcom_phy" [drivers/phy/phy-qcom-ufs-qmp-20nm.ko] undefined! ERROR: "ufs_qcom_phy_power_off" [drivers/phy/phy-qcom-ufs-qmp-14nm.ko] undefined! ERROR: "ufs_qcom_phy_power_on" [drivers/phy/phy-qcom-ufs-qmp-14nm.ko] undefined! ERROR: "ufs_qcom_phy_exit" [drivers/phy/phy-qcom-ufs-qmp-14nm.ko] undefined! ERROR: "ufs_qcom_phy_generic_probe" [drivers/phy/phy-qcom-ufs-qmp-14nm.ko] undefined! ERROR: "ufs_qcom_phy_init_vregulators" [drivers/phy/phy-qcom-ufs-qmp-14nm.ko] undefined! ERROR: "ufs_qcom_phy_init_clks" [drivers/phy/phy-qcom-ufs-qmp-14nm.ko] undefined! ERROR: "ufs_qcom_phy_calibrate" [drivers/phy/phy-qcom-ufs-qmp-14nm.ko] undefined! ERROR: "ufs_qcom_phy_remove" [drivers/phy/phy-qcom-ufs-qmp-14nm.ko] undefined! ERROR: "get_ufs_qcom_phy" [drivers/phy/phy-qcom-ufs-qmp-14nm.ko] undefined! make[1]: *** [__modpost] Error 1 make: *** [modules] Error 2 Signed-off-by: Axel Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-qcom-ufs.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index d95effe3cdc1..a149d92df656 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -73,6 +73,7 @@ int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy, out: return ret; } +EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate); struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, struct ufs_qcom_phy *common_cfg, @@ -111,6 +112,7 @@ struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, out: return generic_phy; } +EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe); /* * This assumes the embedded phy structure inside generic_phy is of type @@ -122,6 +124,7 @@ struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy) { return (struct ufs_qcom_phy *)phy_get_drvdata(generic_phy); } +EXPORT_SYMBOL_GPL(get_ufs_qcom_phy); static int ufs_qcom_phy_base_init(struct platform_device *pdev, @@ -229,6 +232,7 @@ ufs_qcom_phy_init_clks(struct phy *generic_phy, out: return err; } +EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_clks); int ufs_qcom_phy_init_vregulators(struct phy *generic_phy, @@ -253,6 +257,7 @@ ufs_qcom_phy_init_vregulators(struct phy *generic_phy, out: return err; } +EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_vregulators); static int __ufs_qcom_phy_init_vreg(struct phy *phy, struct ufs_qcom_phy_vreg *vreg, const char *name, bool optional) @@ -648,6 +653,7 @@ int ufs_qcom_phy_remove(struct phy *generic_phy, return 0; } +EXPORT_SYMBOL_GPL(ufs_qcom_phy_remove); int ufs_qcom_phy_exit(struct phy *generic_phy) { @@ -658,6 +664,7 @@ int ufs_qcom_phy_exit(struct phy *generic_phy) return 0; } +EXPORT_SYMBOL_GPL(ufs_qcom_phy_exit); int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy) { @@ -726,6 +733,7 @@ out_disable_phy: out: return err; } +EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_on); int ufs_qcom_phy_power_off(struct phy *generic_phy) { @@ -744,3 +752,4 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy) return 0; } +EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_off); -- cgit v1.2.3 From 52ea796b9161b1b81242e6831d9e128ee207ad2d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 23 Mar 2015 12:08:18 +0800 Subject: phy: qcom-ufs: Don't return error if fail to get optional resource "dev_ref_clk_ctrl_mem" is optional resource, so don't return error if fail to get the resource. Since it's an optional resource, don't emit error if fail to get dev_ref_clk_ctrl_mem. Also remove redundant test for res, it's done by devm_ioremap_resource(). Signed-off-by: Axel Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-qcom-ufs.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index a149d92df656..c4199e605ce2 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -135,40 +135,23 @@ int ufs_qcom_phy_base_init(struct platform_device *pdev, int err = 0; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_mem"); - if (!res) { - dev_err(dev, "%s: phy_mem resource not found\n", __func__); - err = -ENOMEM; - goto out; - } - phy_common->mmio = devm_ioremap_resource(dev, res); if (IS_ERR((void const *)phy_common->mmio)) { err = PTR_ERR((void const *)phy_common->mmio); phy_common->mmio = NULL; dev_err(dev, "%s: ioremap for phy_mem resource failed %d\n", __func__, err); - goto out; + return err; } /* "dev_ref_clk_ctrl_mem" is optional resource */ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dev_ref_clk_ctrl_mem"); - if (!res) { - dev_dbg(dev, "%s: dev_ref_clk_ctrl_mem resource not found\n", - __func__); - goto out; - } - phy_common->dev_ref_clk_ctrl_mmio = devm_ioremap_resource(dev, res); - if (IS_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio)) { - err = PTR_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio); + if (IS_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio)) phy_common->dev_ref_clk_ctrl_mmio = NULL; - dev_err(dev, "%s: ioremap for dev_ref_clk_ctrl_mem resource failed %d\n", - __func__, err); - } -out: - return err; + return 0; } static int __ufs_qcom_phy_clk_get(struct phy *phy, -- cgit v1.2.3 From 609adde838f4557f9d209b0432f4bac5c5eb5e86 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 19 Mar 2015 17:08:07 -0700 Subject: phy: Add a driver for dm816x USB PHY Add a minimal driver for dm816x USB. This makes USB work on dm816x without any other changes needed as it can use the existing musb_dsps glue layer for the USB controller. Note that this phy is different from dm814x and am335x. Cc: Bin Liu Cc: Brian Hutchinson Cc: Felipe Balbi Cc: Matthijs van Duin Cc: Paul Bolle Cc: Rusty Russell Signed-off-by: Tony Lindgren Signed-off-by: Kishon Vijay Abraham I --- .../devicetree/bindings/phy/dm816x-phy.txt | 24 ++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-dm816x-usb.c | 290 +++++++++++++++++++++ 4 files changed, 322 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/dm816x-phy.txt create mode 100644 drivers/phy/phy-dm816x-usb.c (limited to 'drivers/phy') diff --git a/Documentation/devicetree/bindings/phy/dm816x-phy.txt b/Documentation/devicetree/bindings/phy/dm816x-phy.txt new file mode 100644 index 000000000000..2fe3d11d063d --- /dev/null +++ b/Documentation/devicetree/bindings/phy/dm816x-phy.txt @@ -0,0 +1,24 @@ +Device tree binding documentation for am816x USB PHY +========================= + +Required properties: +- compatible : should be "ti,dm816x-usb-phy" +- reg : offset and length of the PHY register set. +- reg-names : name for the phy registers +- clocks : phandle to the clock +- clock-names : name of the clock +- syscon: phandle for the syscon node to access misc registers +- #phy-cells : from the generic PHY bindings, must be 1 +- syscon: phandle for the syscon node to access misc registers + +Example: + +usb_phy0: usb-phy@20 { + compatible = "ti,dm8168-usb-phy"; + reg = <0x20 0x8>; + reg-names = "phy"; + clocks = <&main_fapll 6>; + clock-names = "refclk"; + #phy-cells = <0>; + syscon = <&scm_conf>; +}; diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 2962de205ba7..885c39c28a8b 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -35,6 +35,13 @@ config ARMADA375_USBCLUSTER_PHY depends on OF select GENERIC_PHY +config PHY_DM816X_USB + tristate "TI dm816x USB PHY driver" + depends on ARCH_OMAP2PLUS + select GENERIC_PHY + help + Enable this for dm816x USB to work. + config PHY_EXYNOS_MIPI_VIDEO tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver" depends on HAS_IOMEM diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index f080e1bb2a74..dab6665ad9c1 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_GENERIC_PHY) += phy-core.o obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o +obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o diff --git a/drivers/phy/phy-dm816x-usb.c b/drivers/phy/phy-dm816x-usb.c new file mode 100644 index 000000000000..7b42555ddd51 --- /dev/null +++ b/drivers/phy/phy-dm816x-usb.c @@ -0,0 +1,290 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * TRM has two sets of USB_CTRL registers.. The correct register bits + * are in TRM section 24.9.8.2 USB_CTRL Register. The TRM documents the + * phy as being SR70LX Synopsys USB 2.0 OTG nanoPHY. It also seems at + * least dm816x rev c ignores writes to USB_CTRL register, but the TI + * kernel is writing to those so it's possible that later revisions + * have worknig USB_CTRL register. + * + * Also note that At least USB_CTRL register seems to be dm816x specific + * according to the TRM. It's possible that USBPHY_CTRL is more generic, + * but that would have to be checked against the SR70LX documentation + * which does not seem to be publicly available. + * + * Finally, the phy on dm814x and am335x is different from dm816x. + */ +#define DM816X_USB_CTRL_PHYCLKSRC BIT(8) /* 1 = PLL ref clock */ +#define DM816X_USB_CTRL_PHYSLEEP1 BIT(1) /* Enable the first phy */ +#define DM816X_USB_CTRL_PHYSLEEP0 BIT(0) /* Enable the second phy */ + +#define DM816X_USBPHY_CTRL_TXRISETUNE 1 +#define DM816X_USBPHY_CTRL_TXVREFTUNE 0xc +#define DM816X_USBPHY_CTRL_TXPREEMTUNE 0x2 + +struct dm816x_usb_phy { + struct regmap *syscon; + struct device *dev; + unsigned int instance; + struct clk *refclk; + struct usb_phy phy; + unsigned int usb_ctrl; /* Shared between phy0 and phy1 */ + unsigned int usbphy_ctrl; +}; + +static int dm816x_usb_phy_set_host(struct usb_otg *otg, struct usb_bus *host) +{ + otg->host = host; + if (!host) + otg->state = OTG_STATE_UNDEFINED; + + return 0; +} + +static int dm816x_usb_phy_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) +{ + otg->gadget = gadget; + if (!gadget) + otg->state = OTG_STATE_UNDEFINED; + + return 0; +} + +static int dm816x_usb_phy_init(struct phy *x) +{ + struct dm816x_usb_phy *phy = phy_get_drvdata(x); + unsigned int val; + int error; + + if (clk_get_rate(phy->refclk) != 24000000) + dev_warn(phy->dev, "nonstandard phy refclk\n"); + + /* Set PLL ref clock and put phys to sleep */ + error = regmap_update_bits(phy->syscon, phy->usb_ctrl, + DM816X_USB_CTRL_PHYCLKSRC | + DM816X_USB_CTRL_PHYSLEEP1 | + DM816X_USB_CTRL_PHYSLEEP0, + 0); + regmap_read(phy->syscon, phy->usb_ctrl, &val); + if ((val & 3) != 0) + dev_info(phy->dev, + "Working dm816x USB_CTRL! (0x%08x)\n", + val); + + /* + * TI kernel sets these values for "symmetrical eye diagram and + * better signal quality" so let's assume somebody checked the + * values with a scope and set them here too. + */ + regmap_read(phy->syscon, phy->usbphy_ctrl, &val); + val |= DM816X_USBPHY_CTRL_TXRISETUNE | + DM816X_USBPHY_CTRL_TXVREFTUNE | + DM816X_USBPHY_CTRL_TXPREEMTUNE; + regmap_write(phy->syscon, phy->usbphy_ctrl, val); + + return 0; +} + +static struct phy_ops ops = { + .init = dm816x_usb_phy_init, + .owner = THIS_MODULE, +}; + +static int dm816x_usb_phy_runtime_suspend(struct device *dev) +{ + struct dm816x_usb_phy *phy = dev_get_drvdata(dev); + unsigned int mask, val; + int error = 0; + + mask = BIT(phy->instance); + val = ~BIT(phy->instance); + error = regmap_update_bits(phy->syscon, phy->usb_ctrl, + mask, val); + if (error) + dev_err(phy->dev, "phy%i failed to power off\n", + phy->instance); + clk_disable(phy->refclk); + + return 0; +} + +static int dm816x_usb_phy_runtime_resume(struct device *dev) +{ + struct dm816x_usb_phy *phy = dev_get_drvdata(dev); + unsigned int mask, val; + int error; + + error = clk_enable(phy->refclk); + if (error) + return error; + + /* + * Note that at least dm816x rev c does not seem to do + * anything with the USB_CTRL register. But let's follow + * what the TI tree is doing in case later revisions use + * USB_CTRL. + */ + mask = BIT(phy->instance); + val = BIT(phy->instance); + error = regmap_update_bits(phy->syscon, phy->usb_ctrl, + mask, val); + if (error) { + dev_err(phy->dev, "phy%i failed to power on\n", + phy->instance); + clk_disable(phy->refclk); + return error; + } + + return 0; +} + +static UNIVERSAL_DEV_PM_OPS(dm816x_usb_phy_pm_ops, + dm816x_usb_phy_runtime_suspend, + dm816x_usb_phy_runtime_resume, + NULL); + +#ifdef CONFIG_OF +static const struct of_device_id dm816x_usb_phy_id_table[] = { + { + .compatible = "ti,dm8168-usb-phy", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, dm816x_usb_phy_id_table); +#endif + +static int dm816x_usb_phy_probe(struct platform_device *pdev) +{ + struct dm816x_usb_phy *phy; + struct resource *res; + struct phy *generic_phy; + struct phy_provider *phy_provider; + struct usb_otg *otg; + const struct of_device_id *of_id; + const struct usb_phy_data *phy_data; + int error; + + of_id = of_match_device(of_match_ptr(dm816x_usb_phy_id_table), + &pdev->dev); + if (!of_id) + return -EINVAL; + + phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); + if (!phy) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENOENT; + + phy->syscon = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "syscon"); + if (IS_ERR(phy->syscon)) + return PTR_ERR(phy->syscon); + + /* + * According to sprs614e.pdf, the first usb_ctrl is shared and + * the second instance for usb_ctrl is reserved.. Also the + * register bits are different from earlier TRMs. + */ + phy->usb_ctrl = 0x20; + phy->usbphy_ctrl = (res->start & 0xff) + 4; + if (phy->usbphy_ctrl == 0x2c) + phy->instance = 1; + + phy_data = of_id->data; + + otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL); + if (!otg) + return -ENOMEM; + + phy->dev = &pdev->dev; + phy->phy.dev = phy->dev; + phy->phy.label = "dm8168_usb_phy"; + phy->phy.otg = otg; + phy->phy.type = USB_PHY_TYPE_USB2; + otg->set_host = dm816x_usb_phy_set_host; + otg->set_peripheral = dm816x_usb_phy_set_peripheral; + otg->usb_phy = &phy->phy; + + platform_set_drvdata(pdev, phy); + + phy->refclk = devm_clk_get(phy->dev, "refclk"); + if (IS_ERR(phy->refclk)) + return PTR_ERR(phy->refclk); + error = clk_prepare(phy->refclk); + if (error) + return error; + + pm_runtime_enable(phy->dev); + generic_phy = devm_phy_create(phy->dev, NULL, &ops); + if (IS_ERR(generic_phy)) + return PTR_ERR(generic_phy); + + phy_set_drvdata(generic_phy, phy); + + phy_provider = devm_of_phy_provider_register(phy->dev, + of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + + usb_add_phy_dev(&phy->phy); + + return 0; +} + +static int dm816x_usb_phy_remove(struct platform_device *pdev) +{ + struct dm816x_usb_phy *phy = platform_get_drvdata(pdev); + + usb_remove_phy(&phy->phy); + pm_runtime_disable(phy->dev); + clk_unprepare(phy->refclk); + + return 0; +} + +static struct platform_driver dm816x_usb_phy_driver = { + .probe = dm816x_usb_phy_probe, + .remove = dm816x_usb_phy_remove, + .driver = { + .name = "dm816x-usb-phy", + .pm = &dm816x_usb_phy_pm_ops, + .of_match_table = of_match_ptr(dm816x_usb_phy_id_table), + }, +}; + +module_platform_driver(dm816x_usb_phy_driver); + +MODULE_ALIAS("platform:dm816x_usb"); +MODULE_AUTHOR("Tony Lindgren "); +MODULE_DESCRIPTION("dm816x usb phy driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 9c3b443026368583d2df3373a11b1c18c361d9a6 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Sat, 14 Mar 2015 11:57:16 +0800 Subject: phy: Add driver to support individual USB PHYs on sun9i Unlike previous Allwinner SoCs, there is no central PHY control block on the A80. Also, OTG support is completely split off into a different controller. This adds a new driver to support the regular USB PHYs. Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Signed-off-by: Kishon Vijay Abraham I --- .../devicetree/bindings/phy/sun9i-usb-phy.txt | 38 ++++ drivers/phy/Kconfig | 11 ++ drivers/phy/Makefile | 1 + drivers/phy/phy-sun9i-usb.c | 202 +++++++++++++++++++++ 4 files changed, 252 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/sun9i-usb-phy.txt create mode 100644 drivers/phy/phy-sun9i-usb.c (limited to 'drivers/phy') diff --git a/Documentation/devicetree/bindings/phy/sun9i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun9i-usb-phy.txt new file mode 100644 index 000000000000..1cca85c709d1 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/sun9i-usb-phy.txt @@ -0,0 +1,38 @@ +Allwinner sun9i USB PHY +----------------------- + +Required properties: +- compatible : should be one of + * allwinner,sun9i-a80-usb-phy +- reg : a list of offset + length pairs +- #phy-cells : from the generic phy bindings, must be 0 +- phy_type : "hsic" for HSIC usage; + other values or absence of this property indicates normal USB +- clocks : phandle + clock specifier for the phy clocks +- clock-names : depending on the "phy_type" property, + * "phy" for normal USB + * "hsic_480M", "hsic_12M" for HSIC +- resets : a list of phandle + reset specifier pairs +- reset-names : depending on the "phy_type" property, + * "phy" for normal USB + * "hsic" for HSIC + +Optional Properties: +- phy-supply : from the generic phy bindings, a phandle to a regulator that + provides power to VBUS. + +It is recommended to list all clocks and resets available. +The driver will only use those matching the phy_type. + +Example: + usbphy1: phy@00a01800 { + compatible = "allwinner,sun9i-a80-usb-phy"; + reg = <0x00a01800 0x4>; + clocks = <&usb_phy_clk 2>, <&usb_phy_clk 10>, + <&usb_phy_clk 3>; + clock-names = "hsic_480M", "hsic_12M", "phy"; + resets = <&usb_phy_clk 18>, <&usb_phy_clk 19>; + reset-names = "hsic", "phy"; + status = "disabled"; + #phy-cells = <0>; + }; diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 885c39c28a8b..a53bd5b52df9 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -181,6 +181,17 @@ config PHY_SUN4I_USB This driver controls the entire USB PHY block, both the USB OTG parts, as well as the 2 regular USB 2 host PHYs. +config PHY_SUN9I_USB + tristate "Allwinner sun9i SoC USB PHY driver" + depends on ARCH_SUNXI && HAS_IOMEM && OF + depends on RESET_CONTROLLER + select GENERIC_PHY + help + Enable this to support the transceiver that is part of Allwinner + sun9i SoCs. + + This driver controls each individual USB 2 host PHY. + config PHY_SAMSUNG_USB2 tristate "Samsung USB 2.0 PHY driver" depends on HAS_IOMEM diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index dab6665ad9c1..f12625178780 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o +obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o phy-exynos-usb2-y += phy-samsung-usb2.o phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o diff --git a/drivers/phy/phy-sun9i-usb.c b/drivers/phy/phy-sun9i-usb.c new file mode 100644 index 000000000000..0095914a662c --- /dev/null +++ b/drivers/phy/phy-sun9i-usb.c @@ -0,0 +1,202 @@ +/* + * Allwinner sun9i USB phy driver + * + * Copyright (C) 2014-2015 Chen-Yu Tsai + * + * Based on phy-sun4i-usb.c from + * Hans de Goede + * + * and code from + * Allwinner Technology Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SUNXI_AHB_INCR16_BURST_EN BIT(11) +#define SUNXI_AHB_INCR8_BURST_EN BIT(10) +#define SUNXI_AHB_INCR4_BURST_EN BIT(9) +#define SUNXI_AHB_INCRX_ALIGN_EN BIT(8) +#define SUNXI_ULPI_BYPASS_EN BIT(0) + +/* usb1 HSIC specific bits */ +#define SUNXI_EHCI_HS_FORCE BIT(20) +#define SUNXI_HSIC_CONNECT_DET BIT(17) +#define SUNXI_HSIC_CONNECT_INT BIT(16) +#define SUNXI_HSIC BIT(1) + +struct sun9i_usb_phy { + struct phy *phy; + void __iomem *pmu; + struct reset_control *reset; + struct clk *clk; + struct clk *hsic_clk; + enum usb_phy_interface type; +}; + +static void sun9i_usb_phy_passby(struct sun9i_usb_phy *phy, int enable) +{ + u32 bits, reg_value; + + bits = SUNXI_AHB_INCR16_BURST_EN | SUNXI_AHB_INCR8_BURST_EN | + SUNXI_AHB_INCR4_BURST_EN | SUNXI_AHB_INCRX_ALIGN_EN | + SUNXI_ULPI_BYPASS_EN; + + if (phy->type == USBPHY_INTERFACE_MODE_HSIC) + bits |= SUNXI_HSIC | SUNXI_EHCI_HS_FORCE | + SUNXI_HSIC_CONNECT_DET | SUNXI_HSIC_CONNECT_INT; + + reg_value = readl(phy->pmu); + + if (enable) + reg_value |= bits; + else + reg_value &= ~bits; + + writel(reg_value, phy->pmu); +} + +static int sun9i_usb_phy_init(struct phy *_phy) +{ + struct sun9i_usb_phy *phy = phy_get_drvdata(_phy); + int ret; + + ret = clk_prepare_enable(phy->clk); + if (ret) + goto err_clk; + + ret = clk_prepare_enable(phy->hsic_clk); + if (ret) + goto err_hsic_clk; + + ret = reset_control_deassert(phy->reset); + if (ret) + goto err_reset; + + sun9i_usb_phy_passby(phy, 1); + return 0; + +err_reset: + clk_disable_unprepare(phy->hsic_clk); + +err_hsic_clk: + clk_disable_unprepare(phy->clk); + +err_clk: + return ret; +} + +static int sun9i_usb_phy_exit(struct phy *_phy) +{ + struct sun9i_usb_phy *phy = phy_get_drvdata(_phy); + + sun9i_usb_phy_passby(phy, 0); + reset_control_assert(phy->reset); + clk_disable_unprepare(phy->hsic_clk); + clk_disable_unprepare(phy->clk); + + return 0; +} + +static struct phy_ops sun9i_usb_phy_ops = { + .init = sun9i_usb_phy_init, + .exit = sun9i_usb_phy_exit, + .owner = THIS_MODULE, +}; + +static int sun9i_usb_phy_probe(struct platform_device *pdev) +{ + struct sun9i_usb_phy *phy; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct phy_provider *phy_provider; + struct resource *res; + + phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); + if (!phy) + return -ENOMEM; + + phy->type = of_usb_get_phy_mode(np); + if (phy->type == USBPHY_INTERFACE_MODE_HSIC) { + phy->clk = devm_clk_get(dev, "hsic_480M"); + if (IS_ERR(phy->clk)) { + dev_err(dev, "failed to get hsic_480M clock\n"); + return PTR_ERR(phy->clk); + } + + phy->hsic_clk = devm_clk_get(dev, "hsic_12M"); + if (IS_ERR(phy->clk)) { + dev_err(dev, "failed to get hsic_12M clock\n"); + return PTR_ERR(phy->clk); + } + + phy->reset = devm_reset_control_get(dev, "hsic"); + if (IS_ERR(phy->reset)) { + dev_err(dev, "failed to get reset control\n"); + return PTR_ERR(phy->reset); + } + } else { + phy->clk = devm_clk_get(dev, "phy"); + if (IS_ERR(phy->clk)) { + dev_err(dev, "failed to get phy clock\n"); + return PTR_ERR(phy->clk); + } + + phy->reset = devm_reset_control_get(dev, "phy"); + if (IS_ERR(phy->reset)) { + dev_err(dev, "failed to get reset control\n"); + return PTR_ERR(phy->reset); + } + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + phy->pmu = devm_ioremap_resource(dev, res); + if (IS_ERR(phy->pmu)) + return PTR_ERR(phy->pmu); + + phy->phy = devm_phy_create(dev, NULL, &sun9i_usb_phy_ops); + if (IS_ERR(phy->phy)) { + dev_err(dev, "failed to create PHY\n"); + return PTR_ERR(phy->phy); + } + + phy_set_drvdata(phy->phy, phy); + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static const struct of_device_id sun9i_usb_phy_of_match[] = { + { .compatible = "allwinner,sun9i-a80-usb-phy" }, + { }, +}; +MODULE_DEVICE_TABLE(of, sun9i_usb_phy_of_match); + +static struct platform_driver sun9i_usb_phy_driver = { + .probe = sun9i_usb_phy_probe, + .driver = { + .of_match_table = sun9i_usb_phy_of_match, + .name = "sun9i-usb-phy", + } +}; +module_platform_driver(sun9i_usb_phy_driver); + +MODULE_DESCRIPTION("Allwinner sun9i USB phy driver"); +MODULE_AUTHOR("Chen-Yu Tsai "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From fbea230e7884044ee2e84bb28f6879dc30e1db24 Mon Sep 17 00:00:00 2001 From: Peter Griffin Date: Mon, 30 Mar 2015 16:17:07 +0100 Subject: phy: miphy365x: Use the generic phy type constants in dt-bindings/phy/phy.h Now there are generic phy type constants declared in phy.h, migrate over to using them rather than defining our own. This change has been done as one atomic commit to be bisectable. Note: The values of the defines are the same, so there is no ABI breakage with this patch. Signed-off-by: Peter Griffin Acked-by: Rob Herring Acked-by: Lee Jones Acked-by: Maxime Coquelin Signed-off-by: Kishon Vijay Abraham I --- Documentation/devicetree/bindings/phy/phy-miphy365x.txt | 8 ++++---- arch/arm/boot/dts/stih416.dtsi | 4 ++-- drivers/phy/phy-miphy365x.c | 14 +++++++------- include/dt-bindings/phy/phy-miphy365x.h | 14 -------------- 4 files changed, 13 insertions(+), 27 deletions(-) delete mode 100644 include/dt-bindings/phy/phy-miphy365x.h (limited to 'drivers/phy') diff --git a/Documentation/devicetree/bindings/phy/phy-miphy365x.txt b/Documentation/devicetree/bindings/phy/phy-miphy365x.txt index 9802d5d911aa..8772900e056a 100644 --- a/Documentation/devicetree/bindings/phy/phy-miphy365x.txt +++ b/Documentation/devicetree/bindings/phy/phy-miphy365x.txt @@ -20,8 +20,8 @@ Required nodes : A sub-node is required for each channel the controller Required properties (port (child) node): - #phy-cells : Should be 1 (See second example) Cell after port phandle is device type from: - - MIPHY_TYPE_SATA - - MIPHY_TYPE_PCI + - PHY_TYPE_SATA + - PHY_TYPE_PCI - reg : Address and length of register sets for each device in "reg-names" - reg-names : The names of the register addresses corresponding to the @@ -68,10 +68,10 @@ property, containing a phandle to the phy port node and a device type. Example: -#include +#include sata0: sata@fe380000 { ... - phys = <&phy_port0 MIPHY_TYPE_SATA>; + phys = <&phy_port0 PHY_TYPE_SATA>; ... }; diff --git a/arch/arm/boot/dts/stih416.dtsi b/arch/arm/boot/dts/stih416.dtsi index ea28ebadab1a..eeb7afecbbe6 100644 --- a/arch/arm/boot/dts/stih416.dtsi +++ b/arch/arm/boot/dts/stih416.dtsi @@ -10,7 +10,7 @@ #include "stih416-clock.dtsi" #include "stih416-pinctrl.dtsi" -#include +#include #include #include / { @@ -306,7 +306,7 @@ reg = <0xfe380000 0x1000>; interrupts = ; interrupt-names = "hostc"; - phys = <&phy_port0 MIPHY_TYPE_SATA>; + phys = <&phy_port0 PHY_TYPE_SATA>; phy-names = "sata-phy"; resets = <&powerdown STIH416_SATA0_POWERDOWN>, <&softreset STIH416_SATA0_SOFTRESET>; diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c index 6c80154e8bff..98bffbc0f74d 100644 --- a/drivers/phy/phy-miphy365x.c +++ b/drivers/phy/phy-miphy365x.c @@ -25,7 +25,7 @@ #include #include -#include +#include #define HFC_TIMEOUT 100 @@ -176,7 +176,7 @@ static u8 rx_tx_spd[] = { static int miphy365x_set_path(struct miphy365x_phy *miphy_phy, struct miphy365x_dev *miphy_dev) { - bool sata = (miphy_phy->type == MIPHY_TYPE_SATA); + bool sata = (miphy_phy->type == PHY_TYPE_SATA); return regmap_update_bits(miphy_dev->regmap, miphy_phy->ctrlreg, @@ -430,7 +430,7 @@ static int miphy365x_init(struct phy *phy) } /* Initialise Miphy for PCIe or SATA */ - if (miphy_phy->type == MIPHY_TYPE_PCIE) + if (miphy_phy->type == PHY_TYPE_PCIE) ret = miphy365x_init_pcie_port(miphy_phy, miphy_dev); else ret = miphy365x_init_sata_port(miphy_phy, miphy_dev); @@ -454,8 +454,8 @@ int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy, return ret; } - if (!((!strncmp(name, "sata", 4) && type == MIPHY_TYPE_SATA) || - (!strncmp(name, "pcie", 4) && type == MIPHY_TYPE_PCIE))) + if (!((!strncmp(name, "sata", 4) && type == PHY_TYPE_SATA) || + (!strncmp(name, "pcie", 4) && type == PHY_TYPE_PCIE))) return 0; miphy_phy->base = of_iomap(phynode, index); @@ -498,8 +498,8 @@ static struct phy *miphy365x_xlate(struct device *dev, miphy_phy->type = args->args[0]; - if (!(miphy_phy->type == MIPHY_TYPE_SATA || - miphy_phy->type == MIPHY_TYPE_PCIE)) { + if (!(miphy_phy->type == PHY_TYPE_SATA || + miphy_phy->type == PHY_TYPE_PCIE)) { dev_err(dev, "Unsupported device type: %d\n", miphy_phy->type); return ERR_PTR(-EINVAL); } diff --git a/include/dt-bindings/phy/phy-miphy365x.h b/include/dt-bindings/phy/phy-miphy365x.h deleted file mode 100644 index 8ef8aba6edd6..000000000000 --- a/include/dt-bindings/phy/phy-miphy365x.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * This header provides constants for the phy framework - * based on the STMicroelectronics MiPHY365x. - * - * Author: Lee Jones - */ -#ifndef _DT_BINDINGS_PHY_MIPHY -#define _DT_BINDINGS_PHY_MIPHY - -#define MIPHY_TYPE_SATA 1 -#define MIPHY_TYPE_PCIE 2 -#define MIPHY_TYPE_USB 3 - -#endif /* _DT_BINDINGS_PHY_MIPHY */ -- cgit v1.2.3 From 247e21c613649f34bcf2f71e57e813e6ed18b458 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 1 Apr 2015 08:44:32 +0800 Subject: phy: spear1310-miphy: Return proper error for spear1310_miphy_xlate The of_xlate callback should return ERR_PTR on error. Signed-off-by: Axel Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-spear1310-miphy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-spear1310-miphy.c b/drivers/phy/phy-spear1310-miphy.c index 9f47fae7eecb..65ae640cfbd1 100644 --- a/drivers/phy/phy-spear1310-miphy.c +++ b/drivers/phy/phy-spear1310-miphy.c @@ -192,14 +192,14 @@ static struct phy *spear1310_miphy_xlate(struct device *dev, if (args->args_count < 1) { dev_err(dev, "DT did not pass correct no of args\n"); - return NULL; + return ERR_PTR(-ENODEV); } priv->mode = args->args[0]; if (priv->mode != SATA && priv->mode != PCIE) { dev_err(dev, "DT did not pass correct phy mode\n"); - return NULL; + return ERR_PTR(-ENODEV); } return priv->phy; -- cgit v1.2.3 From 407ed8357464851cf12d68c4a969cd933f8dbcaf Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 1 Apr 2015 08:45:33 +0800 Subject: phy: spear1340-miphy: Return proper error for spear1340_miphy_xlate The of_xlate callback should return ERR_PTR on error. Signed-off-by: Axel Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-spear1340-miphy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-spear1340-miphy.c b/drivers/phy/phy-spear1340-miphy.c index e42bc200275f..1a00c2817f34 100644 --- a/drivers/phy/phy-spear1340-miphy.c +++ b/drivers/phy/phy-spear1340-miphy.c @@ -229,14 +229,14 @@ static struct phy *spear1340_miphy_xlate(struct device *dev, if (args->args_count < 1) { dev_err(dev, "DT did not pass correct no of args\n"); - return NULL; + return ERR_PTR(-ENODEV); } priv->mode = args->args[0]; if (priv->mode != SATA && priv->mode != PCIE) { dev_err(dev, "DT did not pass correct phy mode\n"); - return NULL; + return ERR_PTR(-ENODEV); } return priv->phy; -- cgit v1.2.3