From cbf919bd32d9424be8b77dac06fd90cd0a297562 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Thu, 9 Jul 2015 22:48:25 +0200 Subject: phy: add lpc18xx usb otg phy driver Add PHY driver for the internal USB OTG PHY found on NXP LPC18xx and LPC43xx devices. This driver takes care of enabling the PHY in CREG (syscon) and setting the required clock frequency. Signed-off-by: Joachim Eastwood Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/Kconfig | 11 +++ drivers/phy/Makefile | 1 + drivers/phy/phy-lpc18xx-usb-otg.c | 143 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 drivers/phy/phy-lpc18xx-usb-otg.c (limited to 'drivers/phy') diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index c0e6ede3e27d..e2f2a4d394e1 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -54,6 +54,17 @@ config PHY_EXYNOS_MIPI_VIDEO Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P and EXYNOS SoCs. +config PHY_LPC18XX_USB_OTG + tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver" + depends on OF && (ARCH_LPC18XX || COMPILE_TEST) + depends on MFD_SYSCON + select GENERIC_PHY + help + Enable this to support NXP LPC18xx/43xx internal USB OTG PHY. + + This driver is need for USB0 support on LPC18xx/43xx and takes + care of enabling and clock setup. + config PHY_PXA_28NM_HSIC tristate "Marvell USB HSIC 28nm PHY Driver" select GENERIC_PHY diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index f344e1b2e825..a5b18c18fc12 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -10,6 +10,7 @@ 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 obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o +obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o diff --git a/drivers/phy/phy-lpc18xx-usb-otg.c b/drivers/phy/phy-lpc18xx-usb-otg.c new file mode 100644 index 000000000000..3aa8e4de1b03 --- /dev/null +++ b/drivers/phy/phy-lpc18xx-usb-otg.c @@ -0,0 +1,143 @@ +/* + * PHY driver for NXP LPC18xx/43xx internal USB OTG PHY + * + * Copyright (C) 2015 Joachim Eastwood + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* USB OTG PHY register offset and bit in CREG */ +#define LPC18XX_CREG_CREG0 0x004 +#define LPC18XX_CREG_CREG0_USB0PHY BIT(5) + +struct lpc18xx_usb_otg_phy { + struct phy *phy; + struct clk *clk; + struct regmap *reg; +}; + +static int lpc18xx_usb_otg_phy_init(struct phy *phy) +{ + struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy); + int ret; + + ret = clk_prepare(lpc->clk); + if (ret) + return ret; + + /* The PHY must be clocked at 480 MHz */ + return clk_set_rate(lpc->clk, 480000000); +} + +static int lpc18xx_usb_otg_phy_exit(struct phy *phy) +{ + struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy); + + clk_unprepare(lpc->clk); + + return 0; +} + +static int lpc18xx_usb_otg_phy_power_on(struct phy *phy) +{ + struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy); + int ret; + + ret = clk_enable(lpc->clk); + if (ret) + return ret; + + /* The bit in CREG is cleared to enable the PHY */ + return regmap_update_bits(lpc->reg, LPC18XX_CREG_CREG0, + LPC18XX_CREG_CREG0_USB0PHY, 0); +} + +static int lpc18xx_usb_otg_phy_power_off(struct phy *phy) +{ + struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy); + int ret; + + ret = regmap_update_bits(lpc->reg, LPC18XX_CREG_CREG0, + LPC18XX_CREG_CREG0_USB0PHY, + LPC18XX_CREG_CREG0_USB0PHY); + if (ret) + return ret; + + clk_disable(lpc->clk); + + return 0; +} + +static const struct phy_ops lpc18xx_usb_otg_phy_ops = { + .init = lpc18xx_usb_otg_phy_init, + .exit = lpc18xx_usb_otg_phy_exit, + .power_on = lpc18xx_usb_otg_phy_power_on, + .power_off = lpc18xx_usb_otg_phy_power_off, + .owner = THIS_MODULE, +}; + +static int lpc18xx_usb_otg_phy_probe(struct platform_device *pdev) +{ + struct phy_provider *phy_provider; + struct lpc18xx_usb_otg_phy *lpc; + + lpc = devm_kzalloc(&pdev->dev, sizeof(*lpc), GFP_KERNEL); + if (!lpc) + return -ENOMEM; + + lpc->reg = syscon_node_to_regmap(pdev->dev.of_node->parent); + if (IS_ERR(lpc->reg)) { + dev_err(&pdev->dev, "failed to get syscon\n"); + return PTR_ERR(lpc->reg); + } + + lpc->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(lpc->clk)) { + dev_err(&pdev->dev, "failed to get clock\n"); + return PTR_ERR(lpc->clk); + } + + lpc->phy = devm_phy_create(&pdev->dev, NULL, &lpc18xx_usb_otg_phy_ops); + if (IS_ERR(lpc->phy)) { + dev_err(&pdev->dev, "failed to create PHY\n"); + return PTR_ERR(lpc->phy); + } + + phy_set_drvdata(lpc->phy, lpc); + + phy_provider = devm_of_phy_provider_register(&pdev->dev, + of_phy_simple_xlate); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static const struct of_device_id lpc18xx_usb_otg_phy_match[] = { + { .compatible = "nxp,lpc1850-usb-otg-phy" }, + { } +}; +MODULE_DEVICE_TABLE(of, lpc18xx_usb_otg_phy_match); + +static struct platform_driver lpc18xx_usb_otg_phy_driver = { + .probe = lpc18xx_usb_otg_phy_probe, + .driver = { + .name = "lpc18xx-usb-otg-phy", + .of_match_table = lpc18xx_usb_otg_phy_match, + }, +}; +module_platform_driver(lpc18xx_usb_otg_phy_driver); + +MODULE_AUTHOR("Joachim Eastwood "); +MODULE_DESCRIPTION("NXP LPC18xx/43xx USB OTG PHY driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From d2332303efc00d35af7f3d8b025663965862b0e3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 13 Jun 2015 14:37:45 +0200 Subject: phy-sun4i-usb: Add id and vbus detection support for the otg phy (phy0) The usb0 phy is connected to an OTG controller, and as such needs some special handling: 1) It allows explicit control over the pullups, enable these on phy_init and disable them on phy_exit. 2) It has bits to signal id and vbus detect to the musb-core, add support for for monitoring id and vbus detect gpio-s for use in dual role mode, and set these bits to the correct values for operating in host only mode when no gpios are specified in the devicetree. While updating the devicetree binding documentation also add documentation for the sofar undocumented usage of regulators for vbus for all 3 phys. Signed-off-by: Hans de Goede Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-sun4i-usb.c | 250 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 240 insertions(+), 10 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index e17c539e4f6f..37f52f73fdba 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -1,7 +1,7 @@ /* * Allwinner sun4i USB phy driver * - * Copyright (C) 2014 Hans de Goede + * Copyright (C) 2014-2015 Hans de Goede * * Based on code from * Allwinner Technology Co., Ltd. @@ -24,16 +24,19 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include #include #include +#include #define REG_ISCR 0x00 #define REG_PHYCTL 0x04 @@ -47,6 +50,17 @@ #define SUNXI_AHB_INCRX_ALIGN_EN BIT(8) #define SUNXI_ULPI_BYPASS_EN BIT(0) +/* ISCR, Interface Status and Control bits */ +#define ISCR_ID_PULLUP_EN (1 << 17) +#define ISCR_DPDM_PULLUP_EN (1 << 16) +/* sunxi has the phy id/vbus pins not connected, so we use the force bits */ +#define ISCR_FORCE_ID_MASK (3 << 14) +#define ISCR_FORCE_ID_LOW (2 << 14) +#define ISCR_FORCE_ID_HIGH (3 << 14) +#define ISCR_FORCE_VBUS_MASK (3 << 12) +#define ISCR_FORCE_VBUS_LOW (2 << 12) +#define ISCR_FORCE_VBUS_HIGH (3 << 12) + /* Common Control Bits for Both PHYs */ #define PHY_PLL_BW 0x03 #define PHY_RES45_CAL_EN 0x0c @@ -63,6 +77,13 @@ #define MAX_PHYS 3 +/* + * Note do not raise the debounce time, we must report Vusb high within 100ms + * otherwise we get Vbus errors + */ +#define DEBOUNCE_TIME msecs_to_jiffies(50) +#define POLL_TIME msecs_to_jiffies(250) + struct sun4i_usb_phy_data { void __iomem *base; struct mutex mutex; @@ -74,13 +95,56 @@ struct sun4i_usb_phy_data { struct regulator *vbus; struct reset_control *reset; struct clk *clk; + bool regulator_on; int index; } phys[MAX_PHYS]; + /* phy0 / otg related variables */ + bool phy0_init; + bool phy0_poll; + struct gpio_desc *id_det_gpio; + struct gpio_desc *vbus_det_gpio; + int id_det_irq; + int vbus_det_irq; + int id_det; + int vbus_det; + struct delayed_work detect; }; #define to_sun4i_usb_phy_data(phy) \ container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index]) +static void sun4i_usb_phy0_update_iscr(struct phy *_phy, u32 clr, u32 set) +{ + struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); + struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); + u32 iscr; + + iscr = readl(data->base + REG_ISCR); + iscr &= ~clr; + iscr |= set; + writel(iscr, data->base + REG_ISCR); +} + +static void sun4i_usb_phy0_set_id_detect(struct phy *phy, u32 val) +{ + if (val) + val = ISCR_FORCE_ID_HIGH; + else + val = ISCR_FORCE_ID_LOW; + + sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_ID_MASK, val); +} + +static void sun4i_usb_phy0_set_vbus_detect(struct phy *phy, u32 val) +{ + if (val) + val = ISCR_FORCE_VBUS_HIGH; + else + val = ISCR_FORCE_VBUS_LOW; + + sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_VBUS_MASK, val); +} + static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data, int len) { @@ -171,12 +235,39 @@ static int sun4i_usb_phy_init(struct phy *_phy) sun4i_usb_phy_passby(phy, 1); + if (phy->index == 0) { + data->phy0_init = true; + + /* Enable pull-ups */ + sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_DPDM_PULLUP_EN); + sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_ID_PULLUP_EN); + + if (data->id_det_gpio) { + /* OTG mode, force ISCR and cable state updates */ + data->id_det = -1; + data->vbus_det = -1; + queue_delayed_work(system_wq, &data->detect, 0); + } else { + /* Host only mode */ + sun4i_usb_phy0_set_id_detect(_phy, 0); + sun4i_usb_phy0_set_vbus_detect(_phy, 1); + } + } + return 0; } static int sun4i_usb_phy_exit(struct phy *_phy) { struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); + struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); + + if (phy->index == 0) { + /* Disable pull-ups */ + sun4i_usb_phy0_update_iscr(_phy, ISCR_DPDM_PULLUP_EN, 0); + sun4i_usb_phy0_update_iscr(_phy, ISCR_ID_PULLUP_EN, 0); + data->phy0_init = false; + } sun4i_usb_phy_passby(phy, 0); reset_control_assert(phy->reset); @@ -188,20 +279,46 @@ static int sun4i_usb_phy_exit(struct phy *_phy) static int sun4i_usb_phy_power_on(struct phy *_phy) { struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); - int ret = 0; + struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); + int ret; + + if (!phy->vbus || phy->regulator_on) + return 0; + + /* For phy0 only turn on Vbus if we don't have an ext. Vbus */ + if (phy->index == 0 && data->vbus_det) + return 0; - if (phy->vbus) - ret = regulator_enable(phy->vbus); + ret = regulator_enable(phy->vbus); + if (ret) + return ret; - return ret; + phy->regulator_on = true; + + /* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */ + if (phy->index == 0 && data->phy0_poll) + mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME); + + return 0; } static int sun4i_usb_phy_power_off(struct phy *_phy) { struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); + struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); + + if (!phy->vbus || !phy->regulator_on) + return 0; - if (phy->vbus) - regulator_disable(phy->vbus); + regulator_disable(phy->vbus); + phy->regulator_on = false; + + /* + * phy0 vbus typically slowly discharges, sometimes this causes the + * Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan. + */ + if (phy->index == 0 && !data->phy0_poll) + mod_delayed_work(system_wq, &data->detect, POLL_TIME); return 0; } @@ -221,6 +338,49 @@ static struct phy_ops sun4i_usb_phy_ops = { .owner = THIS_MODULE, }; +static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) +{ + struct sun4i_usb_phy_data *data = + container_of(work, struct sun4i_usb_phy_data, detect.work); + struct phy *phy0 = data->phys[0].phy; + int id_det, vbus_det; + + id_det = gpiod_get_value_cansleep(data->id_det_gpio); + vbus_det = gpiod_get_value_cansleep(data->vbus_det_gpio); + + mutex_lock(&phy0->mutex); + + if (!data->phy0_init) { + mutex_unlock(&phy0->mutex); + return; + } + + if (id_det != data->id_det) { + sun4i_usb_phy0_set_id_detect(phy0, id_det); + data->id_det = id_det; + } + + if (vbus_det != data->vbus_det) { + sun4i_usb_phy0_set_vbus_detect(phy0, vbus_det); + data->vbus_det = vbus_det; + } + + mutex_unlock(&phy0->mutex); + + if (data->phy0_poll) + queue_delayed_work(system_wq, &data->detect, POLL_TIME); +} + +static irqreturn_t sun4i_usb_phy0_id_vbus_det_irq(int irq, void *dev_id) +{ + struct sun4i_usb_phy_data *data = dev_id; + + /* vbus or id changed, let the pins settle and then scan them */ + mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME); + + return IRQ_HANDLED; +} + static struct phy *sun4i_usb_phy_xlate(struct device *dev, struct of_phandle_args *args) { @@ -232,6 +392,21 @@ static struct phy *sun4i_usb_phy_xlate(struct device *dev, return data->phys[args->args[0]].phy; } +static int sun4i_usb_phy_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct sun4i_usb_phy_data *data = dev_get_drvdata(dev); + + if (data->id_det_irq >= 0) + devm_free_irq(dev, data->id_det_irq, data); + if (data->vbus_det_irq >= 0) + devm_free_irq(dev, data->vbus_det_irq, data); + + cancel_delayed_work_sync(&data->detect); + + return 0; +} + static int sun4i_usb_phy_probe(struct platform_device *pdev) { struct sun4i_usb_phy_data *data; @@ -240,13 +415,15 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) struct phy_provider *phy_provider; bool dedicated_clocks; struct resource *res; - int i; + int i, ret; data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; mutex_init(&data->mutex); + INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan); + dev_set_drvdata(dev, data); if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy")) data->num_phys = 2; @@ -269,6 +446,26 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) if (IS_ERR(data->base)) return PTR_ERR(data->base); + data->id_det_gpio = devm_gpiod_get(dev, "usb0_id_det", GPIOD_IN); + if (IS_ERR(data->id_det_gpio)) { + if (PTR_ERR(data->id_det_gpio) == -EPROBE_DEFER) + return -EPROBE_DEFER; + data->id_det_gpio = NULL; + } + + data->vbus_det_gpio = devm_gpiod_get(dev, "usb0_vbus_det", GPIOD_IN); + if (IS_ERR(data->vbus_det_gpio)) { + if (PTR_ERR(data->vbus_det_gpio) == -EPROBE_DEFER) + return -EPROBE_DEFER; + data->vbus_det_gpio = NULL; + } + + /* We either want both gpio pins or neither (when in host mode) */ + if (!data->id_det_gpio != !data->vbus_det_gpio) { + dev_err(dev, "failed to get id or vbus detect pin\n"); + return -ENODEV; + } + for (i = 0; i < data->num_phys; i++) { struct sun4i_usb_phy *phy = data->phys + i; char name[16]; @@ -318,10 +515,42 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) phy_set_drvdata(phy->phy, &data->phys[i]); } - dev_set_drvdata(dev, data); + data->id_det_irq = gpiod_to_irq(data->id_det_gpio); + data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio); + if (data->id_det_irq < 0 || data->vbus_det_irq < 0) + data->phy0_poll = true; + + if (data->id_det_irq >= 0) { + ret = devm_request_irq(dev, data->id_det_irq, + sun4i_usb_phy0_id_vbus_det_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "usb0-id-det", data); + if (ret) { + dev_err(dev, "Err requesting id-det-irq: %d\n", ret); + return ret; + } + } + + if (data->vbus_det_irq >= 0) { + ret = devm_request_irq(dev, data->vbus_det_irq, + sun4i_usb_phy0_id_vbus_det_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "usb0-vbus-det", data); + if (ret) { + dev_err(dev, "Err requesting vbus-det-irq: %d\n", ret); + data->vbus_det_irq = -1; + sun4i_usb_phy_remove(pdev); /* Stop detect work */ + return ret; + } + } + phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate); + if (IS_ERR(phy_provider)) { + sun4i_usb_phy_remove(pdev); /* Stop detect work */ + return PTR_ERR(phy_provider); + } - return PTR_ERR_OR_ZERO(phy_provider); + return 0; } static const struct of_device_id sun4i_usb_phy_of_match[] = { @@ -335,6 +564,7 @@ MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); static struct platform_driver sun4i_usb_phy_driver = { .probe = sun4i_usb_phy_probe, + .remove = sun4i_usb_phy_remove, .driver = { .of_match_table = sun4i_usb_phy_of_match, .name = "sun4i-usb-phy", -- cgit v1.2.3 From 1a52abe6821da728b41187c6676b6ab7294e6e2c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 13 Jun 2015 14:37:46 +0200 Subject: phy-sun4i-usb: Add extcon support for the otg phy (phy0) The sunxi musb glue needs to know if a host or normal usb cable is plugged in, add extcon support so that the musb glue can monitor the host status. Signed-off-by: Hans de Goede Acked-by: Chanwoo Choi Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/Kconfig | 1 + drivers/phy/phy-sun4i-usb.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) (limited to 'drivers/phy') diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index e2f2a4d394e1..c0c1ad2e2c01 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -208,6 +208,7 @@ config PHY_SUN4I_USB tristate "Allwinner sunxi SoC USB PHY driver" depends on ARCH_SUNXI && HAS_IOMEM && OF depends on RESET_CONTROLLER + depends on EXTCON select GENERIC_PHY help Enable this to support the transceiver that is part of Allwinner diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index 37f52f73fdba..a6ea2e6b1d5c 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -99,6 +100,7 @@ struct sun4i_usb_phy_data { int index; } phys[MAX_PHYS]; /* phy0 / otg related variables */ + struct extcon_dev *extcon; bool phy0_init; bool phy0_poll; struct gpio_desc *id_det_gpio; @@ -343,7 +345,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) struct sun4i_usb_phy_data *data = container_of(work, struct sun4i_usb_phy_data, detect.work); struct phy *phy0 = data->phys[0].phy; - int id_det, vbus_det; + int id_det, vbus_det, id_notify = 0, vbus_notify = 0; id_det = gpiod_get_value_cansleep(data->id_det_gpio); vbus_det = gpiod_get_value_cansleep(data->vbus_det_gpio); @@ -358,15 +360,24 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) if (id_det != data->id_det) { sun4i_usb_phy0_set_id_detect(phy0, id_det); data->id_det = id_det; + id_notify = 1; } if (vbus_det != data->vbus_det) { sun4i_usb_phy0_set_vbus_detect(phy0, vbus_det); data->vbus_det = vbus_det; + vbus_notify = 1; } mutex_unlock(&phy0->mutex); + if (id_notify) + extcon_set_cable_state_(data->extcon, EXTCON_USB_HOST, + !id_det); + + if (vbus_notify) + extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det); + if (data->phy0_poll) queue_delayed_work(system_wq, &data->detect, POLL_TIME); } @@ -407,6 +418,12 @@ static int sun4i_usb_phy_remove(struct platform_device *pdev) return 0; } +static const unsigned int sun4i_usb_phy0_cable[] = { + EXTCON_USB, + EXTCON_USB_HOST, + EXTCON_NONE, +}; + static int sun4i_usb_phy_probe(struct platform_device *pdev) { struct sun4i_usb_phy_data *data; @@ -466,6 +483,19 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) return -ENODEV; } + if (data->id_det_gpio) { + data->extcon = devm_extcon_dev_allocate(dev, + sun4i_usb_phy0_cable); + if (IS_ERR(data->extcon)) + return PTR_ERR(data->extcon); + + ret = devm_extcon_dev_register(dev, data->extcon); + if (ret) { + dev_err(dev, "failed to register extcon: %d\n", ret); + return ret; + } + } + for (i = 0; i < data->num_phys; i++) { struct sun4i_usb_phy *phy = data->phys + i; char name[16]; -- cgit v1.2.3 From 2846469631393a1cf150f17a99b8ca2b5772b255 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 13 Jun 2015 14:37:47 +0200 Subject: phy-sun4i-usb: Swap check for disconnect threshold Before this commit the code for determining the disconnect threshold was checking for "allwinner,sun4i-a10-usb-phy" or "allwinner,sun6i-a31-usb-phy" assuming that those where the exception and then newer SoCs would use a disconnect threshold of 2 like sun7i does. But it turns out that newer SoCs use a disconnect threshold of 3 and sun5i and sun7i are the exceptions, so check for those instead. Here are the settings from the various Allwinner SDK sources: sun4i-a10: USBC_Phy_Write(usbc_no, 0x2a, 3, 2); sun5i-a13: USBC_Phy_Write(usbc_no, 0x2a, 2, 2); sun6i-a31: USBC_Phy_Write(usbc_no, 0x2a, 3, 2); sun7i-a20: USBC_Phy_Write(usbc_no, 0x2a, 2, 2); sun8i-a23: USBC_Phy_Write(usbc_no, 0x2a, 3, 2); sun8i-h3: USBC_Phy_Write(usbc_no, 0x2a, 3, 2); sun9i-a80: USBC_Phy_Write(usbc_no, 0x2a, 3, 2); Note this commit makes no functional changes as currently we only support sun4i - sun7i. Signed-off-by: Hans de Goede Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-sun4i-usb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index a6ea2e6b1d5c..50ecab9d73df 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -447,11 +447,11 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) else data->num_phys = 3; - if (of_device_is_compatible(np, "allwinner,sun4i-a10-usb-phy") || - of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy")) - data->disc_thresh = 3; - else + if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") || + of_device_is_compatible(np, "allwinner,sun7i-a20-usb-phy")) data->disc_thresh = 2; + else + data->disc_thresh = 3; if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy")) dedicated_clocks = true; -- cgit v1.2.3 From 123dfdbcfaf5eb8753cd6293ab50c41e9b8e9ebf Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 13 Jun 2015 14:37:48 +0200 Subject: phy-sun4i-usb: Add support for the usb-phys on the sun8i-a23 SoC The usb-phys on the sun8i-a23 SoC have the same setup wrt clocks as on the sun6i-a31 SoC, but there are only 2 instead of 3 like on the sun5i-a13 SoC. Signed-off-by: Hans de Goede Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-sun4i-usb.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index 50ecab9d73df..00424dde79c1 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -442,7 +442,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan); dev_set_drvdata(dev, data); - if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy")) + if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") || + of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy")) data->num_phys = 2; else data->num_phys = 3; @@ -453,7 +454,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) else data->disc_thresh = 3; - if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy")) + if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy") || + of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy")) dedicated_clocks = true; else dedicated_clocks = false; @@ -588,6 +590,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = { { .compatible = "allwinner,sun5i-a13-usb-phy" }, { .compatible = "allwinner,sun6i-a31-usb-phy" }, { .compatible = "allwinner,sun7i-a20-usb-phy" }, + { .compatible = "allwinner,sun8i-a23-usb-phy" }, { }, }; MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); -- cgit v1.2.3 From fc1f45ed3043da3aa901e88a9ef0995bbd320698 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 13 Jun 2015 14:37:49 +0200 Subject: phy-sun4i-usb: Add support for the usb-phys on the sun8i-a33 SoC The usb-phys on the sun8i-a33 SoC are mostly the same as sun8i-a23 but for some reason (hw bug?) the phyctl register was moved to a different address and is not initialized to 0 on reset. Signed-off-by: Hans de Goede Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-sun4i-usb.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index 00424dde79c1..ddc399536c5c 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -40,9 +40,10 @@ #include #define REG_ISCR 0x00 -#define REG_PHYCTL 0x04 +#define REG_PHYCTL_A10 0x04 #define REG_PHYBIST 0x08 #define REG_PHYTUNE 0x0c +#define REG_PHYCTL_A33 0x10 #define PHYCTL_DATA BIT(7) @@ -90,6 +91,7 @@ struct sun4i_usb_phy_data { struct mutex mutex; int num_phys; u32 disc_thresh; + bool has_a33_phyctl; struct sun4i_usb_phy { struct phy *phy; void __iomem *pmu; @@ -152,37 +154,46 @@ static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data, { struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy); u32 temp, usbc_bit = BIT(phy->index * 2); + void *phyctl; int i; mutex_lock(&phy_data->mutex); + if (phy_data->has_a33_phyctl) { + phyctl = phy_data->base + REG_PHYCTL_A33; + /* A33 needs us to set phyctl to 0 explicitly */ + writel(0, phyctl); + } else { + phyctl = phy_data->base + REG_PHYCTL_A10; + } + for (i = 0; i < len; i++) { - temp = readl(phy_data->base + REG_PHYCTL); + temp = readl(phyctl); /* clear the address portion */ temp &= ~(0xff << 8); /* set the address */ temp |= ((addr + i) << 8); - writel(temp, phy_data->base + REG_PHYCTL); + writel(temp, phyctl); /* set the data bit and clear usbc bit*/ - temp = readb(phy_data->base + REG_PHYCTL); + temp = readb(phyctl); if (data & 0x1) temp |= PHYCTL_DATA; else temp &= ~PHYCTL_DATA; temp &= ~usbc_bit; - writeb(temp, phy_data->base + REG_PHYCTL); + writeb(temp, phyctl); /* pulse usbc_bit */ - temp = readb(phy_data->base + REG_PHYCTL); + temp = readb(phyctl); temp |= usbc_bit; - writeb(temp, phy_data->base + REG_PHYCTL); + writeb(temp, phyctl); - temp = readb(phy_data->base + REG_PHYCTL); + temp = readb(phyctl); temp &= ~usbc_bit; - writeb(temp, phy_data->base + REG_PHYCTL); + writeb(temp, phyctl); data >>= 1; } @@ -443,7 +454,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) dev_set_drvdata(dev, data); if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") || - of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy")) + of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") || + of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy")) data->num_phys = 2; else data->num_phys = 3; @@ -455,11 +467,15 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) data->disc_thresh = 3; if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy") || - of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy")) + of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") || + of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy")) dedicated_clocks = true; else dedicated_clocks = false; + if (of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy")) + data->has_a33_phyctl = true; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl"); data->base = devm_ioremap_resource(dev, res); if (IS_ERR(data->base)) @@ -591,6 +607,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = { { .compatible = "allwinner,sun6i-a31-usb-phy" }, { .compatible = "allwinner,sun7i-a20-usb-phy" }, { .compatible = "allwinner,sun8i-a23-usb-phy" }, + { .compatible = "allwinner,sun8i-a33-usb-phy" }, { }, }; MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); -- cgit v1.2.3 From 1aedf3a7a47b8bbd38c147eeb0c83816c5590215 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 13 Jun 2015 14:37:50 +0200 Subject: phy-sun4i-usb: Add support for boards with broken Vusb-detection On some boards we cannot detect the presence of an external Vusb, because e.g. the 5V of the otg connector is directly connected to the 5V of the board, and thus is always high. This commit adds support for using such boards by only looking at the id-detection pin. Signed-off-by: Hans de Goede Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-sun4i-usb.c | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index ddc399536c5c..4ba9856ac71a 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -22,6 +22,7 @@ */ #include +#include #include #include #include @@ -309,7 +310,7 @@ static int sun4i_usb_phy_power_on(struct phy *_phy) phy->regulator_on = true; /* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */ - if (phy->index == 0 && data->phy0_poll) + if (phy->index == 0 && data->vbus_det_gpio && data->phy0_poll) mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME); return 0; @@ -330,7 +331,7 @@ static int sun4i_usb_phy_power_off(struct phy *_phy) * phy0 vbus typically slowly discharges, sometimes this causes the * Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan. */ - if (phy->index == 0 && !data->phy0_poll) + if (phy->index == 0 && data->vbus_det_gpio && !data->phy0_poll) mod_delayed_work(system_wq, &data->detect, POLL_TIME); return 0; @@ -359,7 +360,10 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) int id_det, vbus_det, id_notify = 0, vbus_notify = 0; id_det = gpiod_get_value_cansleep(data->id_det_gpio); - vbus_det = gpiod_get_value_cansleep(data->vbus_det_gpio); + if (data->vbus_det_gpio) + vbus_det = gpiod_get_value_cansleep(data->vbus_det_gpio); + else + vbus_det = 1; /* Report vbus as high */ mutex_lock(&phy0->mutex); @@ -369,6 +373,16 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) } if (id_det != data->id_det) { + /* + * When a host cable (id == 0) gets plugged in on systems + * without vbus detection report vbus low for long enough for + * the musb-ip to end the current device session. + */ + if (!data->vbus_det_gpio && id_det == 0) { + sun4i_usb_phy0_set_vbus_detect(phy0, 0); + msleep(200); + sun4i_usb_phy0_set_vbus_detect(phy0, 1); + } sun4i_usb_phy0_set_id_detect(phy0, id_det); data->id_det = id_det; id_notify = 1; @@ -382,9 +396,22 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) mutex_unlock(&phy0->mutex); - if (id_notify) + if (id_notify) { extcon_set_cable_state_(data->extcon, EXTCON_USB_HOST, !id_det); + /* + * When a host cable gets unplugged (id == 1) on systems + * without vbus detection report vbus low for long enough to + * the musb-ip to end the current host session. + */ + if (!data->vbus_det_gpio && id_det == 1) { + mutex_lock(&phy0->mutex); + sun4i_usb_phy0_set_vbus_detect(phy0, 0); + msleep(1000); + sun4i_usb_phy0_set_vbus_detect(phy0, 1); + mutex_unlock(&phy0->mutex); + } + } if (vbus_notify) extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det); @@ -495,9 +522,9 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) data->vbus_det_gpio = NULL; } - /* We either want both gpio pins or neither (when in host mode) */ - if (!data->id_det_gpio != !data->vbus_det_gpio) { - dev_err(dev, "failed to get id or vbus detect pin\n"); + /* vbus_det without id_det makes no sense, and is not supported */ + if (data->vbus_det_gpio && !data->id_det_gpio) { + dev_err(dev, "usb0_id_det missing or invalid\n"); return -ENODEV; } @@ -565,7 +592,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) data->id_det_irq = gpiod_to_irq(data->id_det_gpio); data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio); - if (data->id_det_irq < 0 || data->vbus_det_irq < 0) + if ((data->id_det_gpio && data->id_det_irq < 0) || + (data->vbus_det_gpio && data->vbus_det_irq < 0)) data->phy0_poll = true; if (data->id_det_irq >= 0) { -- cgit v1.2.3 From 8665c18bece7965c3690ac3824bef2f97bae3d71 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 13 Jun 2015 14:37:51 +0200 Subject: phy-sun4i-usb: Add support for monitoring vbus via a power-supply On some boards there is no vbus_det gpio pin, instead vbus-detection for otg can be done via the pmic. This commit adds support for monitoring vbus_det via the power_supply exported by the pmic, enabling support for otg on these boards. Signed-off-by: Hans de Goede Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/Kconfig | 1 + drivers/phy/phy-sun4i-usb.c | 76 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 70 insertions(+), 7 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index c0c1ad2e2c01..0fe9bff7b37b 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -209,6 +209,7 @@ config PHY_SUN4I_USB depends on ARCH_SUNXI && HAS_IOMEM && OF depends on RESET_CONTROLLER depends on EXTCON + depends on POWER_SUPPLY select GENERIC_PHY help Enable this to support the transceiver that is part of Allwinner diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index 4ba9856ac71a..5138843ec42d 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -108,6 +109,9 @@ struct sun4i_usb_phy_data { bool phy0_poll; struct gpio_desc *id_det_gpio; struct gpio_desc *vbus_det_gpio; + struct power_supply *vbus_power_supply; + struct notifier_block vbus_power_nb; + bool vbus_power_nb_registered; int id_det_irq; int vbus_det_irq; int id_det; @@ -352,6 +356,30 @@ static struct phy_ops sun4i_usb_phy_ops = { .owner = THIS_MODULE, }; +static int sun4i_usb_phy0_get_vbus_det(struct sun4i_usb_phy_data *data) +{ + if (data->vbus_det_gpio) + return gpiod_get_value_cansleep(data->vbus_det_gpio); + + if (data->vbus_power_supply) { + union power_supply_propval val; + int r; + + r = power_supply_get_property(data->vbus_power_supply, + POWER_SUPPLY_PROP_PRESENT, &val); + if (r == 0) + return val.intval; + } + + /* Fallback: report vbus as high */ + return 1; +} + +static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data) +{ + return data->vbus_det_gpio || data->vbus_power_supply; +} + static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) { struct sun4i_usb_phy_data *data = @@ -360,10 +388,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) int id_det, vbus_det, id_notify = 0, vbus_notify = 0; id_det = gpiod_get_value_cansleep(data->id_det_gpio); - if (data->vbus_det_gpio) - vbus_det = gpiod_get_value_cansleep(data->vbus_det_gpio); - else - vbus_det = 1; /* Report vbus as high */ + vbus_det = sun4i_usb_phy0_get_vbus_det(data); mutex_lock(&phy0->mutex); @@ -378,7 +403,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) * without vbus detection report vbus low for long enough for * the musb-ip to end the current device session. */ - if (!data->vbus_det_gpio && id_det == 0) { + if (!sun4i_usb_phy0_have_vbus_det(data) && id_det == 0) { sun4i_usb_phy0_set_vbus_detect(phy0, 0); msleep(200); sun4i_usb_phy0_set_vbus_detect(phy0, 1); @@ -404,7 +429,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) * without vbus detection report vbus low for long enough to * the musb-ip to end the current host session. */ - if (!data->vbus_det_gpio && id_det == 1) { + if (!sun4i_usb_phy0_have_vbus_det(data) && id_det == 1) { mutex_lock(&phy0->mutex); sun4i_usb_phy0_set_vbus_detect(phy0, 0); msleep(1000); @@ -430,6 +455,20 @@ static irqreturn_t sun4i_usb_phy0_id_vbus_det_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static int sun4i_usb_phy0_vbus_notify(struct notifier_block *nb, + unsigned long val, void *v) +{ + struct sun4i_usb_phy_data *data = + container_of(nb, struct sun4i_usb_phy_data, vbus_power_nb); + struct power_supply *psy = v; + + /* Properties on the vbus_power_supply changed, scan vbus_det */ + if (val == PSY_EVENT_PROP_CHANGED && psy == data->vbus_power_supply) + mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME); + + return NOTIFY_OK; +} + static struct phy *sun4i_usb_phy_xlate(struct device *dev, struct of_phandle_args *args) { @@ -446,6 +485,8 @@ static int sun4i_usb_phy_remove(struct platform_device *pdev) struct device *dev = &pdev->dev; struct sun4i_usb_phy_data *data = dev_get_drvdata(dev); + if (data->vbus_power_nb_registered) + power_supply_unreg_notifier(&data->vbus_power_nb); if (data->id_det_irq >= 0) devm_free_irq(dev, data->id_det_irq, data); if (data->vbus_det_irq >= 0) @@ -522,8 +563,18 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) data->vbus_det_gpio = NULL; } + if (of_find_property(np, "usb0_vbus_power-supply", NULL)) { + data->vbus_power_supply = devm_power_supply_get_by_phandle(dev, + "usb0_vbus_power-supply"); + if (IS_ERR(data->vbus_power_supply)) + return PTR_ERR(data->vbus_power_supply); + + if (!data->vbus_power_supply) + return -EPROBE_DEFER; + } + /* vbus_det without id_det makes no sense, and is not supported */ - if (data->vbus_det_gpio && !data->id_det_gpio) { + if (sun4i_usb_phy0_have_vbus_det(data) && !data->id_det_gpio) { dev_err(dev, "usb0_id_det missing or invalid\n"); return -ENODEV; } @@ -620,6 +671,17 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) } } + if (data->vbus_power_supply) { + data->vbus_power_nb.notifier_call = sun4i_usb_phy0_vbus_notify; + data->vbus_power_nb.priority = 0; + ret = power_supply_reg_notifier(&data->vbus_power_nb); + if (ret) { + sun4i_usb_phy_remove(pdev); /* Stop detect work */ + return ret; + } + data->vbus_power_nb_registered = true; + } + phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate); if (IS_ERR(phy_provider)) { sun4i_usb_phy_remove(pdev); /* Stop detect work */ -- cgit v1.2.3 From 2c89e41f03fa9798405e07bae95760fc86a1068f Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 24 Jun 2015 10:40:53 +0200 Subject: phy: berlin: .owner field is setup by core There was big cleanup in past to remove this unneeded setting. Signed-off-by: Michal Simek Acked-by: Antoine Tenart Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-berlin-usb.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c index c6fc95b53083..d7431f6ab975 100644 --- a/drivers/phy/phy-berlin-usb.c +++ b/drivers/phy/phy-berlin-usb.c @@ -207,7 +207,6 @@ static struct platform_driver phy_berlin_usb_driver = { .probe = phy_berlin_usb_probe, .driver = { .name = "phy-berlin-usb", - .owner = THIS_MODULE, .of_match_table = phy_berlin_sata_of_match, }, }; -- cgit v1.2.3 From 456dedc9e70d2d99b928d215baa881c03369c613 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 24 Jun 2015 10:40:54 +0200 Subject: phy: berlin: Do not use sata name in usb phy driver copy and paste error from berlin sata phy driver. Signed-off-by: Michal Simek Acked-by: Antoine Tenart Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-berlin-usb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c index d7431f6ab975..762f0fbdc119 100644 --- a/drivers/phy/phy-berlin-usb.c +++ b/drivers/phy/phy-berlin-usb.c @@ -152,7 +152,7 @@ static struct phy_ops phy_berlin_usb_ops = { .owner = THIS_MODULE, }; -static const struct of_device_id phy_berlin_sata_of_match[] = { +static const struct of_device_id phy_berlin_usb_of_match[] = { { .compatible = "marvell,berlin2-usb-phy", .data = &phy_berlin_pll_dividers[0], @@ -163,12 +163,12 @@ static const struct of_device_id phy_berlin_sata_of_match[] = { }, { }, }; -MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match); +MODULE_DEVICE_TABLE(of, phy_berlin_usb_of_match); static int phy_berlin_usb_probe(struct platform_device *pdev) { const struct of_device_id *match = - of_match_device(phy_berlin_sata_of_match, &pdev->dev); + of_match_device(phy_berlin_usb_of_match, &pdev->dev); struct phy_berlin_usb_priv *priv; struct resource *res; struct phy *phy; @@ -207,7 +207,7 @@ static struct platform_driver phy_berlin_usb_driver = { .probe = phy_berlin_usb_probe, .driver = { .name = "phy-berlin-usb", - .of_match_table = phy_berlin_sata_of_match, + .of_match_table = phy_berlin_usb_of_match, }, }; module_platform_driver(phy_berlin_usb_driver); -- cgit v1.2.3 From 2508aaed39c94f61c11ee66787ed4702c8afbc67 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 24 Jun 2015 10:40:55 +0200 Subject: phy: berlin: Trivial coding style cleanup Remove unneeded space after tab. Signed-off-by: Michal Simek Acked-by: Antoine Tenart Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-berlin-usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c index 762f0fbdc119..0fe0d81c29ee 100644 --- a/drivers/phy/phy-berlin-usb.c +++ b/drivers/phy/phy-berlin-usb.c @@ -208,7 +208,7 @@ static struct platform_driver phy_berlin_usb_driver = { .driver = { .name = "phy-berlin-usb", .of_match_table = phy_berlin_usb_of_match, - }, + }, }; module_platform_driver(phy_berlin_usb_driver); -- cgit v1.2.3 From 511fdecc9bc98c7b498e72b0dfe8f34481334e4c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 10 Jul 2015 14:38:10 +0900 Subject: phy: Drop owner assignment from i2c_driver i2c_driver does not need to set an owner because i2c_register_driver() will set it. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-armada375-usb2.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-armada375-usb2.c b/drivers/phy/phy-armada375-usb2.c index 8ccc3952c13d..39c7d21f12da 100644 --- a/drivers/phy/phy-armada375-usb2.c +++ b/drivers/phy/phy-armada375-usb2.c @@ -149,7 +149,6 @@ static struct platform_driver armada375_usb_phy_driver = { .driver = { .of_match_table = of_usb_cluster_table, .name = "armada-375-usb-cluster", - .owner = THIS_MODULE, } }; module_platform_driver(armada375_usb_phy_driver); -- cgit v1.2.3 From 219bf1599e1f6c0cbdc2fe775a97c00bf1ae392d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 10 Jul 2015 15:26:27 +0900 Subject: phy: Drop owner assignment from platform_driver platform_driver does not need to set an owner because platform_driver_register() will set it. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-miphy28lp.c | 1 - drivers/phy/phy-qcom-ufs-qmp-14nm.c | 1 - drivers/phy/phy-qcom-ufs-qmp-20nm.c | 1 - drivers/phy/phy-rockchip-usb.c | 1 - 4 files changed, 4 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c index 5e257ef7ac05..677c290f4b14 100644 --- a/drivers/phy/phy-miphy28lp.c +++ b/drivers/phy/phy-miphy28lp.c @@ -1268,7 +1268,6 @@ static struct platform_driver miphy28lp_driver = { .probe = miphy28lp_probe, .driver = { .name = "miphy28lp-phy", - .owner = THIS_MODULE, .of_match_table = miphy28lp_of_match, } }; diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c index f5fc50a9fce7..e1eea1b379fc 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c @@ -191,7 +191,6 @@ static struct platform_driver ufs_qcom_phy_qmp_14nm_driver = { .driver = { .of_match_table = ufs_qcom_phy_qmp_14nm_of_match, .name = "ufs_qcom_phy_qmp_14nm", - .owner = THIS_MODULE, }, }; diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c index 8332f96b2c4a..fde8c876823b 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c @@ -247,7 +247,6 @@ static struct platform_driver ufs_qcom_phy_qmp_20nm_driver = { .driver = { .of_match_table = ufs_qcom_phy_qmp_20nm_of_match, .name = "ufs_qcom_phy_qmp_20nm", - .owner = THIS_MODULE, }, }; diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c index 7d4c33643768..bf78721b58f4 100644 --- a/drivers/phy/phy-rockchip-usb.c +++ b/drivers/phy/phy-rockchip-usb.c @@ -146,7 +146,6 @@ static struct platform_driver rockchip_usb_driver = { .probe = rockchip_usb_phy_probe, .driver = { .name = "rockchip-usb-phy", - .owner = THIS_MODULE, .of_match_table = rockchip_usb_phy_dt_ids, }, }; -- cgit v1.2.3 From 3d772c4adbf94ce6971be2e9272157f831bccb8f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 31 Jul 2015 10:01:41 +0200 Subject: phy-sun4i-sub: Move vbus-detect helper functions up in the file Move vbus-detect helper functions up in the file, just moving some code around, no functional changes what so ever. Signed-off-by: Hans de Goede Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-sun4i-usb.c | 48 ++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index 5138843ec42d..27ae89e0d3ca 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -294,6 +294,30 @@ static int sun4i_usb_phy_exit(struct phy *_phy) return 0; } +static int sun4i_usb_phy0_get_vbus_det(struct sun4i_usb_phy_data *data) +{ + if (data->vbus_det_gpio) + return gpiod_get_value_cansleep(data->vbus_det_gpio); + + if (data->vbus_power_supply) { + union power_supply_propval val; + int r; + + r = power_supply_get_property(data->vbus_power_supply, + POWER_SUPPLY_PROP_PRESENT, &val); + if (r == 0) + return val.intval; + } + + /* Fallback: report vbus as high */ + return 1; +} + +static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data) +{ + return data->vbus_det_gpio || data->vbus_power_supply; +} + static int sun4i_usb_phy_power_on(struct phy *_phy) { struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); @@ -356,30 +380,6 @@ static struct phy_ops sun4i_usb_phy_ops = { .owner = THIS_MODULE, }; -static int sun4i_usb_phy0_get_vbus_det(struct sun4i_usb_phy_data *data) -{ - if (data->vbus_det_gpio) - return gpiod_get_value_cansleep(data->vbus_det_gpio); - - if (data->vbus_power_supply) { - union power_supply_propval val; - int r; - - r = power_supply_get_property(data->vbus_power_supply, - POWER_SUPPLY_PROP_PRESENT, &val); - if (r == 0) - return val.intval; - } - - /* Fallback: report vbus as high */ - return 1; -} - -static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data) -{ - return data->vbus_det_gpio || data->vbus_power_supply; -} - static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) { struct sun4i_usb_phy_data *data = -- cgit v1.2.3 From 8083526e0585e23447ac9ea94ca3f6d32d6dee8f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 31 Jul 2015 10:01:42 +0200 Subject: phy-sun4i-usb: Only check vbus-det on power-on on boards with vbus-det data->vbus_det is always 1 on boards without a (working) vbus-det, skip the vbus_det test on such boards. This fixes the sun4i usb phy code never turning on Vbus on such boards. Signed-off-by: Hans de Goede Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-sun4i-usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index 27ae89e0d3ca..e2eb688d82f5 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -328,7 +328,8 @@ static int sun4i_usb_phy_power_on(struct phy *_phy) return 0; /* For phy0 only turn on Vbus if we don't have an ext. Vbus */ - if (phy->index == 0 && data->vbus_det) + if (phy->index == 0 && sun4i_usb_phy0_have_vbus_det(data) && + data->vbus_det) return 0; ret = regulator_enable(phy->vbus); -- cgit v1.2.3 From 42ad8f6721720513f3569a67b157fcff068aa92d Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Fri, 5 Jun 2015 08:27:03 +0800 Subject: phy: ulpi_phy: Add const qualifier to ops The ops is never changed in ulpi_phy_create(), so make it const. Signed-off-by: Axel Lin Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/ulpi_phy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/phy') diff --git a/drivers/phy/ulpi_phy.h b/drivers/phy/ulpi_phy.h index ac49fb6285ee..f2ebe490a4bc 100644 --- a/drivers/phy/ulpi_phy.h +++ b/drivers/phy/ulpi_phy.h @@ -5,7 +5,7 @@ * and it's controller, which is always the parent. */ static inline struct phy -*ulpi_phy_create(struct ulpi *ulpi, struct phy_ops *ops) +*ulpi_phy_create(struct ulpi *ulpi, const struct phy_ops *ops) { struct phy *phy; int ret; -- cgit v1.2.3 From 4a9e5ca1a54a3cb4a5f85359f646638cec567607 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Wed, 15 Jul 2015 15:33:51 +0800 Subject: phy: Constify struct phy_ops variables The phy_ops variables are never modified after initialized in these drivers, so make them const. Signed-off-by: Axel Lin Acked-by: Patrice Chotard Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-armada375-usb2.c | 2 +- drivers/phy/phy-bcm-kona-usb2.c | 2 +- drivers/phy/phy-berlin-sata.c | 2 +- drivers/phy/phy-berlin-usb.c | 2 +- drivers/phy/phy-brcmstb-sata.c | 2 +- drivers/phy/phy-dm816x-usb.c | 2 +- drivers/phy/phy-exynos-dp-video.c | 2 +- drivers/phy/phy-exynos-mipi-video.c | 2 +- drivers/phy/phy-exynos5-usbdrd.c | 2 +- drivers/phy/phy-exynos5250-sata.c | 2 +- drivers/phy/phy-hix5hd2-sata.c | 2 +- drivers/phy/phy-miphy28lp.c | 2 +- drivers/phy/phy-miphy365x.c | 2 +- drivers/phy/phy-mvebu-sata.c | 2 +- drivers/phy/phy-omap-usb2.c | 2 +- drivers/phy/phy-qcom-apq8064-sata.c | 2 +- drivers/phy/phy-qcom-ipq806x-sata.c | 2 +- drivers/phy/phy-qcom-ufs-i.h | 2 +- drivers/phy/phy-qcom-ufs-qmp-14nm.c | 2 +- drivers/phy/phy-qcom-ufs-qmp-20nm.c | 2 +- drivers/phy/phy-qcom-ufs.c | 2 +- drivers/phy/phy-rcar-gen2.c | 2 +- drivers/phy/phy-rockchip-usb.c | 2 +- drivers/phy/phy-samsung-usb2.c | 2 +- drivers/phy/phy-spear1310-miphy.c | 2 +- drivers/phy/phy-spear1340-miphy.c | 2 +- drivers/phy/phy-stih41x-usb.c | 2 +- drivers/phy/phy-sun4i-usb.c | 2 +- drivers/phy/phy-sun9i-usb.c | 2 +- drivers/phy/phy-ti-pipe3.c | 2 +- drivers/phy/phy-tusb1210.c | 2 +- 31 files changed, 31 insertions(+), 31 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-armada375-usb2.c b/drivers/phy/phy-armada375-usb2.c index 39c7d21f12da..1a3db288c0a9 100644 --- a/drivers/phy/phy-armada375-usb2.c +++ b/drivers/phy/phy-armada375-usb2.c @@ -51,7 +51,7 @@ static int armada375_usb_phy_init(struct phy *phy) return 0; } -static struct phy_ops armada375_usb_phy_ops = { +static const struct phy_ops armada375_usb_phy_ops = { .init = armada375_usb_phy_init, .owner = THIS_MODULE, }; diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/phy-bcm-kona-usb2.c index ef2dc1aab2b9..7b67fe49e30b 100644 --- a/drivers/phy/phy-bcm-kona-usb2.c +++ b/drivers/phy/phy-bcm-kona-usb2.c @@ -91,7 +91,7 @@ static int bcm_kona_usb_phy_power_off(struct phy *gphy) return 0; } -static struct phy_ops ops = { +static const struct phy_ops ops = { .init = bcm_kona_usb_phy_init, .power_on = bcm_kona_usb_phy_power_on, .power_off = bcm_kona_usb_phy_power_off, diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c index 6f3e06d687de..0062027afb1e 100644 --- a/drivers/phy/phy-berlin-sata.c +++ b/drivers/phy/phy-berlin-sata.c @@ -176,7 +176,7 @@ static struct phy *phy_berlin_sata_phy_xlate(struct device *dev, return priv->phys[i]->phy; } -static struct phy_ops phy_berlin_sata_ops = { +static const struct phy_ops phy_berlin_sata_ops = { .power_on = phy_berlin_sata_power_on, .power_off = phy_berlin_sata_power_off, .owner = THIS_MODULE, diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c index 0fe0d81c29ee..204ee5952fb3 100644 --- a/drivers/phy/phy-berlin-usb.c +++ b/drivers/phy/phy-berlin-usb.c @@ -147,7 +147,7 @@ static int phy_berlin_usb_power_on(struct phy *phy) return 0; } -static struct phy_ops phy_berlin_usb_ops = { +static const struct phy_ops phy_berlin_usb_ops = { .power_on = phy_berlin_usb_power_on, .owner = THIS_MODULE, }; diff --git a/drivers/phy/phy-brcmstb-sata.c b/drivers/phy/phy-brcmstb-sata.c index b7e303d28caf..8a2cb16a1937 100644 --- a/drivers/phy/phy-brcmstb-sata.c +++ b/drivers/phy/phy-brcmstb-sata.c @@ -122,7 +122,7 @@ static int brcm_sata_phy_init(struct phy *phy) return 0; } -static struct phy_ops phy_ops_28nm = { +static const struct phy_ops phy_ops_28nm = { .init = brcm_sata_phy_init, .owner = THIS_MODULE, }; diff --git a/drivers/phy/phy-dm816x-usb.c b/drivers/phy/phy-dm816x-usb.c index 7b42555ddd51..b4bbef664d20 100644 --- a/drivers/phy/phy-dm816x-usb.c +++ b/drivers/phy/phy-dm816x-usb.c @@ -113,7 +113,7 @@ static int dm816x_usb_phy_init(struct phy *x) return 0; } -static struct phy_ops ops = { +static const struct phy_ops ops = { .init = dm816x_usb_phy_init, .owner = THIS_MODULE, }; diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c index 179cbf9451aa..34b06154e5d9 100644 --- a/drivers/phy/phy-exynos-dp-video.c +++ b/drivers/phy/phy-exynos-dp-video.c @@ -48,7 +48,7 @@ static int exynos_dp_video_phy_power_off(struct phy *phy) EXYNOS5_PHY_ENABLE, 0); } -static struct phy_ops exynos_dp_video_phy_ops = { +static const struct phy_ops exynos_dp_video_phy_ops = { .power_on = exynos_dp_video_phy_power_on, .power_off = exynos_dp_video_phy_power_off, .owner = THIS_MODULE, diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c index df7519a39ba0..2a54caba93b4 100644 --- a/drivers/phy/phy-exynos-mipi-video.c +++ b/drivers/phy/phy-exynos-mipi-video.c @@ -124,7 +124,7 @@ static struct phy *exynos_mipi_video_phy_xlate(struct device *dev, return state->phys[args->args[0]].phy; } -static struct phy_ops exynos_mipi_video_phy_ops = { +static const struct phy_ops exynos_mipi_video_phy_ops = { .power_on = exynos_mipi_video_phy_power_on, .power_off = exynos_mipi_video_phy_power_off, .owner = THIS_MODULE, diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c index d72ef15b0d68..20696f53303f 100644 --- a/drivers/phy/phy-exynos5-usbdrd.c +++ b/drivers/phy/phy-exynos5-usbdrd.c @@ -537,7 +537,7 @@ static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev, return phy_drd->phys[args->args[0]].phy; } -static struct phy_ops exynos5_usbdrd_phy_ops = { +static const struct phy_ops exynos5_usbdrd_phy_ops = { .init = exynos5_usbdrd_phy_init, .exit = exynos5_usbdrd_phy_exit, .power_on = exynos5_usbdrd_phy_power_on, diff --git a/drivers/phy/phy-exynos5250-sata.c b/drivers/phy/phy-exynos5250-sata.c index bc858cc800a1..60e13afcd9b8 100644 --- a/drivers/phy/phy-exynos5250-sata.c +++ b/drivers/phy/phy-exynos5250-sata.c @@ -154,7 +154,7 @@ static int exynos_sata_phy_init(struct phy *phy) return ret; } -static struct phy_ops exynos_sata_phy_ops = { +static const struct phy_ops exynos_sata_phy_ops = { .init = exynos_sata_phy_init, .power_on = exynos_sata_phy_power_on, .power_off = exynos_sata_phy_power_off, diff --git a/drivers/phy/phy-hix5hd2-sata.c b/drivers/phy/phy-hix5hd2-sata.c index d6b22659cac1..e5ab3aa78b9d 100644 --- a/drivers/phy/phy-hix5hd2-sata.c +++ b/drivers/phy/phy-hix5hd2-sata.c @@ -129,7 +129,7 @@ static int hix5hd2_sata_phy_init(struct phy *phy) return 0; } -static struct phy_ops hix5hd2_sata_phy_ops = { +static const struct phy_ops hix5hd2_sata_phy_ops = { .init = hix5hd2_sata_phy_init, .owner = THIS_MODULE, }; diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c index 677c290f4b14..c47b56b4a2b8 100644 --- a/drivers/phy/phy-miphy28lp.c +++ b/drivers/phy/phy-miphy28lp.c @@ -1132,7 +1132,7 @@ static struct phy *miphy28lp_xlate(struct device *dev, return miphy_phy->phy; } -static struct phy_ops miphy28lp_ops = { +static const struct phy_ops miphy28lp_ops = { .init = miphy28lp_init, .owner = THIS_MODULE, }; diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c index 0ff354d6e183..00a686a073ed 100644 --- a/drivers/phy/phy-miphy365x.c +++ b/drivers/phy/phy-miphy365x.c @@ -510,7 +510,7 @@ static struct phy *miphy365x_xlate(struct device *dev, return miphy_phy->phy; } -static struct phy_ops miphy365x_ops = { +static const struct phy_ops miphy365x_ops = { .init = miphy365x_init, .owner = THIS_MODULE, }; diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/phy-mvebu-sata.c index 03b94f92e6f1..768ce92e81ce 100644 --- a/drivers/phy/phy-mvebu-sata.c +++ b/drivers/phy/phy-mvebu-sata.c @@ -75,7 +75,7 @@ static int phy_mvebu_sata_power_off(struct phy *phy) return 0; } -static struct phy_ops phy_mvebu_sata_ops = { +static const struct phy_ops phy_mvebu_sata_ops = { .power_on = phy_mvebu_sata_power_on, .power_off = phy_mvebu_sata_power_off, .owner = THIS_MODULE, diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c index c1a468686bdc..0fe80589ffbe 100644 --- a/drivers/phy/phy-omap-usb2.c +++ b/drivers/phy/phy-omap-usb2.c @@ -137,7 +137,7 @@ static int omap_usb_init(struct phy *x) return 0; } -static struct phy_ops ops = { +static const struct phy_ops ops = { .init = omap_usb_init, .power_on = omap_usb_power_on, .power_off = omap_usb_power_off, diff --git a/drivers/phy/phy-qcom-apq8064-sata.c b/drivers/phy/phy-qcom-apq8064-sata.c index 4b243f7a10e4..69ce2afac015 100644 --- a/drivers/phy/phy-qcom-apq8064-sata.c +++ b/drivers/phy/phy-qcom-apq8064-sata.c @@ -204,7 +204,7 @@ static int qcom_apq8064_sata_phy_exit(struct phy *generic_phy) return 0; } -static struct phy_ops qcom_apq8064_sata_phy_ops = { +static const struct phy_ops qcom_apq8064_sata_phy_ops = { .init = qcom_apq8064_sata_phy_init, .exit = qcom_apq8064_sata_phy_exit, .owner = THIS_MODULE, diff --git a/drivers/phy/phy-qcom-ipq806x-sata.c b/drivers/phy/phy-qcom-ipq806x-sata.c index 6f2fe2627916..0ad127cc9298 100644 --- a/drivers/phy/phy-qcom-ipq806x-sata.c +++ b/drivers/phy/phy-qcom-ipq806x-sata.c @@ -126,7 +126,7 @@ static int qcom_ipq806x_sata_phy_exit(struct phy *generic_phy) return 0; } -static struct phy_ops qcom_ipq806x_sata_phy_ops = { +static const struct phy_ops qcom_ipq806x_sata_phy_ops = { .init = qcom_ipq806x_sata_phy_init, .exit = qcom_ipq806x_sata_phy_exit, .owner = THIS_MODULE, diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h index 591a39175e8a..2bd5ce43a724 100644 --- a/drivers/phy/phy-qcom-ufs-i.h +++ b/drivers/phy/phy-qcom-ufs-i.h @@ -150,7 +150,7 @@ int ufs_qcom_phy_remove(struct phy *generic_phy, struct ufs_qcom_phy *ufs_qcom_phy); struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, struct ufs_qcom_phy *common_cfg, - struct phy_ops *ufs_qcom_phy_gen_ops, + const struct phy_ops *ufs_qcom_phy_gen_ops, struct ufs_qcom_phy_specific_ops *phy_spec_ops); int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy, struct ufs_qcom_phy_calibration *tbl_A, int tbl_size_A, diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c index e1eea1b379fc..56631e77c11d 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c @@ -115,7 +115,7 @@ static int ufs_qcom_phy_qmp_14nm_is_pcs_ready(struct ufs_qcom_phy *phy_common) return err; } -static struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = { +static const struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = { .init = ufs_qcom_phy_qmp_14nm_init, .exit = ufs_qcom_phy_exit, .power_on = ufs_qcom_phy_power_on, diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c index fde8c876823b..b16ea77d07b9 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c @@ -171,7 +171,7 @@ static int ufs_qcom_phy_qmp_20nm_is_pcs_ready(struct ufs_qcom_phy *phy_common) return err; } -static struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = { +static const struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = { .init = ufs_qcom_phy_qmp_20nm_init, .exit = ufs_qcom_phy_exit, .power_on = ufs_qcom_phy_power_on, diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c index f9c618f0ab6e..49a1ed0cef56 100644 --- a/drivers/phy/phy-qcom-ufs.c +++ b/drivers/phy/phy-qcom-ufs.c @@ -77,7 +77,7 @@ EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate); struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, struct ufs_qcom_phy *common_cfg, - struct phy_ops *ufs_qcom_phy_gen_ops, + const struct phy_ops *ufs_qcom_phy_gen_ops, struct ufs_qcom_phy_specific_ops *phy_spec_ops) { int err; diff --git a/drivers/phy/phy-rcar-gen2.c b/drivers/phy/phy-rcar-gen2.c index 39d9b2995435..6e0d9fa8e1d1 100644 --- a/drivers/phy/phy-rcar-gen2.c +++ b/drivers/phy/phy-rcar-gen2.c @@ -184,7 +184,7 @@ static int rcar_gen2_phy_power_off(struct phy *p) return 0; } -static struct phy_ops rcar_gen2_phy_ops = { +static const struct phy_ops rcar_gen2_phy_ops = { .init = rcar_gen2_phy_init, .exit = rcar_gen2_phy_exit, .power_on = rcar_gen2_phy_power_on, diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c index bf78721b58f4..5a5c073e72fe 100644 --- a/drivers/phy/phy-rockchip-usb.c +++ b/drivers/phy/phy-rockchip-usb.c @@ -84,7 +84,7 @@ static int rockchip_usb_phy_power_on(struct phy *_phy) return 0; } -static struct phy_ops ops = { +static const struct phy_ops ops = { .power_on = rockchip_usb_phy_power_on, .power_off = rockchip_usb_phy_power_off, .owner = THIS_MODULE, diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c index 55b6994932e3..f278a9c547e1 100644 --- a/drivers/phy/phy-samsung-usb2.c +++ b/drivers/phy/phy-samsung-usb2.c @@ -71,7 +71,7 @@ static int samsung_usb2_phy_power_off(struct phy *phy) return 0; } -static struct phy_ops samsung_usb2_phy_ops = { +static const struct phy_ops samsung_usb2_phy_ops = { .power_on = samsung_usb2_phy_power_on, .power_off = samsung_usb2_phy_power_off, .owner = THIS_MODULE, diff --git a/drivers/phy/phy-spear1310-miphy.c b/drivers/phy/phy-spear1310-miphy.c index 45d0005b2203..ed67e98e54ca 100644 --- a/drivers/phy/phy-spear1310-miphy.c +++ b/drivers/phy/phy-spear1310-miphy.c @@ -179,7 +179,7 @@ static const struct of_device_id spear1310_miphy_of_match[] = { }; MODULE_DEVICE_TABLE(of, spear1310_miphy_of_match); -static struct phy_ops spear1310_miphy_ops = { +static const struct phy_ops spear1310_miphy_ops = { .init = spear1310_miphy_init, .exit = spear1310_miphy_exit, .owner = THIS_MODULE, diff --git a/drivers/phy/phy-spear1340-miphy.c b/drivers/phy/phy-spear1340-miphy.c index 494240da4a39..97280c0cf612 100644 --- a/drivers/phy/phy-spear1340-miphy.c +++ b/drivers/phy/phy-spear1340-miphy.c @@ -189,7 +189,7 @@ static const struct of_device_id spear1340_miphy_of_match[] = { }; MODULE_DEVICE_TABLE(of, spear1340_miphy_of_match); -static struct phy_ops spear1340_miphy_ops = { +static const struct phy_ops spear1340_miphy_ops = { .init = spear1340_miphy_init, .exit = spear1340_miphy_exit, .owner = THIS_MODULE, diff --git a/drivers/phy/phy-stih41x-usb.c b/drivers/phy/phy-stih41x-usb.c index c093b472b57d..0ac74639ad02 100644 --- a/drivers/phy/phy-stih41x-usb.c +++ b/drivers/phy/phy-stih41x-usb.c @@ -112,7 +112,7 @@ static int stih41x_usb_phy_power_off(struct phy *phy) return 0; } -static struct phy_ops stih41x_usb_phy_ops = { +static const struct phy_ops stih41x_usb_phy_ops = { .init = stih41x_usb_phy_init, .power_on = stih41x_usb_phy_power_on, .power_off = stih41x_usb_phy_power_off, diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index e2eb688d82f5..623c7143152e 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -373,7 +373,7 @@ void sun4i_usb_phy_set_squelch_detect(struct phy *_phy, bool enabled) sun4i_usb_phy_write(phy, PHY_SQUELCH_DETECT, enabled ? 0 : 2, 2); } -static struct phy_ops sun4i_usb_phy_ops = { +static const struct phy_ops sun4i_usb_phy_ops = { .init = sun4i_usb_phy_init, .exit = sun4i_usb_phy_exit, .power_on = sun4i_usb_phy_power_on, diff --git a/drivers/phy/phy-sun9i-usb.c b/drivers/phy/phy-sun9i-usb.c index 0095914a662c..ac4f31abefe3 100644 --- a/drivers/phy/phy-sun9i-usb.c +++ b/drivers/phy/phy-sun9i-usb.c @@ -114,7 +114,7 @@ static int sun9i_usb_phy_exit(struct phy *_phy) return 0; } -static struct phy_ops sun9i_usb_phy_ops = { +static const struct phy_ops sun9i_usb_phy_ops = { .init = sun9i_usb_phy_init, .exit = sun9i_usb_phy_exit, .owner = THIS_MODULE, diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c index 53f295c1bab1..2038f1945f2c 100644 --- a/drivers/phy/phy-ti-pipe3.c +++ b/drivers/phy/phy-ti-pipe3.c @@ -279,7 +279,7 @@ static int ti_pipe3_exit(struct phy *x) return 0; } -static struct phy_ops ops = { +static const struct phy_ops ops = { .init = ti_pipe3_init, .exit = ti_pipe3_exit, .power_on = ti_pipe3_power_on, diff --git a/drivers/phy/phy-tusb1210.c b/drivers/phy/phy-tusb1210.c index 07efdd318bdc..2535d792d57a 100644 --- a/drivers/phy/phy-tusb1210.c +++ b/drivers/phy/phy-tusb1210.c @@ -53,7 +53,7 @@ static int tusb1210_power_off(struct phy *phy) return 0; } -static struct phy_ops phy_ops = { +static const struct phy_ops phy_ops = { .power_on = tusb1210_power_on, .power_off = tusb1210_power_off, .owner = THIS_MODULE, -- cgit v1.2.3 From cfd093bbb5fe84ec8c7bb069fe618159a8b601f5 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Sun, 9 Aug 2015 00:02:41 +0200 Subject: phy: lpc18xx-usb-otg: fix clock order in phy init Changing the frequency of the USB clock must be done before the PLL is powered on (prepared). This matters when the USB clock is not setup by either boot ROM or boot loader. Reorder the function calls to adhere to the order noted in the user manual. Signed-off-by: Joachim Eastwood Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-lpc18xx-usb-otg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/phy') diff --git a/drivers/phy/phy-lpc18xx-usb-otg.c b/drivers/phy/phy-lpc18xx-usb-otg.c index 3aa8e4de1b03..3b7a71eb5b7e 100644 --- a/drivers/phy/phy-lpc18xx-usb-otg.c +++ b/drivers/phy/phy-lpc18xx-usb-otg.c @@ -33,12 +33,12 @@ static int lpc18xx_usb_otg_phy_init(struct phy *phy) struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy); int ret; - ret = clk_prepare(lpc->clk); + /* The PHY must be clocked at 480 MHz */ + ret = clk_set_rate(lpc->clk, 480000000); if (ret) return ret; - /* The PHY must be clocked at 480 MHz */ - return clk_set_rate(lpc->clk, 480000000); + return clk_prepare(lpc->clk); } static int lpc18xx_usb_otg_phy_exit(struct phy *phy) -- cgit v1.2.3