diff options
Diffstat (limited to 'drivers/usb/phy')
27 files changed, 215 insertions, 2685 deletions
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index aff702c0eb9f..0f8ab981d572 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -137,35 +137,6 @@ config USB_ISP1301  	  To compile this driver as a module, choose M here: the  	  module will be called phy-isp1301. -config USB_MSM_OTG -	tristate "Qualcomm on-chip USB OTG controller support" -	depends on (USB || USB_GADGET) && (ARCH_QCOM || COMPILE_TEST) -	depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y' -	depends on RESET_CONTROLLER -	select USB_PHY -	help -	  Enable this to support the USB OTG transceiver on Qualcomm chips. It -	  handles PHY initialization, clock management, and workarounds -	  required after resetting the hardware and power management. -	  This driver is required even for peripheral only or host only -	  mode configurations. -	  This driver is not supported on boards like trout which -	  has an external PHY. - -config USB_QCOM_8X16_PHY -	tristate "Qualcomm APQ8016/MSM8916 on-chip USB PHY controller support" -	depends on ARCH_QCOM || COMPILE_TEST -	depends on RESET_CONTROLLER -	select USB_PHY -	select USB_ULPI_VIEWPORT -	help -	  Enable this to support the USB transceiver on Qualcomm 8x16 chipsets. -	  It handles PHY initialization, clock management, power management, -	  and workarounds required after resetting the hardware. - -	  To compile this driver as a module, choose M here: the -	  module will be called phy-qcom-8x16-usb. -  config USB_MV_OTG  	tristate "Marvell USB OTG support"  	depends on USB_EHCI_MV && USB_MV_UDC && PM && USB_OTG diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index e7c9ca8cafb0..25e579fb92b8 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0  #  # Makefile for physical layer USB drivers  # @@ -18,8 +19,6 @@ obj-$(CONFIG_TWL6030_USB)		+= phy-twl6030-usb.o  obj-$(CONFIG_USB_EHCI_TEGRA)		+= phy-tegra-usb.o  obj-$(CONFIG_USB_GPIO_VBUS)		+= phy-gpio-vbus-usb.o  obj-$(CONFIG_USB_ISP1301)		+= phy-isp1301.o -obj-$(CONFIG_USB_MSM_OTG)		+= phy-msm-usb.o -obj-$(CONFIG_USB_QCOM_8X16_PHY)	+= phy-qcom-8x16-usb.o  obj-$(CONFIG_USB_MV_OTG)		+= phy-mv-usb.o  obj-$(CONFIG_USB_MXS_PHY)		+= phy-mxs-usb.o  obj-$(CONFIG_USB_ULPI)			+= phy-ulpi.o diff --git a/drivers/usb/phy/of.c b/drivers/usb/phy/of.c index 66ffa82457a8..1ab134f45d67 100644 --- a/drivers/usb/phy/of.c +++ b/drivers/usb/phy/of.c @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+  /*   * USB of helper code - * - * 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.   */  #include <linux/kernel.h> diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index 61bf2285d5b1..87295313a10c 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+  /*   * USB transceiver driver for AB8500 family chips   * @@ -5,21 +6,6 @@   * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>   * Avinash Kumar <avinash.kumar@stericsson.com>   * Thirupathi Chippakurthy <thirupathi.chippakurthy@stericsson.com> - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - *   */  #include <linux/module.h> diff --git a/drivers/usb/phy/phy-am335x-control.c b/drivers/usb/phy/phy-am335x-control.c index 5f5f19813fde..a3cb25cb74f8 100644 --- a/drivers/usb/phy/phy-am335x-control.c +++ b/drivers/usb/phy/phy-am335x-control.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/module.h>  #include <linux/platform_device.h>  #include <linux/err.h> diff --git a/drivers/usb/phy/phy-am335x-control.h b/drivers/usb/phy/phy-am335x-control.h index e86b3165d69d..cd4acfc6e360 100644 --- a/drivers/usb/phy/phy-am335x-control.h +++ b/drivers/usb/phy/phy-am335x-control.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  #ifndef _AM335x_PHY_CONTROL_H_  #define _AM335x_PHY_CONTROL_H_ diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c index 7e5aece769da..b36fa8b953d0 100644 --- a/drivers/usb/phy/phy-am335x.c +++ b/drivers/usb/phy/phy-am335x.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  #include <linux/module.h>  #include <linux/platform_device.h>  #include <linux/dma-mapping.h> diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c index cf8f40ae6e01..900875f326d7 100644 --- a/drivers/usb/phy/phy-fsl-usb.c +++ b/drivers/usb/phy/phy-fsl-usb.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+  /*   * Copyright (C) 2007,2008 Freescale semiconductor, Inc.   * @@ -5,20 +6,6 @@   *         Jerry Huang <Chang-Ming.Huang@freescale.com>   *   * Initialization based on code from Shlomi Gridish. - * - * 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. - * - * You should have received a copy of the  GNU General Public License along - * with this program; if not, write  to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA.   */  #include <linux/module.h> diff --git a/drivers/usb/phy/phy-fsl-usb.h b/drivers/usb/phy/phy-fsl-usb.h index 23149954a09c..43d410f6641b 100644 --- a/drivers/usb/phy/phy-fsl-usb.h +++ b/drivers/usb/phy/phy-fsl-usb.h @@ -1,19 +1,5 @@ -/* Copyright (C) 2007,2008 Freescale Semiconductor, Inc. - * - * 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. - * - * You should have received a copy of the  GNU General Public License along - * with this program; if not, write  to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ +// SPDX-License-Identifier: GPL-2.0+ +/* Copyright (C) 2007,2008 Freescale Semiconductor, Inc. */  #include <linux/usb/otg-fsm.h>  #include <linux/usb/otg.h> diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c index 89d6e7a5fdb7..74ba88297991 100644 --- a/drivers/usb/phy/phy-generic.c +++ b/drivers/usb/phy/phy-generic.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+  /*   * NOP USB transceiver for all USB transceiver which are either built-in   * into USB IP or which are mostly autonomous. @@ -5,20 +6,6 @@   * Copyright (C) 2009 Texas Instruments Inc   * Author: Ajay Kumar Gupta <ajay.gupta@ti.com>   * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - *   * Current status:   *	This provides a "nop" transceiver for PHYs which are   *	autonomous such as isp1504, isp1707, etc. @@ -224,7 +211,7 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,  	int err = 0;  	u32 clk_rate = 0; -	bool needs_vcc = false; +	bool needs_vcc = false, needs_clk = false;  	if (dev->of_node) {  		struct device_node *node = dev->of_node; @@ -233,6 +220,7 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,  			clk_rate = 0;  		needs_vcc = of_property_read_bool(node, "vcc-supply"); +		needs_clk = of_property_read_bool(node, "clocks");  		nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset",  							   GPIOD_ASIS);  		err = PTR_ERR_OR_ZERO(nop->gpiod_reset); @@ -275,6 +263,8 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,  	if (IS_ERR(nop->clk)) {  		dev_dbg(dev, "Can't get phy clock: %ld\n",  					PTR_ERR(nop->clk)); +		if (needs_clk) +			return PTR_ERR(nop->clk);  	}  	if (!IS_ERR(nop->clk) && clk_rate) { diff --git a/drivers/usb/phy/phy-generic.h b/drivers/usb/phy/phy-generic.h index 0d0eadd54ed9..97289627561d 100644 --- a/drivers/usb/phy/phy-generic.h +++ b/drivers/usb/phy/phy-generic.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */  #ifndef _PHY_GENERIC_H_  #define _PHY_GENERIC_H_ diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c index f66120db8a41..553e2573c74f 100644 --- a/drivers/usb/phy/phy-gpio-vbus-usb.c +++ b/drivers/usb/phy/phy-gpio-vbus-usb.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * gpio-vbus.c - simple GPIO VBUS sensing driver for B peripheral devices   *   * Copyright (c) 2008 Philipp Zabel <philipp.zabel@gmail.com> - * - * 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 <linux/kernel.h> diff --git a/drivers/usb/phy/phy-isp1301-omap.c b/drivers/usb/phy/phy-isp1301-omap.c index c6052c814bcc..7041ba030052 100644 --- a/drivers/usb/phy/phy-isp1301-omap.c +++ b/drivers/usb/phy/phy-isp1301-omap.c @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+  /*   * isp1301_omap - ISP 1301 USB transceiver, talking to OMAP OTG controller   *   * Copyright (C) 2004 Texas Instruments   * Copyright (C) 2004 David Brownell - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */  #include <linux/kernel.h> @@ -1183,9 +1170,11 @@ static irqreturn_t isp1301_irq(int irq, void *isp)  	return IRQ_HANDLED;  } -static void isp1301_timer(unsigned long _isp) +static void isp1301_timer(struct timer_list *t)  { -	isp1301_defer_work((void *)_isp, WORK_TIMER); +	struct isp1301 *isp = from_timer(isp, t, timer); + +	isp1301_defer_work(isp, WORK_TIMER);  }  /*-------------------------------------------------------------------------*/ @@ -1222,7 +1211,6 @@ static int isp1301_remove(struct i2c_client *i2c)  	if (machine_is_omap_h2())  		gpio_free(2); -	isp->timer.data = 0;  	set_bit(WORK_STOP, &isp->todo);  	del_timer_sync(&isp->timer);  	flush_work(&isp->work); @@ -1507,9 +1495,7 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)  	}  	INIT_WORK(&isp->work, isp1301_work); -	init_timer(&isp->timer); -	isp->timer.function = isp1301_timer; -	isp->timer.data = (unsigned long) isp; +	timer_setup(&isp->timer, isp1301_timer, 0);  	i2c_set_clientdata(i2c, isp);  	isp->client = i2c; diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c index f333024660b4..93b7d6a30aad 100644 --- a/drivers/usb/phy/phy-isp1301.c +++ b/drivers/usb/phy/phy-isp1301.c @@ -1,13 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * NXP ISP1301 USB transceiver driver   *   * Copyright (C) 2012 Roland Stigge   *   * Author: Roland Stigge <stigge@antcom.de> - * - * 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 <linux/module.h> diff --git a/drivers/usb/phy/phy-keystone.c b/drivers/usb/phy/phy-keystone.c index 01d4e4cdbc79..19871266312d 100644 --- a/drivers/usb/phy/phy-keystone.c +++ b/drivers/usb/phy/phy-keystone.c @@ -1,19 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+  /*   * phy-keystone - USB PHY, talking to dwc3 controller in Keystone.   *   * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com - * 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.   *   * Author: WingMan Kwok <w-kwok2@ti.com> - * - * 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 <linux/module.h> diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c deleted file mode 100644 index 3d0dd2f97415..000000000000 --- a/drivers/usb/phy/phy-msm-usb.c +++ /dev/null @@ -1,2085 +0,0 @@ -/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include <linux/module.h> -#include <linux/device.h> -#include <linux/extcon.h> -#include <linux/gpio/consumer.h> -#include <linux/platform_device.h> -#include <linux/clk.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/err.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/ioport.h> -#include <linux/uaccess.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <linux/pm_runtime.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/reboot.h> -#include <linux/reset.h> -#include <linux/types.h> -#include <linux/usb/otg.h> - -#include <linux/usb.h> -#include <linux/usb/otg.h> -#include <linux/usb/of.h> -#include <linux/usb/ulpi.h> -#include <linux/usb/gadget.h> -#include <linux/usb/hcd.h> -#include <linux/usb/msm_hsusb_hw.h> -#include <linux/regulator/consumer.h> - -/** - * OTG control - * - * OTG_NO_CONTROL	Id/VBUS notifications not required. Useful in host - *                      only configuration. - * OTG_PHY_CONTROL	Id/VBUS notifications comes form USB PHY. - * OTG_PMIC_CONTROL	Id/VBUS notifications comes from PMIC hardware. - * OTG_USER_CONTROL	Id/VBUS notifcations comes from User via sysfs. - * - */ -enum otg_control_type { -	OTG_NO_CONTROL = 0, -	OTG_PHY_CONTROL, -	OTG_PMIC_CONTROL, -	OTG_USER_CONTROL, -}; - -/** - * PHY used in - * - * INVALID_PHY			Unsupported PHY - * CI_45NM_INTEGRATED_PHY	Chipidea 45nm integrated PHY - * SNPS_28NM_INTEGRATED_PHY	Synopsis 28nm integrated PHY - * - */ -enum msm_usb_phy_type { -	INVALID_PHY = 0, -	CI_45NM_INTEGRATED_PHY, -	SNPS_28NM_INTEGRATED_PHY, -}; - -#define IDEV_CHG_MAX	1500 -#define IUNIT		100 - -/** - * Different states involved in USB charger detection. - * - * USB_CHG_STATE_UNDEFINED	USB charger is not connected or detection - *                              process is not yet started. - * USB_CHG_STATE_WAIT_FOR_DCD	Waiting for Data pins contact. - * USB_CHG_STATE_DCD_DONE	Data pin contact is detected. - * USB_CHG_STATE_PRIMARY_DONE	Primary detection is completed (Detects - *                              between SDP and DCP/CDP). - * USB_CHG_STATE_SECONDARY_DONE	Secondary detection is completed (Detects - *                              between DCP and CDP). - * USB_CHG_STATE_DETECTED	USB charger type is determined. - * - */ -enum usb_chg_state { -	USB_CHG_STATE_UNDEFINED = 0, -	USB_CHG_STATE_WAIT_FOR_DCD, -	USB_CHG_STATE_DCD_DONE, -	USB_CHG_STATE_PRIMARY_DONE, -	USB_CHG_STATE_SECONDARY_DONE, -	USB_CHG_STATE_DETECTED, -}; - -/** - * USB charger types - * - * USB_INVALID_CHARGER	Invalid USB charger. - * USB_SDP_CHARGER	Standard downstream port. Refers to a downstream port - *                      on USB2.0 compliant host/hub. - * USB_DCP_CHARGER	Dedicated charger port (AC charger/ Wall charger). - * USB_CDP_CHARGER	Charging downstream port. Enumeration can happen and - *                      IDEV_CHG_MAX can be drawn irrespective of USB state. - * - */ -enum usb_chg_type { -	USB_INVALID_CHARGER = 0, -	USB_SDP_CHARGER, -	USB_DCP_CHARGER, -	USB_CDP_CHARGER, -}; - -/** - * struct msm_otg_platform_data - platform device data - *              for msm_otg driver. - * @phy_init_seq: PHY configuration sequence values. Value of -1 is reserved as - *              "do not overwrite default vaule at this address". - * @phy_init_sz: PHY configuration sequence size. - * @vbus_power: VBUS power on/off routine. - * @power_budget: VBUS power budget in mA (0 will be treated as 500mA). - * @mode: Supported mode (OTG/peripheral/host). - * @otg_control: OTG switch controlled by user/Id pin - */ -struct msm_otg_platform_data { -	int *phy_init_seq; -	int phy_init_sz; -	void (*vbus_power)(bool on); -	unsigned power_budget; -	enum usb_dr_mode mode; -	enum otg_control_type otg_control; -	enum msm_usb_phy_type phy_type; -	void (*setup_gpio)(enum usb_otg_state state); -}; - -/** - * struct msm_otg: OTG driver data. Shared by HCD and DCD. - * @otg: USB OTG Transceiver structure. - * @pdata: otg device platform data. - * @irq: IRQ number assigned for HSUSB controller. - * @clk: clock struct of usb_hs_clk. - * @pclk: clock struct of usb_hs_pclk. - * @core_clk: clock struct of usb_hs_core_clk. - * @regs: ioremapped register base address. - * @inputs: OTG state machine inputs(Id, SessValid etc). - * @sm_work: OTG state machine work. - * @in_lpm: indicates low power mode (LPM) state. - * @async_int: Async interrupt arrived. - * @cur_power: The amount of mA available from downstream port. - * @chg_work: Charger detection work. - * @chg_state: The state of charger detection process. - * @chg_type: The type of charger attached. - * @dcd_retires: The retry count used to track Data contact - *               detection process. - * @manual_pullup: true if VBUS is not routed to USB controller/phy - *	and controller driver therefore enables pull-up explicitly before - *	starting controller using usbcmd run/stop bit. - * @vbus: VBUS signal state trakining, using extcon framework - * @id: ID signal state trakining, using extcon framework - * @switch_gpio: Descriptor for GPIO used to control external Dual - *               SPDT USB Switch. - * @reboot: Used to inform the driver to route USB D+/D- line to Device - *	    connector - */ -struct msm_otg { -	struct usb_phy phy; -	struct msm_otg_platform_data *pdata; -	int irq; -	struct clk *clk; -	struct clk *pclk; -	struct clk *core_clk; -	void __iomem *regs; -#define ID		0 -#define B_SESS_VLD	1 -	unsigned long inputs; -	struct work_struct sm_work; -	atomic_t in_lpm; -	int async_int; -	unsigned cur_power; -	int phy_number; -	struct delayed_work chg_work; -	enum usb_chg_state chg_state; -	enum usb_chg_type chg_type; -	u8 dcd_retries; -	struct regulator *v3p3; -	struct regulator *v1p8; -	struct regulator *vddcx; -	struct regulator_bulk_data supplies[3]; - -	struct reset_control *phy_rst; -	struct reset_control *link_rst; -	int vdd_levels[3]; - -	bool manual_pullup; - -	struct gpio_desc *switch_gpio; -	struct notifier_block reboot; -}; - -#define MSM_USB_BASE	(motg->regs) -#define DRIVER_NAME	"msm_otg" - -#define ULPI_IO_TIMEOUT_USEC	(10 * 1000) -#define LINK_RESET_TIMEOUT_USEC	(250 * 1000) - -#define USB_PHY_3P3_VOL_MIN	3050000 /* uV */ -#define USB_PHY_3P3_VOL_MAX	3300000 /* uV */ -#define USB_PHY_3P3_HPM_LOAD	50000	/* uA */ -#define USB_PHY_3P3_LPM_LOAD	4000	/* uA */ - -#define USB_PHY_1P8_VOL_MIN	1800000 /* uV */ -#define USB_PHY_1P8_VOL_MAX	1800000 /* uV */ -#define USB_PHY_1P8_HPM_LOAD	50000	/* uA */ -#define USB_PHY_1P8_LPM_LOAD	4000	/* uA */ - -#define USB_PHY_VDD_DIG_VOL_MIN	1000000 /* uV */ -#define USB_PHY_VDD_DIG_VOL_MAX	1320000 /* uV */ -#define USB_PHY_SUSP_DIG_VOL	500000  /* uV */ - -enum vdd_levels { -	VDD_LEVEL_NONE = 0, -	VDD_LEVEL_MIN, -	VDD_LEVEL_MAX, -}; - -static int msm_hsusb_init_vddcx(struct msm_otg *motg, int init) -{ -	int ret = 0; - -	if (init) { -		ret = regulator_set_voltage(motg->vddcx, -				motg->vdd_levels[VDD_LEVEL_MIN], -				motg->vdd_levels[VDD_LEVEL_MAX]); -		if (ret) { -			dev_err(motg->phy.dev, "Cannot set vddcx voltage\n"); -			return ret; -		} - -		ret = regulator_enable(motg->vddcx); -		if (ret) -			dev_err(motg->phy.dev, "unable to enable hsusb vddcx\n"); -	} else { -		ret = regulator_set_voltage(motg->vddcx, 0, -				motg->vdd_levels[VDD_LEVEL_MAX]); -		if (ret) -			dev_err(motg->phy.dev, "Cannot set vddcx voltage\n"); -		ret = regulator_disable(motg->vddcx); -		if (ret) -			dev_err(motg->phy.dev, "unable to disable hsusb vddcx\n"); -	} - -	return ret; -} - -static int msm_hsusb_ldo_init(struct msm_otg *motg, int init) -{ -	int rc = 0; - -	if (init) { -		rc = regulator_set_voltage(motg->v3p3, USB_PHY_3P3_VOL_MIN, -				USB_PHY_3P3_VOL_MAX); -		if (rc) { -			dev_err(motg->phy.dev, "Cannot set v3p3 voltage\n"); -			goto exit; -		} -		rc = regulator_enable(motg->v3p3); -		if (rc) { -			dev_err(motg->phy.dev, "unable to enable the hsusb 3p3\n"); -			goto exit; -		} -		rc = regulator_set_voltage(motg->v1p8, USB_PHY_1P8_VOL_MIN, -				USB_PHY_1P8_VOL_MAX); -		if (rc) { -			dev_err(motg->phy.dev, "Cannot set v1p8 voltage\n"); -			goto disable_3p3; -		} -		rc = regulator_enable(motg->v1p8); -		if (rc) { -			dev_err(motg->phy.dev, "unable to enable the hsusb 1p8\n"); -			goto disable_3p3; -		} - -		return 0; -	} - -	regulator_disable(motg->v1p8); -disable_3p3: -	regulator_disable(motg->v3p3); -exit: -	return rc; -} - -static int msm_hsusb_ldo_set_mode(struct msm_otg *motg, int on) -{ -	int ret = 0; - -	if (on) { -		ret = regulator_set_load(motg->v1p8, USB_PHY_1P8_HPM_LOAD); -		if (ret < 0) { -			pr_err("Could not set HPM for v1p8\n"); -			return ret; -		} -		ret = regulator_set_load(motg->v3p3, USB_PHY_3P3_HPM_LOAD); -		if (ret < 0) { -			pr_err("Could not set HPM for v3p3\n"); -			regulator_set_load(motg->v1p8, USB_PHY_1P8_LPM_LOAD); -			return ret; -		} -	} else { -		ret = regulator_set_load(motg->v1p8, USB_PHY_1P8_LPM_LOAD); -		if (ret < 0) -			pr_err("Could not set LPM for v1p8\n"); -		ret = regulator_set_load(motg->v3p3, USB_PHY_3P3_LPM_LOAD); -		if (ret < 0) -			pr_err("Could not set LPM for v3p3\n"); -	} - -	pr_debug("reg (%s)\n", on ? "HPM" : "LPM"); -	return ret < 0 ? ret : 0; -} - -static int ulpi_read(struct usb_phy *phy, u32 reg) -{ -	struct msm_otg *motg = container_of(phy, struct msm_otg, phy); -	int cnt = 0; - -	/* initiate read operation */ -	writel(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg), -	       USB_ULPI_VIEWPORT); - -	/* wait for completion */ -	while (cnt < ULPI_IO_TIMEOUT_USEC) { -		if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN)) -			break; -		udelay(1); -		cnt++; -	} - -	if (cnt >= ULPI_IO_TIMEOUT_USEC) { -		dev_err(phy->dev, "ulpi_read: timeout %08x\n", -			readl(USB_ULPI_VIEWPORT)); -		return -ETIMEDOUT; -	} -	return ULPI_DATA_READ(readl(USB_ULPI_VIEWPORT)); -} - -static int ulpi_write(struct usb_phy *phy, u32 val, u32 reg) -{ -	struct msm_otg *motg = container_of(phy, struct msm_otg, phy); -	int cnt = 0; - -	/* initiate write operation */ -	writel(ULPI_RUN | ULPI_WRITE | -	       ULPI_ADDR(reg) | ULPI_DATA(val), -	       USB_ULPI_VIEWPORT); - -	/* wait for completion */ -	while (cnt < ULPI_IO_TIMEOUT_USEC) { -		if (!(readl(USB_ULPI_VIEWPORT) & ULPI_RUN)) -			break; -		udelay(1); -		cnt++; -	} - -	if (cnt >= ULPI_IO_TIMEOUT_USEC) { -		dev_err(phy->dev, "ulpi_write: timeout\n"); -		return -ETIMEDOUT; -	} -	return 0; -} - -static struct usb_phy_io_ops msm_otg_io_ops = { -	.read = ulpi_read, -	.write = ulpi_write, -}; - -static void ulpi_init(struct msm_otg *motg) -{ -	struct msm_otg_platform_data *pdata = motg->pdata; -	int *seq = pdata->phy_init_seq, idx; -	u32 addr = ULPI_EXT_VENDOR_SPECIFIC; - -	for (idx = 0; idx < pdata->phy_init_sz; idx++) { -		if (seq[idx] == -1) -			continue; - -		dev_vdbg(motg->phy.dev, "ulpi: write 0x%02x to 0x%02x\n", -				seq[idx], addr + idx); -		ulpi_write(&motg->phy, seq[idx], addr + idx); -	} -} - -static int msm_phy_notify_disconnect(struct usb_phy *phy, -				   enum usb_device_speed speed) -{ -	struct msm_otg *motg = container_of(phy, struct msm_otg, phy); -	int val; - -	if (motg->manual_pullup) { -		val = ULPI_MISC_A_VBUSVLDEXT | ULPI_MISC_A_VBUSVLDEXTSEL; -		usb_phy_io_write(phy, val, ULPI_CLR(ULPI_MISC_A)); -	} - -	/* -	 * Put the transceiver in non-driving mode. Otherwise host -	 * may not detect soft-disconnection. -	 */ -	val = ulpi_read(phy, ULPI_FUNC_CTRL); -	val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; -	val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; -	ulpi_write(phy, val, ULPI_FUNC_CTRL); - -	return 0; -} - -static int msm_otg_link_clk_reset(struct msm_otg *motg, bool assert) -{ -	int ret; - -	if (assert) -		ret = reset_control_assert(motg->link_rst); -	else -		ret = reset_control_deassert(motg->link_rst); - -	if (ret) -		dev_err(motg->phy.dev, "usb link clk reset %s failed\n", -			assert ? "assert" : "deassert"); - -	return ret; -} - -static int msm_otg_phy_clk_reset(struct msm_otg *motg) -{ -	int ret = 0; - -	if (motg->phy_rst) -		ret = reset_control_reset(motg->phy_rst); - -	if (ret) -		dev_err(motg->phy.dev, "usb phy clk reset failed\n"); - -	return ret; -} - -static int msm_link_reset(struct msm_otg *motg) -{ -	u32 val; -	int ret; - -	ret = msm_otg_link_clk_reset(motg, 1); -	if (ret) -		return ret; - -	/* wait for 1ms delay as suggested in HPG. */ -	usleep_range(1000, 1200); - -	ret = msm_otg_link_clk_reset(motg, 0); -	if (ret) -		return ret; - -	if (motg->phy_number) -		writel(readl(USB_PHY_CTRL2) | BIT(16), USB_PHY_CTRL2); - -	/* put transceiver in serial mode as part of reset */ -	val = readl(USB_PORTSC) & ~PORTSC_PTS_MASK; -	writel(val | PORTSC_PTS_SERIAL, USB_PORTSC); - -	return 0; -} - -static int msm_otg_reset(struct usb_phy *phy) -{ -	struct msm_otg *motg = container_of(phy, struct msm_otg, phy); -	int cnt = 0; - -	writel(USBCMD_RESET, USB_USBCMD); -	while (cnt < LINK_RESET_TIMEOUT_USEC) { -		if (!(readl(USB_USBCMD) & USBCMD_RESET)) -			break; -		udelay(1); -		cnt++; -	} -	if (cnt >= LINK_RESET_TIMEOUT_USEC) -		return -ETIMEDOUT; - -	/* select ULPI phy and clear other status/control bits in PORTSC */ -	writel(PORTSC_PTS_ULPI, USB_PORTSC); - -	writel(0x0, USB_AHBBURST); -	writel(0x08, USB_AHBMODE); - -	if (motg->phy_number) -		writel(readl(USB_PHY_CTRL2) | BIT(16), USB_PHY_CTRL2); -	return 0; -} - -static void msm_phy_reset(struct msm_otg *motg) -{ -	void __iomem *addr; - -	if (motg->pdata->phy_type != SNPS_28NM_INTEGRATED_PHY) { -		msm_otg_phy_clk_reset(motg); -		return; -	} - -	addr = USB_PHY_CTRL; -	if (motg->phy_number) -		addr = USB_PHY_CTRL2; - -	/* Assert USB PHY_POR */ -	writel(readl(addr) | PHY_POR_ASSERT, addr); - -	/* -	 * wait for minimum 10 microseconds as suggested in HPG. -	 * Use a slightly larger value since the exact value didn't -	 * work 100% of the time. -	 */ -	udelay(12); - -	/* Deassert USB PHY_POR */ -	writel(readl(addr) & ~PHY_POR_ASSERT, addr); -} - -static int msm_usb_reset(struct usb_phy *phy) -{ -	struct msm_otg *motg = container_of(phy, struct msm_otg, phy); -	int ret; - -	if (!IS_ERR(motg->core_clk)) -		clk_prepare_enable(motg->core_clk); - -	ret = msm_link_reset(motg); -	if (ret) { -		dev_err(phy->dev, "phy_reset failed\n"); -		return ret; -	} - -	ret = msm_otg_reset(&motg->phy); -	if (ret) { -		dev_err(phy->dev, "link reset failed\n"); -		return ret; -	} - -	msleep(100); - -	/* Reset USB PHY after performing USB Link RESET */ -	msm_phy_reset(motg); - -	if (!IS_ERR(motg->core_clk)) -		clk_disable_unprepare(motg->core_clk); - -	return 0; -} - -static int msm_phy_init(struct usb_phy *phy) -{ -	struct msm_otg *motg = container_of(phy, struct msm_otg, phy); -	struct msm_otg_platform_data *pdata = motg->pdata; -	u32 val, ulpi_val = 0; - -	/* Program USB PHY Override registers. */ -	ulpi_init(motg); - -	/* -	 * It is recommended in HPG to reset USB PHY after programming -	 * USB PHY Override registers. -	 */ -	msm_phy_reset(motg); - -	if (pdata->otg_control == OTG_PHY_CONTROL) { -		val = readl(USB_OTGSC); -		if (pdata->mode == USB_DR_MODE_OTG) { -			ulpi_val = ULPI_INT_IDGRD | ULPI_INT_SESS_VALID; -			val |= OTGSC_IDIE | OTGSC_BSVIE; -		} else if (pdata->mode == USB_DR_MODE_PERIPHERAL) { -			ulpi_val = ULPI_INT_SESS_VALID; -			val |= OTGSC_BSVIE; -		} -		writel(val, USB_OTGSC); -		ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_RISE); -		ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_FALL); -	} - -	if (motg->manual_pullup) { -		val = ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT; -		ulpi_write(phy, val, ULPI_SET(ULPI_MISC_A)); - -		val = readl(USB_GENCONFIG_2); -		val |= GENCONFIG_2_SESS_VLD_CTRL_EN; -		writel(val, USB_GENCONFIG_2); - -		val = readl(USB_USBCMD); -		val |= USBCMD_SESS_VLD_CTRL; -		writel(val, USB_USBCMD); - -		val = ulpi_read(phy, ULPI_FUNC_CTRL); -		val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; -		val |= ULPI_FUNC_CTRL_OPMODE_NORMAL; -		ulpi_write(phy, val, ULPI_FUNC_CTRL); -	} - -	if (motg->phy_number) -		writel(readl(USB_PHY_CTRL2) | BIT(16), USB_PHY_CTRL2); - -	return 0; -} - -#define PHY_SUSPEND_TIMEOUT_USEC	(500 * 1000) -#define PHY_RESUME_TIMEOUT_USEC	(100 * 1000) - -#ifdef CONFIG_PM - -static int msm_hsusb_config_vddcx(struct msm_otg *motg, int high) -{ -	int max_vol = motg->vdd_levels[VDD_LEVEL_MAX]; -	int min_vol; -	int ret; - -	if (high) -		min_vol = motg->vdd_levels[VDD_LEVEL_MIN]; -	else -		min_vol = motg->vdd_levels[VDD_LEVEL_NONE]; - -	ret = regulator_set_voltage(motg->vddcx, min_vol, max_vol); -	if (ret) { -		pr_err("Cannot set vddcx voltage\n"); -		return ret; -	} - -	pr_debug("%s: min_vol:%d max_vol:%d\n", __func__, min_vol, max_vol); - -	return ret; -} - -static int msm_otg_suspend(struct msm_otg *motg) -{ -	struct usb_phy *phy = &motg->phy; -	struct usb_bus *bus = phy->otg->host; -	struct msm_otg_platform_data *pdata = motg->pdata; -	void __iomem *addr; -	int cnt = 0; - -	if (atomic_read(&motg->in_lpm)) -		return 0; - -	disable_irq(motg->irq); -	/* -	 * Chipidea 45-nm PHY suspend sequence: -	 * -	 * Interrupt Latch Register auto-clear feature is not present -	 * in all PHY versions. Latch register is clear on read type. -	 * Clear latch register to avoid spurious wakeup from -	 * low power mode (LPM). -	 * -	 * PHY comparators are disabled when PHY enters into low power -	 * mode (LPM). Keep PHY comparators ON in LPM only when we expect -	 * VBUS/Id notifications from USB PHY. Otherwise turn off USB -	 * PHY comparators. This save significant amount of power. -	 * -	 * PLL is not turned off when PHY enters into low power mode (LPM). -	 * Disable PLL for maximum power savings. -	 */ - -	if (motg->pdata->phy_type == CI_45NM_INTEGRATED_PHY) { -		ulpi_read(phy, 0x14); -		if (pdata->otg_control == OTG_PHY_CONTROL) -			ulpi_write(phy, 0x01, 0x30); -		ulpi_write(phy, 0x08, 0x09); -	} - -	/* -	 * PHY may take some time or even fail to enter into low power -	 * mode (LPM). Hence poll for 500 msec and reset the PHY and link -	 * in failure case. -	 */ -	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC); -	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) { -		if (readl(USB_PORTSC) & PORTSC_PHCD) -			break; -		udelay(1); -		cnt++; -	} - -	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) { -		dev_err(phy->dev, "Unable to suspend PHY\n"); -		msm_otg_reset(phy); -		enable_irq(motg->irq); -		return -ETIMEDOUT; -	} - -	/* -	 * PHY has capability to generate interrupt asynchronously in low -	 * power mode (LPM). This interrupt is level triggered. So USB IRQ -	 * line must be disabled till async interrupt enable bit is cleared -	 * in USBCMD register. Assert STP (ULPI interface STOP signal) to -	 * block data communication from PHY. -	 */ -	writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD); - -	addr = USB_PHY_CTRL; -	if (motg->phy_number) -		addr = USB_PHY_CTRL2; - -	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY && -			motg->pdata->otg_control == OTG_PMIC_CONTROL) -		writel(readl(addr) | PHY_RETEN, addr); - -	clk_disable_unprepare(motg->pclk); -	clk_disable_unprepare(motg->clk); -	if (!IS_ERR(motg->core_clk)) -		clk_disable_unprepare(motg->core_clk); - -	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY && -			motg->pdata->otg_control == OTG_PMIC_CONTROL) { -		msm_hsusb_ldo_set_mode(motg, 0); -		msm_hsusb_config_vddcx(motg, 0); -	} - -	if (device_may_wakeup(phy->dev)) -		enable_irq_wake(motg->irq); -	if (bus) -		clear_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags); - -	atomic_set(&motg->in_lpm, 1); -	enable_irq(motg->irq); - -	dev_info(phy->dev, "USB in low power mode\n"); - -	return 0; -} - -static int msm_otg_resume(struct msm_otg *motg) -{ -	struct usb_phy *phy = &motg->phy; -	struct usb_bus *bus = phy->otg->host; -	void __iomem *addr; -	int cnt = 0; -	unsigned temp; - -	if (!atomic_read(&motg->in_lpm)) -		return 0; - -	clk_prepare_enable(motg->pclk); -	clk_prepare_enable(motg->clk); -	if (!IS_ERR(motg->core_clk)) -		clk_prepare_enable(motg->core_clk); - -	if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY && -			motg->pdata->otg_control == OTG_PMIC_CONTROL) { - -		addr = USB_PHY_CTRL; -		if (motg->phy_number) -			addr = USB_PHY_CTRL2; - -		msm_hsusb_ldo_set_mode(motg, 1); -		msm_hsusb_config_vddcx(motg, 1); -		writel(readl(addr) & ~PHY_RETEN, addr); -	} - -	temp = readl(USB_USBCMD); -	temp &= ~ASYNC_INTR_CTRL; -	temp &= ~ULPI_STP_CTRL; -	writel(temp, USB_USBCMD); - -	/* -	 * PHY comes out of low power mode (LPM) in case of wakeup -	 * from asynchronous interrupt. -	 */ -	if (!(readl(USB_PORTSC) & PORTSC_PHCD)) -		goto skip_phy_resume; - -	writel(readl(USB_PORTSC) & ~PORTSC_PHCD, USB_PORTSC); -	while (cnt < PHY_RESUME_TIMEOUT_USEC) { -		if (!(readl(USB_PORTSC) & PORTSC_PHCD)) -			break; -		udelay(1); -		cnt++; -	} - -	if (cnt >= PHY_RESUME_TIMEOUT_USEC) { -		/* -		 * This is a fatal error. Reset the link and -		 * PHY. USB state can not be restored. Re-insertion -		 * of USB cable is the only way to get USB working. -		 */ -		dev_err(phy->dev, "Unable to resume USB. Re-plugin the cable\n"); -		msm_otg_reset(phy); -	} - -skip_phy_resume: -	if (device_may_wakeup(phy->dev)) -		disable_irq_wake(motg->irq); -	if (bus) -		set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags); - -	atomic_set(&motg->in_lpm, 0); - -	if (motg->async_int) { -		motg->async_int = 0; -		pm_runtime_put(phy->dev); -		enable_irq(motg->irq); -	} - -	dev_info(phy->dev, "USB exited from low power mode\n"); - -	return 0; -} -#endif - -static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA) -{ -	if (motg->cur_power == mA) -		return; - -	/* TODO: Notify PMIC about available current */ -	dev_info(motg->phy.dev, "Avail curr from USB = %u\n", mA); -	motg->cur_power = mA; -} - -static void msm_otg_start_host(struct usb_phy *phy, int on) -{ -	struct msm_otg *motg = container_of(phy, struct msm_otg, phy); -	struct msm_otg_platform_data *pdata = motg->pdata; -	struct usb_hcd *hcd; - -	if (!phy->otg->host) -		return; - -	hcd = bus_to_hcd(phy->otg->host); - -	if (on) { -		dev_dbg(phy->dev, "host on\n"); - -		if (pdata->vbus_power) -			pdata->vbus_power(1); -		/* -		 * Some boards have a switch cotrolled by gpio -		 * to enable/disable internal HUB. Enable internal -		 * HUB before kicking the host. -		 */ -		if (pdata->setup_gpio) -			pdata->setup_gpio(OTG_STATE_A_HOST); -#ifdef CONFIG_USB -		usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); -		device_wakeup_enable(hcd->self.controller); -#endif -	} else { -		dev_dbg(phy->dev, "host off\n"); - -#ifdef CONFIG_USB -		usb_remove_hcd(hcd); -#endif -		if (pdata->setup_gpio) -			pdata->setup_gpio(OTG_STATE_UNDEFINED); -		if (pdata->vbus_power) -			pdata->vbus_power(0); -	} -} - -static int msm_otg_set_host(struct usb_otg *otg, struct usb_bus *host) -{ -	struct msm_otg *motg = container_of(otg->usb_phy, struct msm_otg, phy); -	struct usb_hcd *hcd; - -	/* -	 * Fail host registration if this board can support -	 * only peripheral configuration. -	 */ -	if (motg->pdata->mode == USB_DR_MODE_PERIPHERAL) { -		dev_info(otg->usb_phy->dev, "Host mode is not supported\n"); -		return -ENODEV; -	} - -	if (!host) { -		if (otg->state == OTG_STATE_A_HOST) { -			pm_runtime_get_sync(otg->usb_phy->dev); -			msm_otg_start_host(otg->usb_phy, 0); -			otg->host = NULL; -			otg->state = OTG_STATE_UNDEFINED; -			schedule_work(&motg->sm_work); -		} else { -			otg->host = NULL; -		} - -		return 0; -	} - -	hcd = bus_to_hcd(host); -	hcd->power_budget = motg->pdata->power_budget; - -	otg->host = host; -	dev_dbg(otg->usb_phy->dev, "host driver registered w/ tranceiver\n"); - -	pm_runtime_get_sync(otg->usb_phy->dev); -	schedule_work(&motg->sm_work); - -	return 0; -} - -static void msm_otg_start_peripheral(struct usb_phy *phy, int on) -{ -	struct msm_otg *motg = container_of(phy, struct msm_otg, phy); -	struct msm_otg_platform_data *pdata = motg->pdata; - -	if (!phy->otg->gadget) -		return; - -	if (on) { -		dev_dbg(phy->dev, "gadget on\n"); -		/* -		 * Some boards have a switch cotrolled by gpio -		 * to enable/disable internal HUB. Disable internal -		 * HUB before kicking the gadget. -		 */ -		if (pdata->setup_gpio) -			pdata->setup_gpio(OTG_STATE_B_PERIPHERAL); -		usb_gadget_vbus_connect(phy->otg->gadget); -	} else { -		dev_dbg(phy->dev, "gadget off\n"); -		usb_gadget_vbus_disconnect(phy->otg->gadget); -		if (pdata->setup_gpio) -			pdata->setup_gpio(OTG_STATE_UNDEFINED); -	} - -} - -static int msm_otg_set_peripheral(struct usb_otg *otg, -					struct usb_gadget *gadget) -{ -	struct msm_otg *motg = container_of(otg->usb_phy, struct msm_otg, phy); - -	/* -	 * Fail peripheral registration if this board can support -	 * only host configuration. -	 */ -	if (motg->pdata->mode == USB_DR_MODE_HOST) { -		dev_info(otg->usb_phy->dev, "Peripheral mode is not supported\n"); -		return -ENODEV; -	} - -	if (!gadget) { -		if (otg->state == OTG_STATE_B_PERIPHERAL) { -			pm_runtime_get_sync(otg->usb_phy->dev); -			msm_otg_start_peripheral(otg->usb_phy, 0); -			otg->gadget = NULL; -			otg->state = OTG_STATE_UNDEFINED; -			schedule_work(&motg->sm_work); -		} else { -			otg->gadget = NULL; -		} - -		return 0; -	} -	otg->gadget = gadget; -	dev_dbg(otg->usb_phy->dev, -		"peripheral driver registered w/ tranceiver\n"); - -	pm_runtime_get_sync(otg->usb_phy->dev); -	schedule_work(&motg->sm_work); - -	return 0; -} - -static bool msm_chg_check_secondary_det(struct msm_otg *motg) -{ -	struct usb_phy *phy = &motg->phy; -	u32 chg_det; -	bool ret = false; - -	switch (motg->pdata->phy_type) { -	case CI_45NM_INTEGRATED_PHY: -		chg_det = ulpi_read(phy, 0x34); -		ret = chg_det & (1 << 4); -		break; -	case SNPS_28NM_INTEGRATED_PHY: -		chg_det = ulpi_read(phy, 0x87); -		ret = chg_det & 1; -		break; -	default: -		break; -	} -	return ret; -} - -static void msm_chg_enable_secondary_det(struct msm_otg *motg) -{ -	struct usb_phy *phy = &motg->phy; -	u32 chg_det; - -	switch (motg->pdata->phy_type) { -	case CI_45NM_INTEGRATED_PHY: -		chg_det = ulpi_read(phy, 0x34); -		/* Turn off charger block */ -		chg_det |= ~(1 << 1); -		ulpi_write(phy, chg_det, 0x34); -		udelay(20); -		/* control chg block via ULPI */ -		chg_det &= ~(1 << 3); -		ulpi_write(phy, chg_det, 0x34); -		/* put it in host mode for enabling D- source */ -		chg_det &= ~(1 << 2); -		ulpi_write(phy, chg_det, 0x34); -		/* Turn on chg detect block */ -		chg_det &= ~(1 << 1); -		ulpi_write(phy, chg_det, 0x34); -		udelay(20); -		/* enable chg detection */ -		chg_det &= ~(1 << 0); -		ulpi_write(phy, chg_det, 0x34); -		break; -	case SNPS_28NM_INTEGRATED_PHY: -		/* -		 * Configure DM as current source, DP as current sink -		 * and enable battery charging comparators. -		 */ -		ulpi_write(phy, 0x8, 0x85); -		ulpi_write(phy, 0x2, 0x85); -		ulpi_write(phy, 0x1, 0x85); -		break; -	default: -		break; -	} -} - -static bool msm_chg_check_primary_det(struct msm_otg *motg) -{ -	struct usb_phy *phy = &motg->phy; -	u32 chg_det; -	bool ret = false; - -	switch (motg->pdata->phy_type) { -	case CI_45NM_INTEGRATED_PHY: -		chg_det = ulpi_read(phy, 0x34); -		ret = chg_det & (1 << 4); -		break; -	case SNPS_28NM_INTEGRATED_PHY: -		chg_det = ulpi_read(phy, 0x87); -		ret = chg_det & 1; -		break; -	default: -		break; -	} -	return ret; -} - -static void msm_chg_enable_primary_det(struct msm_otg *motg) -{ -	struct usb_phy *phy = &motg->phy; -	u32 chg_det; - -	switch (motg->pdata->phy_type) { -	case CI_45NM_INTEGRATED_PHY: -		chg_det = ulpi_read(phy, 0x34); -		/* enable chg detection */ -		chg_det &= ~(1 << 0); -		ulpi_write(phy, chg_det, 0x34); -		break; -	case SNPS_28NM_INTEGRATED_PHY: -		/* -		 * Configure DP as current source, DM as current sink -		 * and enable battery charging comparators. -		 */ -		ulpi_write(phy, 0x2, 0x85); -		ulpi_write(phy, 0x1, 0x85); -		break; -	default: -		break; -	} -} - -static bool msm_chg_check_dcd(struct msm_otg *motg) -{ -	struct usb_phy *phy = &motg->phy; -	u32 line_state; -	bool ret = false; - -	switch (motg->pdata->phy_type) { -	case CI_45NM_INTEGRATED_PHY: -		line_state = ulpi_read(phy, 0x15); -		ret = !(line_state & 1); -		break; -	case SNPS_28NM_INTEGRATED_PHY: -		line_state = ulpi_read(phy, 0x87); -		ret = line_state & 2; -		break; -	default: -		break; -	} -	return ret; -} - -static void msm_chg_disable_dcd(struct msm_otg *motg) -{ -	struct usb_phy *phy = &motg->phy; -	u32 chg_det; - -	switch (motg->pdata->phy_type) { -	case CI_45NM_INTEGRATED_PHY: -		chg_det = ulpi_read(phy, 0x34); -		chg_det &= ~(1 << 5); -		ulpi_write(phy, chg_det, 0x34); -		break; -	case SNPS_28NM_INTEGRATED_PHY: -		ulpi_write(phy, 0x10, 0x86); -		break; -	default: -		break; -	} -} - -static void msm_chg_enable_dcd(struct msm_otg *motg) -{ -	struct usb_phy *phy = &motg->phy; -	u32 chg_det; - -	switch (motg->pdata->phy_type) { -	case CI_45NM_INTEGRATED_PHY: -		chg_det = ulpi_read(phy, 0x34); -		/* Turn on D+ current source */ -		chg_det |= (1 << 5); -		ulpi_write(phy, chg_det, 0x34); -		break; -	case SNPS_28NM_INTEGRATED_PHY: -		/* Data contact detection enable */ -		ulpi_write(phy, 0x10, 0x85); -		break; -	default: -		break; -	} -} - -static void msm_chg_block_on(struct msm_otg *motg) -{ -	struct usb_phy *phy = &motg->phy; -	u32 func_ctrl, chg_det; - -	/* put the controller in non-driving mode */ -	func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL); -	func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK; -	func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; -	ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL); - -	switch (motg->pdata->phy_type) { -	case CI_45NM_INTEGRATED_PHY: -		chg_det = ulpi_read(phy, 0x34); -		/* control chg block via ULPI */ -		chg_det &= ~(1 << 3); -		ulpi_write(phy, chg_det, 0x34); -		/* Turn on chg detect block */ -		chg_det &= ~(1 << 1); -		ulpi_write(phy, chg_det, 0x34); -		udelay(20); -		break; -	case SNPS_28NM_INTEGRATED_PHY: -		/* Clear charger detecting control bits */ -		ulpi_write(phy, 0x3F, 0x86); -		/* Clear alt interrupt latch and enable bits */ -		ulpi_write(phy, 0x1F, 0x92); -		ulpi_write(phy, 0x1F, 0x95); -		udelay(100); -		break; -	default: -		break; -	} -} - -static void msm_chg_block_off(struct msm_otg *motg) -{ -	struct usb_phy *phy = &motg->phy; -	u32 func_ctrl, chg_det; - -	switch (motg->pdata->phy_type) { -	case CI_45NM_INTEGRATED_PHY: -		chg_det = ulpi_read(phy, 0x34); -		/* Turn off charger block */ -		chg_det |= ~(1 << 1); -		ulpi_write(phy, chg_det, 0x34); -		break; -	case SNPS_28NM_INTEGRATED_PHY: -		/* Clear charger detecting control bits */ -		ulpi_write(phy, 0x3F, 0x86); -		/* Clear alt interrupt latch and enable bits */ -		ulpi_write(phy, 0x1F, 0x92); -		ulpi_write(phy, 0x1F, 0x95); -		break; -	default: -		break; -	} - -	/* put the controller in normal mode */ -	func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL); -	func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK; -	func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL; -	ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL); -} - -#define MSM_CHG_DCD_POLL_TIME		(100 * HZ/1000) /* 100 msec */ -#define MSM_CHG_DCD_MAX_RETRIES		6 /* Tdcd_tmout = 6 * 100 msec */ -#define MSM_CHG_PRIMARY_DET_TIME	(40 * HZ/1000) /* TVDPSRC_ON */ -#define MSM_CHG_SECONDARY_DET_TIME	(40 * HZ/1000) /* TVDMSRC_ON */ -static void msm_chg_detect_work(struct work_struct *w) -{ -	struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work); -	struct usb_phy *phy = &motg->phy; -	bool is_dcd, tmout, vout; -	unsigned long delay; - -	dev_dbg(phy->dev, "chg detection work\n"); -	switch (motg->chg_state) { -	case USB_CHG_STATE_UNDEFINED: -		pm_runtime_get_sync(phy->dev); -		msm_chg_block_on(motg); -		msm_chg_enable_dcd(motg); -		motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD; -		motg->dcd_retries = 0; -		delay = MSM_CHG_DCD_POLL_TIME; -		break; -	case USB_CHG_STATE_WAIT_FOR_DCD: -		is_dcd = msm_chg_check_dcd(motg); -		tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES; -		if (is_dcd || tmout) { -			msm_chg_disable_dcd(motg); -			msm_chg_enable_primary_det(motg); -			delay = MSM_CHG_PRIMARY_DET_TIME; -			motg->chg_state = USB_CHG_STATE_DCD_DONE; -		} else { -			delay = MSM_CHG_DCD_POLL_TIME; -		} -		break; -	case USB_CHG_STATE_DCD_DONE: -		vout = msm_chg_check_primary_det(motg); -		if (vout) { -			msm_chg_enable_secondary_det(motg); -			delay = MSM_CHG_SECONDARY_DET_TIME; -			motg->chg_state = USB_CHG_STATE_PRIMARY_DONE; -		} else { -			motg->chg_type = USB_SDP_CHARGER; -			motg->chg_state = USB_CHG_STATE_DETECTED; -			delay = 0; -		} -		break; -	case USB_CHG_STATE_PRIMARY_DONE: -		vout = msm_chg_check_secondary_det(motg); -		if (vout) -			motg->chg_type = USB_DCP_CHARGER; -		else -			motg->chg_type = USB_CDP_CHARGER; -		motg->chg_state = USB_CHG_STATE_SECONDARY_DONE; -		/* fall through */ -	case USB_CHG_STATE_SECONDARY_DONE: -		motg->chg_state = USB_CHG_STATE_DETECTED; -	case USB_CHG_STATE_DETECTED: -		msm_chg_block_off(motg); -		dev_dbg(phy->dev, "charger = %d\n", motg->chg_type); -		schedule_work(&motg->sm_work); -		return; -	default: -		return; -	} - -	schedule_delayed_work(&motg->chg_work, delay); -} - -/* - * We support OTG, Peripheral only and Host only configurations. In case - * of OTG, mode switch (host-->peripheral/peripheral-->host) can happen - * via Id pin status or user request (debugfs). Id/BSV interrupts are not - * enabled when switch is controlled by user and default mode is supplied - * by board file, which can be changed by userspace later. - */ -static void msm_otg_init_sm(struct msm_otg *motg) -{ -	struct msm_otg_platform_data *pdata = motg->pdata; -	u32 otgsc = readl(USB_OTGSC); - -	switch (pdata->mode) { -	case USB_DR_MODE_OTG: -		if (pdata->otg_control == OTG_PHY_CONTROL) { -			if (otgsc & OTGSC_ID) -				set_bit(ID, &motg->inputs); -			else -				clear_bit(ID, &motg->inputs); - -			if (otgsc & OTGSC_BSV) -				set_bit(B_SESS_VLD, &motg->inputs); -			else -				clear_bit(B_SESS_VLD, &motg->inputs); -		} else if (pdata->otg_control == OTG_USER_CONTROL) { -				set_bit(ID, &motg->inputs); -				clear_bit(B_SESS_VLD, &motg->inputs); -		} -		break; -	case USB_DR_MODE_HOST: -		clear_bit(ID, &motg->inputs); -		break; -	case USB_DR_MODE_PERIPHERAL: -		set_bit(ID, &motg->inputs); -		if (otgsc & OTGSC_BSV) -			set_bit(B_SESS_VLD, &motg->inputs); -		else -			clear_bit(B_SESS_VLD, &motg->inputs); -		break; -	default: -		break; -	} -} - -static void msm_otg_sm_work(struct work_struct *w) -{ -	struct msm_otg *motg = container_of(w, struct msm_otg, sm_work); -	struct usb_otg *otg = motg->phy.otg; - -	switch (otg->state) { -	case OTG_STATE_UNDEFINED: -		dev_dbg(otg->usb_phy->dev, "OTG_STATE_UNDEFINED state\n"); -		msm_otg_reset(otg->usb_phy); -		msm_otg_init_sm(motg); -		otg->state = OTG_STATE_B_IDLE; -		/* FALL THROUGH */ -	case OTG_STATE_B_IDLE: -		dev_dbg(otg->usb_phy->dev, "OTG_STATE_B_IDLE state\n"); -		if (!test_bit(ID, &motg->inputs) && otg->host) { -			/* disable BSV bit */ -			writel(readl(USB_OTGSC) & ~OTGSC_BSVIE, USB_OTGSC); -			msm_otg_start_host(otg->usb_phy, 1); -			otg->state = OTG_STATE_A_HOST; -		} else if (test_bit(B_SESS_VLD, &motg->inputs)) { -			switch (motg->chg_state) { -			case USB_CHG_STATE_UNDEFINED: -				msm_chg_detect_work(&motg->chg_work.work); -				break; -			case USB_CHG_STATE_DETECTED: -				switch (motg->chg_type) { -				case USB_DCP_CHARGER: -					msm_otg_notify_charger(motg, -							IDEV_CHG_MAX); -					break; -				case USB_CDP_CHARGER: -					msm_otg_notify_charger(motg, -							IDEV_CHG_MAX); -					msm_otg_start_peripheral(otg->usb_phy, -								 1); -					otg->state -						= OTG_STATE_B_PERIPHERAL; -					break; -				case USB_SDP_CHARGER: -					msm_otg_notify_charger(motg, IUNIT); -					msm_otg_start_peripheral(otg->usb_phy, -								 1); -					otg->state -						= OTG_STATE_B_PERIPHERAL; -					break; -				default: -					break; -				} -				break; -			default: -				break; -			} -		} else { -			/* -			 * If charger detection work is pending, decrement -			 * the pm usage counter to balance with the one that -			 * is incremented in charger detection work. -			 */ -			if (cancel_delayed_work_sync(&motg->chg_work)) { -				pm_runtime_put_sync(otg->usb_phy->dev); -				msm_otg_reset(otg->usb_phy); -			} -			msm_otg_notify_charger(motg, 0); -			motg->chg_state = USB_CHG_STATE_UNDEFINED; -			motg->chg_type = USB_INVALID_CHARGER; -		} - -		if (otg->state == OTG_STATE_B_IDLE) -			pm_runtime_put_sync(otg->usb_phy->dev); -		break; -	case OTG_STATE_B_PERIPHERAL: -		dev_dbg(otg->usb_phy->dev, "OTG_STATE_B_PERIPHERAL state\n"); -		if (!test_bit(B_SESS_VLD, &motg->inputs) || -				!test_bit(ID, &motg->inputs)) { -			msm_otg_notify_charger(motg, 0); -			msm_otg_start_peripheral(otg->usb_phy, 0); -			motg->chg_state = USB_CHG_STATE_UNDEFINED; -			motg->chg_type = USB_INVALID_CHARGER; -			otg->state = OTG_STATE_B_IDLE; -			msm_otg_reset(otg->usb_phy); -			schedule_work(w); -		} -		break; -	case OTG_STATE_A_HOST: -		dev_dbg(otg->usb_phy->dev, "OTG_STATE_A_HOST state\n"); -		if (test_bit(ID, &motg->inputs)) { -			msm_otg_start_host(otg->usb_phy, 0); -			otg->state = OTG_STATE_B_IDLE; -			msm_otg_reset(otg->usb_phy); -			schedule_work(w); -		} -		break; -	default: -		break; -	} -} - -static irqreturn_t msm_otg_irq(int irq, void *data) -{ -	struct msm_otg *motg = data; -	struct usb_phy *phy = &motg->phy; -	u32 otgsc = 0; - -	if (atomic_read(&motg->in_lpm)) { -		disable_irq_nosync(irq); -		motg->async_int = 1; -		pm_runtime_get(phy->dev); -		return IRQ_HANDLED; -	} - -	otgsc = readl(USB_OTGSC); -	if (!(otgsc & (OTGSC_IDIS | OTGSC_BSVIS))) -		return IRQ_NONE; - -	if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) { -		if (otgsc & OTGSC_ID) -			set_bit(ID, &motg->inputs); -		else -			clear_bit(ID, &motg->inputs); -		dev_dbg(phy->dev, "ID set/clear\n"); -		pm_runtime_get_noresume(phy->dev); -	} else if ((otgsc & OTGSC_BSVIS) && (otgsc & OTGSC_BSVIE)) { -		if (otgsc & OTGSC_BSV) -			set_bit(B_SESS_VLD, &motg->inputs); -		else -			clear_bit(B_SESS_VLD, &motg->inputs); -		dev_dbg(phy->dev, "BSV set/clear\n"); -		pm_runtime_get_noresume(phy->dev); -	} - -	writel(otgsc, USB_OTGSC); -	schedule_work(&motg->sm_work); -	return IRQ_HANDLED; -} - -static int msm_otg_mode_show(struct seq_file *s, void *unused) -{ -	struct msm_otg *motg = s->private; -	struct usb_otg *otg = motg->phy.otg; - -	switch (otg->state) { -	case OTG_STATE_A_HOST: -		seq_puts(s, "host\n"); -		break; -	case OTG_STATE_B_PERIPHERAL: -		seq_puts(s, "peripheral\n"); -		break; -	default: -		seq_puts(s, "none\n"); -		break; -	} - -	return 0; -} - -static int msm_otg_mode_open(struct inode *inode, struct file *file) -{ -	return single_open(file, msm_otg_mode_show, inode->i_private); -} - -static ssize_t msm_otg_mode_write(struct file *file, const char __user *ubuf, -				size_t count, loff_t *ppos) -{ -	struct seq_file *s = file->private_data; -	struct msm_otg *motg = s->private; -	char buf[16]; -	struct usb_otg *otg = motg->phy.otg; -	int status = count; -	enum usb_dr_mode req_mode; - -	memset(buf, 0x00, sizeof(buf)); - -	if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) { -		status = -EFAULT; -		goto out; -	} - -	if (!strncmp(buf, "host", 4)) { -		req_mode = USB_DR_MODE_HOST; -	} else if (!strncmp(buf, "peripheral", 10)) { -		req_mode = USB_DR_MODE_PERIPHERAL; -	} else if (!strncmp(buf, "none", 4)) { -		req_mode = USB_DR_MODE_UNKNOWN; -	} else { -		status = -EINVAL; -		goto out; -	} - -	switch (req_mode) { -	case USB_DR_MODE_UNKNOWN: -		switch (otg->state) { -		case OTG_STATE_A_HOST: -		case OTG_STATE_B_PERIPHERAL: -			set_bit(ID, &motg->inputs); -			clear_bit(B_SESS_VLD, &motg->inputs); -			break; -		default: -			goto out; -		} -		break; -	case USB_DR_MODE_PERIPHERAL: -		switch (otg->state) { -		case OTG_STATE_B_IDLE: -		case OTG_STATE_A_HOST: -			set_bit(ID, &motg->inputs); -			set_bit(B_SESS_VLD, &motg->inputs); -			break; -		default: -			goto out; -		} -		break; -	case USB_DR_MODE_HOST: -		switch (otg->state) { -		case OTG_STATE_B_IDLE: -		case OTG_STATE_B_PERIPHERAL: -			clear_bit(ID, &motg->inputs); -			break; -		default: -			goto out; -		} -		break; -	default: -		goto out; -	} - -	pm_runtime_get_sync(otg->usb_phy->dev); -	schedule_work(&motg->sm_work); -out: -	return status; -} - -static const struct file_operations msm_otg_mode_fops = { -	.open = msm_otg_mode_open, -	.read = seq_read, -	.write = msm_otg_mode_write, -	.llseek = seq_lseek, -	.release = single_release, -}; - -static struct dentry *msm_otg_dbg_root; -static struct dentry *msm_otg_dbg_mode; - -static int msm_otg_debugfs_init(struct msm_otg *motg) -{ -	msm_otg_dbg_root = debugfs_create_dir("msm_otg", NULL); - -	if (!msm_otg_dbg_root || IS_ERR(msm_otg_dbg_root)) -		return -ENODEV; - -	msm_otg_dbg_mode = debugfs_create_file("mode", S_IRUGO | S_IWUSR, -				msm_otg_dbg_root, motg, &msm_otg_mode_fops); -	if (!msm_otg_dbg_mode) { -		debugfs_remove(msm_otg_dbg_root); -		msm_otg_dbg_root = NULL; -		return -ENODEV; -	} - -	return 0; -} - -static void msm_otg_debugfs_cleanup(void) -{ -	debugfs_remove(msm_otg_dbg_mode); -	debugfs_remove(msm_otg_dbg_root); -} - -static const struct of_device_id msm_otg_dt_match[] = { -	{ -		.compatible = "qcom,usb-otg-ci", -		.data = (void *) CI_45NM_INTEGRATED_PHY -	}, -	{ -		.compatible = "qcom,usb-otg-snps", -		.data = (void *) SNPS_28NM_INTEGRATED_PHY -	}, -	{ } -}; -MODULE_DEVICE_TABLE(of, msm_otg_dt_match); - -static int msm_otg_vbus_notifier(struct notifier_block *nb, unsigned long event, -				void *ptr) -{ -	struct usb_phy *usb_phy = container_of(nb, struct usb_phy, vbus_nb); -	struct msm_otg *motg = container_of(usb_phy, struct msm_otg, phy); - -	if (event) -		set_bit(B_SESS_VLD, &motg->inputs); -	else -		clear_bit(B_SESS_VLD, &motg->inputs); - -	if (test_bit(B_SESS_VLD, &motg->inputs)) { -		/* Switch D+/D- lines to Device connector */ -		gpiod_set_value_cansleep(motg->switch_gpio, 0); -	} else { -		/* Switch D+/D- lines to Hub */ -		gpiod_set_value_cansleep(motg->switch_gpio, 1); -	} - -	schedule_work(&motg->sm_work); - -	return NOTIFY_DONE; -} - -static int msm_otg_id_notifier(struct notifier_block *nb, unsigned long event, -				void *ptr) -{ -	struct usb_phy *usb_phy = container_of(nb, struct usb_phy, id_nb); -	struct msm_otg *motg = container_of(usb_phy, struct msm_otg, phy); - -	if (event) -		clear_bit(ID, &motg->inputs); -	else -		set_bit(ID, &motg->inputs); - -	schedule_work(&motg->sm_work); - -	return NOTIFY_DONE; -} - -static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) -{ -	struct msm_otg_platform_data *pdata; -	struct device_node *node = pdev->dev.of_node; -	struct property *prop; -	int len, ret, words; -	u32 val, tmp[3]; - -	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); -	if (!pdata) -		return -ENOMEM; - -	motg->pdata = pdata; - -	pdata->phy_type = (enum msm_usb_phy_type)of_device_get_match_data(&pdev->dev); -	if (!pdata->phy_type) -		return 1; - -	motg->link_rst = devm_reset_control_get(&pdev->dev, "link"); -	if (IS_ERR(motg->link_rst)) -		return PTR_ERR(motg->link_rst); - -	motg->phy_rst = devm_reset_control_get(&pdev->dev, "phy"); -	if (IS_ERR(motg->phy_rst)) -		motg->phy_rst = NULL; - -	pdata->mode = usb_get_dr_mode(&pdev->dev); -	if (pdata->mode == USB_DR_MODE_UNKNOWN) -		pdata->mode = USB_DR_MODE_OTG; - -	pdata->otg_control = OTG_PHY_CONTROL; -	if (!of_property_read_u32(node, "qcom,otg-control", &val)) -		if (val == OTG_PMIC_CONTROL) -			pdata->otg_control = val; - -	if (!of_property_read_u32(node, "qcom,phy-num", &val) && val < 2) -		motg->phy_number = val; - -	motg->vdd_levels[VDD_LEVEL_NONE] = USB_PHY_SUSP_DIG_VOL; -	motg->vdd_levels[VDD_LEVEL_MIN] = USB_PHY_VDD_DIG_VOL_MIN; -	motg->vdd_levels[VDD_LEVEL_MAX] = USB_PHY_VDD_DIG_VOL_MAX; - -	if (of_get_property(node, "qcom,vdd-levels", &len) && -	    len == sizeof(tmp)) { -		of_property_read_u32_array(node, "qcom,vdd-levels", -					   tmp, len / sizeof(*tmp)); -		motg->vdd_levels[VDD_LEVEL_NONE] = tmp[VDD_LEVEL_NONE]; -		motg->vdd_levels[VDD_LEVEL_MIN] = tmp[VDD_LEVEL_MIN]; -		motg->vdd_levels[VDD_LEVEL_MAX] = tmp[VDD_LEVEL_MAX]; -	} - -	motg->manual_pullup = of_property_read_bool(node, "qcom,manual-pullup"); - -	motg->switch_gpio = devm_gpiod_get_optional(&pdev->dev, "switch", -						    GPIOD_OUT_LOW); -	if (IS_ERR(motg->switch_gpio)) -		return PTR_ERR(motg->switch_gpio); - -	prop = of_find_property(node, "qcom,phy-init-sequence", &len); -	if (!prop || !len) -		return 0; - -	words = len / sizeof(u32); - -	if (words >= ULPI_EXT_VENDOR_SPECIFIC) { -		dev_warn(&pdev->dev, "Too big PHY init sequence %d\n", words); -		return 0; -	} - -	pdata->phy_init_seq = devm_kzalloc(&pdev->dev, len, GFP_KERNEL); -	if (!pdata->phy_init_seq) -		return 0; - -	ret = of_property_read_u32_array(node, "qcom,phy-init-sequence", -					 pdata->phy_init_seq, words); -	if (!ret) -		pdata->phy_init_sz = words; - -	return 0; -} - -static int msm_otg_reboot_notify(struct notifier_block *this, -				 unsigned long code, void *unused) -{ -	struct msm_otg *motg = container_of(this, struct msm_otg, reboot); - -	/* -	 * Ensure that D+/D- lines are routed to uB connector, so -	 * we could load bootloader/kernel at next reboot -	 */ -	gpiod_set_value_cansleep(motg->switch_gpio, 0); -	return NOTIFY_DONE; -} - -static int msm_otg_probe(struct platform_device *pdev) -{ -	int ret = 0; -	struct device_node *np = pdev->dev.of_node; -	struct msm_otg_platform_data *pdata; -	struct resource *res; -	struct msm_otg *motg; -	struct usb_phy *phy; -	void __iomem *phy_select; - -	motg = devm_kzalloc(&pdev->dev, sizeof(struct msm_otg), GFP_KERNEL); -	if (!motg) -		return -ENOMEM; - -	motg->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), -				     GFP_KERNEL); -	if (!motg->phy.otg) -		return -ENOMEM; - -	phy = &motg->phy; -	phy->dev = &pdev->dev; - -	motg->clk = devm_clk_get(&pdev->dev, np ? "core" : "usb_hs_clk"); -	if (IS_ERR(motg->clk)) { -		dev_err(&pdev->dev, "failed to get usb_hs_clk\n"); -		return PTR_ERR(motg->clk); -	} - -	/* -	 * If USB Core is running its protocol engine based on CORE CLK, -	 * CORE CLK  must be running at >55Mhz for correct HSUSB -	 * operation and USB core cannot tolerate frequency changes on -	 * CORE CLK. -	 */ -	motg->pclk = devm_clk_get(&pdev->dev, np ? "iface" : "usb_hs_pclk"); -	if (IS_ERR(motg->pclk)) { -		dev_err(&pdev->dev, "failed to get usb_hs_pclk\n"); -		return PTR_ERR(motg->pclk); -	} - -	/* -	 * USB core clock is not present on all MSM chips. This -	 * clock is introduced to remove the dependency on AXI -	 * bus frequency. -	 */ -	motg->core_clk = devm_clk_get(&pdev->dev, -				      np ? "alt_core" : "usb_hs_core_clk"); - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) -		return -EINVAL; -	motg->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); -	if (!motg->regs) -		return -ENOMEM; - -	pdata = dev_get_platdata(&pdev->dev); -	if (!pdata) { -		if (!np) -			return -ENXIO; -		ret = msm_otg_read_dt(pdev, motg); -		if (ret) -			return ret; -	} - -	/* -	 * NOTE: The PHYs can be multiplexed between the chipidea controller -	 * and the dwc3 controller, using a single bit. It is important that -	 * the dwc3 driver does not set this bit in an incompatible way. -	 */ -	if (motg->phy_number) { -		phy_select = devm_ioremap_nocache(&pdev->dev, USB2_PHY_SEL, 4); -		if (!phy_select) -			return -ENOMEM; - -		/* Enable second PHY with the OTG port */ -		writel(0x1, phy_select); -	} - -	dev_info(&pdev->dev, "OTG regs = %p\n", motg->regs); - -	motg->irq = platform_get_irq(pdev, 0); -	if (motg->irq < 0) { -		dev_err(&pdev->dev, "platform_get_irq failed\n"); -		ret = motg->irq; -		return motg->irq; -	} - -	motg->supplies[0].supply = "vddcx"; -	motg->supplies[1].supply = "v3p3"; -	motg->supplies[2].supply = "v1p8"; - -	ret = devm_regulator_bulk_get(motg->phy.dev, ARRAY_SIZE(motg->supplies), -				      motg->supplies); -	if (ret) -		return ret; - -	motg->vddcx = motg->supplies[0].consumer; -	motg->v3p3  = motg->supplies[1].consumer; -	motg->v1p8  = motg->supplies[2].consumer; - -	clk_set_rate(motg->clk, 60000000); - -	clk_prepare_enable(motg->clk); -	clk_prepare_enable(motg->pclk); - -	if (!IS_ERR(motg->core_clk)) -		clk_prepare_enable(motg->core_clk); - -	ret = msm_hsusb_init_vddcx(motg, 1); -	if (ret) { -		dev_err(&pdev->dev, "hsusb vddcx configuration failed\n"); -		goto disable_clks; -	} - -	ret = msm_hsusb_ldo_init(motg, 1); -	if (ret) { -		dev_err(&pdev->dev, "hsusb vreg configuration failed\n"); -		goto disable_vddcx; -	} -	ret = msm_hsusb_ldo_set_mode(motg, 1); -	if (ret) { -		dev_err(&pdev->dev, "hsusb vreg enable failed\n"); -		goto disable_ldo; -	} - -	writel(0, USB_USBINTR); -	writel(0, USB_OTGSC); - -	INIT_WORK(&motg->sm_work, msm_otg_sm_work); -	INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work); -	ret = devm_request_irq(&pdev->dev, motg->irq, msm_otg_irq, IRQF_SHARED, -					"msm_otg", motg); -	if (ret) { -		dev_err(&pdev->dev, "request irq failed\n"); -		goto disable_ldo; -	} - -	phy->init = msm_phy_init; -	phy->notify_disconnect = msm_phy_notify_disconnect; -	phy->type = USB_PHY_TYPE_USB2; -	phy->vbus_nb.notifier_call = msm_otg_vbus_notifier; -	phy->id_nb.notifier_call = msm_otg_id_notifier; - -	phy->io_ops = &msm_otg_io_ops; - -	phy->otg->usb_phy = &motg->phy; -	phy->otg->set_host = msm_otg_set_host; -	phy->otg->set_peripheral = msm_otg_set_peripheral; - -	msm_usb_reset(phy); - -	ret = usb_add_phy_dev(&motg->phy); -	if (ret) { -		dev_err(&pdev->dev, "usb_add_phy failed\n"); -		goto disable_ldo; -	} - -	ret = extcon_get_state(phy->edev, EXTCON_USB); -	if (ret) -		set_bit(B_SESS_VLD, &motg->inputs); -	else -		clear_bit(B_SESS_VLD, &motg->inputs); - -	ret = extcon_get_state(phy->id_edev, EXTCON_USB_HOST); -	if (ret) -		clear_bit(ID, &motg->inputs); -	else -		set_bit(ID, &motg->inputs); - -	platform_set_drvdata(pdev, motg); -	device_init_wakeup(&pdev->dev, 1); - -	if (motg->pdata->mode == USB_DR_MODE_OTG && -		motg->pdata->otg_control == OTG_USER_CONTROL) { -		ret = msm_otg_debugfs_init(motg); -		if (ret) -			dev_dbg(&pdev->dev, "Can not create mode change file\n"); -	} - -	if (test_bit(B_SESS_VLD, &motg->inputs)) { -		/* Switch D+/D- lines to Device connector */ -		gpiod_set_value_cansleep(motg->switch_gpio, 0); -	} else { -		/* Switch D+/D- lines to Hub */ -		gpiod_set_value_cansleep(motg->switch_gpio, 1); -	} - -	motg->reboot.notifier_call = msm_otg_reboot_notify; -	register_reboot_notifier(&motg->reboot); - -	pm_runtime_set_active(&pdev->dev); -	pm_runtime_enable(&pdev->dev); - -	return 0; - -disable_ldo: -	msm_hsusb_ldo_init(motg, 0); -disable_vddcx: -	msm_hsusb_init_vddcx(motg, 0); -disable_clks: -	clk_disable_unprepare(motg->pclk); -	clk_disable_unprepare(motg->clk); -	if (!IS_ERR(motg->core_clk)) -		clk_disable_unprepare(motg->core_clk); - -	return ret; -} - -static int msm_otg_remove(struct platform_device *pdev) -{ -	struct msm_otg *motg = platform_get_drvdata(pdev); -	struct usb_phy *phy = &motg->phy; -	int cnt = 0; - -	if (phy->otg->host || phy->otg->gadget) -		return -EBUSY; - -	unregister_reboot_notifier(&motg->reboot); - -	/* -	 * Ensure that D+/D- lines are routed to uB connector, so -	 * we could load bootloader/kernel at next reboot -	 */ -	gpiod_set_value_cansleep(motg->switch_gpio, 0); - -	msm_otg_debugfs_cleanup(); -	cancel_delayed_work_sync(&motg->chg_work); -	cancel_work_sync(&motg->sm_work); - -	pm_runtime_resume(&pdev->dev); - -	device_init_wakeup(&pdev->dev, 0); -	pm_runtime_disable(&pdev->dev); - -	usb_remove_phy(phy); -	disable_irq(motg->irq); - -	/* -	 * Put PHY in low power mode. -	 */ -	ulpi_read(phy, 0x14); -	ulpi_write(phy, 0x08, 0x09); - -	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC); -	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) { -		if (readl(USB_PORTSC) & PORTSC_PHCD) -			break; -		udelay(1); -		cnt++; -	} -	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC) -		dev_err(phy->dev, "Unable to suspend PHY\n"); - -	clk_disable_unprepare(motg->pclk); -	clk_disable_unprepare(motg->clk); -	if (!IS_ERR(motg->core_clk)) -		clk_disable_unprepare(motg->core_clk); -	msm_hsusb_ldo_init(motg, 0); - -	pm_runtime_set_suspended(&pdev->dev); - -	return 0; -} - -#ifdef CONFIG_PM -static int msm_otg_runtime_idle(struct device *dev) -{ -	struct msm_otg *motg = dev_get_drvdata(dev); -	struct usb_otg *otg = motg->phy.otg; - -	dev_dbg(dev, "OTG runtime idle\n"); - -	/* -	 * It is observed some times that a spurious interrupt -	 * comes when PHY is put into LPM immediately after PHY reset. -	 * This 1 sec delay also prevents entering into LPM immediately -	 * after asynchronous interrupt. -	 */ -	if (otg->state != OTG_STATE_UNDEFINED) -		pm_schedule_suspend(dev, 1000); - -	return -EAGAIN; -} - -static int msm_otg_runtime_suspend(struct device *dev) -{ -	struct msm_otg *motg = dev_get_drvdata(dev); - -	dev_dbg(dev, "OTG runtime suspend\n"); -	return msm_otg_suspend(motg); -} - -static int msm_otg_runtime_resume(struct device *dev) -{ -	struct msm_otg *motg = dev_get_drvdata(dev); - -	dev_dbg(dev, "OTG runtime resume\n"); -	return msm_otg_resume(motg); -} -#endif - -#ifdef CONFIG_PM_SLEEP -static int msm_otg_pm_suspend(struct device *dev) -{ -	struct msm_otg *motg = dev_get_drvdata(dev); - -	dev_dbg(dev, "OTG PM suspend\n"); -	return msm_otg_suspend(motg); -} - -static int msm_otg_pm_resume(struct device *dev) -{ -	struct msm_otg *motg = dev_get_drvdata(dev); -	int ret; - -	dev_dbg(dev, "OTG PM resume\n"); - -	ret = msm_otg_resume(motg); -	if (ret) -		return ret; - -	/* -	 * Runtime PM Documentation recommends bringing the -	 * device to full powered state upon resume. -	 */ -	pm_runtime_disable(dev); -	pm_runtime_set_active(dev); -	pm_runtime_enable(dev); - -	return 0; -} -#endif - -static const struct dev_pm_ops msm_otg_dev_pm_ops = { -	SET_SYSTEM_SLEEP_PM_OPS(msm_otg_pm_suspend, msm_otg_pm_resume) -	SET_RUNTIME_PM_OPS(msm_otg_runtime_suspend, msm_otg_runtime_resume, -				msm_otg_runtime_idle) -}; - -static struct platform_driver msm_otg_driver = { -	.probe = msm_otg_probe, -	.remove = msm_otg_remove, -	.driver = { -		.name = DRIVER_NAME, -		.pm = &msm_otg_dev_pm_ops, -		.of_match_table = msm_otg_dt_match, -	}, -}; - -module_platform_driver(msm_otg_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("MSM USB transceiver driver"); diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c index 0e315694adc9..554b72282276 100644 --- a/drivers/usb/phy/phy-mv-usb.c +++ b/drivers/usb/phy/phy-mv-usb.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+  /*   * Copyright (C) 2011 Marvell International Ltd. All rights reserved.   * Author: Chao Xie <chao.xie@marvell.com>   *	   Neil Zhang <zhangwm@marvell.com> - * - * 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.   */  #include <linux/module.h> @@ -87,9 +83,10 @@ static void mv_otg_run_state_machine(struct mv_otg *mvotg,  	queue_delayed_work(mvotg->qwork, &mvotg->work, delay);  } -static void mv_otg_timer_await_bcon(unsigned long data) +static void mv_otg_timer_await_bcon(struct timer_list *t)  { -	struct mv_otg *mvotg = (struct mv_otg *) data; +	struct mv_otg *mvotg = from_timer(mvotg, t, +					  otg_ctrl.timer[A_WAIT_BCON_TIMER]);  	mvotg->otg_ctrl.a_wait_bcon_timeout = 1; @@ -117,8 +114,7 @@ static int mv_otg_cancel_timer(struct mv_otg *mvotg, unsigned int id)  }  static int mv_otg_set_timer(struct mv_otg *mvotg, unsigned int id, -			    unsigned long interval, -			    void (*callback) (unsigned long)) +			    unsigned long interval)  {  	struct timer_list *timer; @@ -131,9 +127,6 @@ static int mv_otg_set_timer(struct mv_otg *mvotg, unsigned int id,  		return -EBUSY;  	} -	init_timer(timer); -	timer->data = (unsigned long) mvotg; -	timer->function = callback;  	timer->expires = jiffies + interval;  	add_timer(timer); @@ -459,8 +452,7 @@ run:  			if (old_state != OTG_STATE_A_HOST)  				mv_otg_start_host(mvotg, 1);  			mv_otg_set_timer(mvotg, A_WAIT_BCON_TIMER, -					 T_A_WAIT_BCON, -					 mv_otg_timer_await_bcon); +					 T_A_WAIT_BCON);  			/*  			 * Now, we directly enter A_HOST. So set b_conn = 1  			 * here. In fact, it need host driver to notify us. @@ -722,7 +714,8 @@ static int mv_otg_probe(struct platform_device *pdev)  	otg->set_vbus = mv_otg_set_vbus;  	for (i = 0; i < OTG_TIMER_NUM; i++) -		init_timer(&mvotg->otg_ctrl.timer[i]); +		timer_setup(&mvotg->otg_ctrl.timer[i], +			    mv_otg_timer_await_bcon, 0);  	r = platform_get_resource_byname(mvotg->pdev,  					 IORESOURCE_MEM, "phyregs"); diff --git a/drivers/usb/phy/phy-mv-usb.h b/drivers/usb/phy/phy-mv-usb.h index 551da6eb0ba8..96701a1229ad 100644 --- a/drivers/usb/phy/phy-mv-usb.h +++ b/drivers/usb/phy/phy-mv-usb.h @@ -1,10 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0+  /*   * Copyright (C) 2011 Marvell International Ltd. All rights reserved. - * - * 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.   */  #ifndef	__MV_USB_OTG_CONTROLLER__ diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index 0e2f1a36d315..da031c45395a 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -1,14 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+  /*   * Copyright 2012-2014 Freescale Semiconductor, Inc.   * Copyright (C) 2012 Marek Vasut <marex@denx.de>   * on behalf of DENX Software Engineering GmbH - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html   */  #include <linux/module.h> @@ -67,11 +61,26 @@  #define ANADIG_ANA_MISC0_SET			0x154  #define ANADIG_ANA_MISC0_CLR			0x158 +#define ANADIG_USB1_CHRG_DETECT_SET		0x1b4 +#define ANADIG_USB1_CHRG_DETECT_CLR		0x1b8 +#define ANADIG_USB1_CHRG_DETECT_EN_B		BIT(20) +#define ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B	BIT(19) +#define ANADIG_USB1_CHRG_DETECT_CHK_CONTACT	BIT(18) +  #define ANADIG_USB1_VBUS_DET_STAT		0x1c0 +#define ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID	BIT(3) + +#define ANADIG_USB1_CHRG_DET_STAT		0x1d0 +#define ANADIG_USB1_CHRG_DET_STAT_DM_STATE	BIT(2) +#define ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED	BIT(1) +#define ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT	BIT(0) +  #define ANADIG_USB2_VBUS_DET_STAT		0x220  #define ANADIG_USB1_LOOPBACK_SET		0x1e4  #define ANADIG_USB1_LOOPBACK_CLR		0x1e8 +#define ANADIG_USB1_LOOPBACK_UTMI_TESTSTART	BIT(0) +  #define ANADIG_USB2_LOOPBACK_SET		0x244  #define ANADIG_USB2_LOOPBACK_CLR		0x248 @@ -479,6 +488,144 @@ static int mxs_phy_on_disconnect(struct usb_phy *phy,  	return 0;  } +#define MXS_USB_CHARGER_DATA_CONTACT_TIMEOUT	100 +static int mxs_charger_data_contact_detect(struct mxs_phy *x) +{ +	struct regmap *regmap = x->regmap_anatop; +	int i, stable_contact_count = 0; +	u32 val; + +	/* Check if vbus is valid */ +	regmap_read(regmap, ANADIG_USB1_VBUS_DET_STAT, &val); +	if (!(val & ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID)) { +		dev_err(x->phy.dev, "vbus is not valid\n"); +		return -EINVAL; +	} + +	/* Enable charger detector */ +	regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_CLR, +				ANADIG_USB1_CHRG_DETECT_EN_B); +	/* +	 * - Do not check whether a charger is connected to the USB port +	 * - Check whether the USB plug has been in contact with each other +	 */ +	regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_SET, +			ANADIG_USB1_CHRG_DETECT_CHK_CONTACT | +			ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B); + +	/* Check if plug is connected */ +	for (i = 0; i < MXS_USB_CHARGER_DATA_CONTACT_TIMEOUT; i++) { +		regmap_read(regmap, ANADIG_USB1_CHRG_DET_STAT, &val); +		if (val & ANADIG_USB1_CHRG_DET_STAT_PLUG_CONTACT) { +			stable_contact_count++; +			if (stable_contact_count > 5) +				/* Data pin makes contact */ +				break; +			else +				usleep_range(5000, 10000); +		} else { +			stable_contact_count = 0; +			usleep_range(5000, 6000); +		} +	} + +	if (i == MXS_USB_CHARGER_DATA_CONTACT_TIMEOUT) { +		dev_err(x->phy.dev, +			"Data pin can't make good contact.\n"); +		/* Disable charger detector */ +		regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_SET, +				ANADIG_USB1_CHRG_DETECT_EN_B | +				ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B); +		return -ENXIO; +	} + +	return 0; +} + +static enum usb_charger_type mxs_charger_primary_detection(struct mxs_phy *x) +{ +	struct regmap *regmap = x->regmap_anatop; +	enum usb_charger_type chgr_type = UNKNOWN_TYPE; +	u32 val; + +	/* +	 * - Do check whether a charger is connected to the USB port +	 * - Do not Check whether the USB plug has been in contact with +	 *   each other +	 */ +	regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_CLR, +			ANADIG_USB1_CHRG_DETECT_CHK_CONTACT | +			ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B); + +	msleep(100); + +	/* Check if it is a charger */ +	regmap_read(regmap, ANADIG_USB1_CHRG_DET_STAT, &val); +	if (!(val & ANADIG_USB1_CHRG_DET_STAT_CHRG_DETECTED)) { +		chgr_type = SDP_TYPE; +		dev_dbg(x->phy.dev, "It is a stardard downstream port\n"); +	} + +	/* Disable charger detector */ +	regmap_write(regmap, ANADIG_USB1_CHRG_DETECT_SET, +			ANADIG_USB1_CHRG_DETECT_EN_B | +			ANADIG_USB1_CHRG_DETECT_CHK_CHRG_B); + +	return chgr_type; +} + +/* + * It must be called after DP is pulled up, which is used to + * differentiate DCP and CDP. + */ +enum usb_charger_type mxs_charger_secondary_detection(struct mxs_phy *x) +{ +	struct regmap *regmap = x->regmap_anatop; +	int val; + +	msleep(80); + +	regmap_read(regmap, ANADIG_USB1_CHRG_DET_STAT, &val); +	if (val & ANADIG_USB1_CHRG_DET_STAT_DM_STATE) { +		dev_dbg(x->phy.dev, "It is a dedicate charging port\n"); +		return DCP_TYPE; +	} else { +		dev_dbg(x->phy.dev, "It is a charging downstream port\n"); +		return CDP_TYPE; +	} +} + +static enum usb_charger_type mxs_phy_charger_detect(struct usb_phy *phy) +{ +	struct mxs_phy *mxs_phy = to_mxs_phy(phy); +	struct regmap *regmap = mxs_phy->regmap_anatop; +	void __iomem *base = phy->io_priv; +	enum usb_charger_type chgr_type = UNKNOWN_TYPE; + +	if (mxs_charger_data_contact_detect(mxs_phy)) +		return chgr_type; + +	chgr_type = mxs_charger_primary_detection(mxs_phy); + +	if (chgr_type != SDP_TYPE) { +		/* Pull up DP via test */ +		writel_relaxed(BM_USBPHY_DEBUG_CLKGATE, +				base + HW_USBPHY_DEBUG_CLR); +		regmap_write(regmap, ANADIG_USB1_LOOPBACK_SET, +				ANADIG_USB1_LOOPBACK_UTMI_TESTSTART); + +		chgr_type = mxs_charger_secondary_detection(mxs_phy); + +		/* Stop the test */ +		regmap_write(regmap, ANADIG_USB1_LOOPBACK_CLR, +				ANADIG_USB1_LOOPBACK_UTMI_TESTSTART); +		writel_relaxed(BM_USBPHY_DEBUG_CLKGATE, +				base + HW_USBPHY_DEBUG_SET); +	} + +	return chgr_type; +} +  static int mxs_phy_probe(struct platform_device *pdev)  {  	struct resource *res; @@ -567,6 +714,7 @@ static int mxs_phy_probe(struct platform_device *pdev)  	mxs_phy->phy.notify_disconnect	= mxs_phy_on_disconnect;  	mxs_phy->phy.type		= USB_PHY_TYPE_USB2;  	mxs_phy->phy.set_wakeup		= mxs_phy_set_wakeup; +	mxs_phy->phy.charger_detect	= mxs_phy_charger_detect;  	mxs_phy->clk = clk;  	mxs_phy->data = of_id->data; diff --git a/drivers/usb/phy/phy-omap-otg.c b/drivers/usb/phy/phy-omap-otg.c index 800d1d90753d..ee0863c6553e 100644 --- a/drivers/usb/phy/phy-omap-otg.c +++ b/drivers/usb/phy/phy-omap-otg.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * OMAP OTG controller driver   * @@ -6,15 +7,6 @@   * Copyright (C) 2005-2006 Nokia Corporation   * Copyright (C) 2004 Texas Instruments   * Copyright (C) 2004 David Brownell - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file "COPYING" in the main directory of this - * archive for more details. - * - * 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 <linux/io.h> diff --git a/drivers/usb/phy/phy-qcom-8x16-usb.c b/drivers/usb/phy/phy-qcom-8x16-usb.c deleted file mode 100644 index 679afeaaa9a8..000000000000 --- a/drivers/usb/phy/phy-qcom-8x16-usb.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (c) 2015, Linaro Limited - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * 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 <linux/clk.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/err.h> -#include <linux/extcon.h> -#include <linux/gpio/consumer.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/platform_device.h> -#include <linux/reboot.h> -#include <linux/regulator/consumer.h> -#include <linux/reset.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/usb/ulpi.h> - -#define HSPHY_AHBBURST			0x0090 -#define HSPHY_AHBMODE			0x0098 -#define HSPHY_GENCONFIG			0x009c -#define HSPHY_GENCONFIG_2		0x00a0 - -#define HSPHY_USBCMD			0x0140 -#define HSPHY_ULPI_VIEWPORT		0x0170 -#define HSPHY_CTRL			0x0240 - -#define HSPHY_TXFIFO_IDLE_FORCE_DIS	BIT(4) -#define HSPHY_SESS_VLD_CTRL_EN		BIT(7) -#define HSPHY_POR_ASSERT		BIT(0) -#define HSPHY_RETEN			BIT(1) - -#define HSPHY_SESS_VLD_CTRL		BIT(25) - -#define ULPI_PWR_CLK_MNG_REG		0x88 -#define ULPI_PWR_OTG_COMP_DISABLE	BIT(0) - -#define ULPI_MISC_A			0x96 -#define ULPI_MISC_A_VBUSVLDEXTSEL	BIT(1) -#define ULPI_MISC_A_VBUSVLDEXT		BIT(0) - -#define HSPHY_3P3_MIN			3050000 /* uV */ -#define HSPHY_3P3_MAX			3300000 /* uV */ - -#define HSPHY_1P8_MIN			1800000 /* uV */ -#define HSPHY_1P8_MAX			1800000 /* uV */ - -#define HSPHY_VDD_MIN			5 -#define HSPHY_VDD_MAX			7 - -struct phy_8x16 { -	struct usb_phy			phy; -	void __iomem			*regs; -	struct clk			*core_clk; -	struct clk			*iface_clk; -	struct regulator_bulk_data	regulator[3]; - -	struct reset_control		*phy_reset; - -	struct gpio_desc		*switch_gpio; -	struct notifier_block		reboot_notify; -}; - -static int phy_8x16_notify_connect(struct usb_phy *phy, -				   enum usb_device_speed speed) -{ -	struct phy_8x16 *qphy = container_of(phy, struct phy_8x16, phy); -	u32 val; - -	val = ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT; -	usb_phy_io_write(&qphy->phy, val, ULPI_SET(ULPI_MISC_A)); - -	val = readl(qphy->regs + HSPHY_USBCMD); -	val |= HSPHY_SESS_VLD_CTRL; -	writel(val, qphy->regs + HSPHY_USBCMD); - -	return 0; -} - -static int phy_8x16_notify_disconnect(struct usb_phy *phy, -				      enum usb_device_speed speed) -{ -	struct phy_8x16 *qphy = container_of(phy, struct phy_8x16, phy); -	u32 val; - -	val = ULPI_MISC_A_VBUSVLDEXT | ULPI_MISC_A_VBUSVLDEXTSEL; -	usb_phy_io_write(&qphy->phy, val, ULPI_CLR(ULPI_MISC_A)); - -	val = readl(qphy->regs + HSPHY_USBCMD); -	val &= ~HSPHY_SESS_VLD_CTRL; -	writel(val, qphy->regs + HSPHY_USBCMD); - -	return 0; -} - -static int phy_8x16_vbus_on(struct phy_8x16 *qphy) -{ -	phy_8x16_notify_connect(&qphy->phy, USB_SPEED_UNKNOWN); - -	/* Switch D+/D- lines to Device connector */ -	gpiod_set_value_cansleep(qphy->switch_gpio, 0); - -	return 0; -} - -static int phy_8x16_vbus_off(struct phy_8x16 *qphy) -{ -	phy_8x16_notify_disconnect(&qphy->phy, USB_SPEED_UNKNOWN); - -	/* Switch D+/D- lines to USB HUB */ -	gpiod_set_value_cansleep(qphy->switch_gpio, 1); - -	return 0; -} - -static int phy_8x16_vbus_notify(struct notifier_block *nb, unsigned long event, -				void *ptr) -{ -	struct usb_phy *usb_phy = container_of(nb, struct usb_phy, vbus_nb); -	struct phy_8x16 *qphy = container_of(usb_phy, struct phy_8x16, phy); - -	if (event) -		phy_8x16_vbus_on(qphy); -	else -		phy_8x16_vbus_off(qphy); - -	return NOTIFY_DONE; -} - -static int phy_8x16_init(struct usb_phy *phy) -{ -	struct phy_8x16 *qphy = container_of(phy, struct phy_8x16, phy); -	u32 val, init[] = {0x44, 0x6B, 0x24, 0x13}; -	u32 addr = ULPI_EXT_VENDOR_SPECIFIC; -	int idx, state; - -	for (idx = 0; idx < ARRAY_SIZE(init); idx++) -		usb_phy_io_write(phy, init[idx], addr + idx); - -	reset_control_reset(qphy->phy_reset); - -	/* Assert USB HSPHY_POR */ -	val = readl(qphy->regs + HSPHY_CTRL); -	val |= HSPHY_POR_ASSERT; -	writel(val, qphy->regs + HSPHY_CTRL); - -	/* -	 * wait for minimum 10 microseconds as suggested in HPG. -	 * Use a slightly larger value since the exact value didn't -	 * work 100% of the time. -	 */ -	usleep_range(12, 15); - -	/* Deassert USB HSPHY_POR */ -	val = readl(qphy->regs + HSPHY_CTRL); -	val &= ~HSPHY_POR_ASSERT; -	writel(val, qphy->regs + HSPHY_CTRL); - -	usleep_range(10, 15); - -	writel(0x00, qphy->regs + HSPHY_AHBBURST); -	writel(0x08, qphy->regs + HSPHY_AHBMODE); - -	/* workaround for rx buffer collision issue */ -	val = readl(qphy->regs + HSPHY_GENCONFIG); -	val &= ~HSPHY_TXFIFO_IDLE_FORCE_DIS; -	writel(val, qphy->regs + HSPHY_GENCONFIG); - -	val = readl(qphy->regs + HSPHY_GENCONFIG_2); -	val |= HSPHY_SESS_VLD_CTRL_EN; -	writel(val, qphy->regs + HSPHY_GENCONFIG_2); - -	val = ULPI_PWR_OTG_COMP_DISABLE; -	usb_phy_io_write(phy, val, ULPI_SET(ULPI_PWR_CLK_MNG_REG)); - -	state = extcon_get_state(qphy->phy.edev, EXTCON_USB); -	if (state) -		phy_8x16_vbus_on(qphy); -	else -		phy_8x16_vbus_off(qphy); - -	val = usb_phy_io_read(&qphy->phy, ULPI_FUNC_CTRL); -	val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; -	val |= ULPI_FUNC_CTRL_OPMODE_NORMAL; -	usb_phy_io_write(&qphy->phy, val, ULPI_FUNC_CTRL); - -	return 0; -} - -static void phy_8x16_shutdown(struct usb_phy *phy) -{ -	u32 val; - -	/* Put the controller in non-driving mode */ -	val = usb_phy_io_read(phy, ULPI_FUNC_CTRL); -	val &= ~ULPI_FUNC_CTRL_OPMODE_MASK; -	val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING; -	usb_phy_io_write(phy, val, ULPI_FUNC_CTRL); -} - -static int phy_8x16_read_devicetree(struct phy_8x16 *qphy) -{ -	struct device *dev = qphy->phy.dev; -	int ret; - -	qphy->core_clk = devm_clk_get(dev, "core"); -	if (IS_ERR(qphy->core_clk)) -		return PTR_ERR(qphy->core_clk); - -	qphy->iface_clk = devm_clk_get(dev, "iface"); -	if (IS_ERR(qphy->iface_clk)) -		return PTR_ERR(qphy->iface_clk); - -	qphy->regulator[0].supply = "v3p3"; -	qphy->regulator[1].supply = "v1p8"; -	qphy->regulator[2].supply = "vddcx"; - -	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(qphy->regulator), -				      qphy->regulator); -	if (ret) -		return ret; - -	qphy->phy_reset = devm_reset_control_get(dev, "phy"); -	if (IS_ERR(qphy->phy_reset)) -		return PTR_ERR(qphy->phy_reset); - -	qphy->switch_gpio = devm_gpiod_get_optional(dev, "switch", -						   GPIOD_OUT_LOW); -	return PTR_ERR_OR_ZERO(qphy->switch_gpio); -} - -static int phy_8x16_reboot_notify(struct notifier_block *this, -				  unsigned long code, void *unused) -{ -	struct phy_8x16 *qphy; - -	qphy = container_of(this, struct phy_8x16, reboot_notify); - -	/* -	 * Ensure that D+/D- lines are routed to uB connector, so -	 * we could load bootloader/kernel at next reboot_notify -	 */ -	gpiod_set_value_cansleep(qphy->switch_gpio, 0); -	return NOTIFY_DONE; -} - -static int phy_8x16_probe(struct platform_device *pdev) -{ -	struct phy_8x16 *qphy; -	struct resource *res; -	struct usb_phy *phy; -	int ret; - -	qphy = devm_kzalloc(&pdev->dev, sizeof(*qphy), GFP_KERNEL); -	if (!qphy) -		return -ENOMEM; - -	platform_set_drvdata(pdev, qphy); - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	qphy->regs = devm_ioremap_resource(&pdev->dev, res); -	if (IS_ERR(qphy->regs)) -		return PTR_ERR(qphy->regs); - -	phy			= &qphy->phy; -	phy->dev		= &pdev->dev; -	phy->label		= dev_name(&pdev->dev); -	phy->init		= phy_8x16_init; -	phy->shutdown		= phy_8x16_shutdown; -	phy->notify_connect	= phy_8x16_notify_connect; -	phy->notify_disconnect	= phy_8x16_notify_disconnect; -	phy->io_priv		= qphy->regs + HSPHY_ULPI_VIEWPORT; -	phy->io_ops		= &ulpi_viewport_access_ops; -	phy->type		= USB_PHY_TYPE_USB2; -	phy->vbus_nb.notifier_call = phy_8x16_vbus_notify; -	phy->id_nb.notifier_call = NULL; - -	ret = phy_8x16_read_devicetree(qphy); -	if (ret < 0) -		return ret; - -	ret = clk_set_rate(qphy->core_clk, INT_MAX); -	if (ret < 0) -		dev_dbg(phy->dev, "Can't boost core clock\n"); - -	ret = clk_prepare_enable(qphy->core_clk); -	if (ret < 0) -		return ret; - -	ret = clk_prepare_enable(qphy->iface_clk); -	if (ret < 0) -		goto off_core; - -	ret = regulator_bulk_enable(ARRAY_SIZE(qphy->regulator), -				    qphy->regulator); -	if (WARN_ON(ret)) -		goto off_clks; - -	ret = usb_add_phy_dev(&qphy->phy); -	if (ret) -		goto off_power; - -	qphy->reboot_notify.notifier_call = phy_8x16_reboot_notify; -	register_reboot_notifier(&qphy->reboot_notify); - -	return 0; - -off_power: -	regulator_bulk_disable(ARRAY_SIZE(qphy->regulator), qphy->regulator); -off_clks: -	clk_disable_unprepare(qphy->iface_clk); -off_core: -	clk_disable_unprepare(qphy->core_clk); -	return ret; -} - -static int phy_8x16_remove(struct platform_device *pdev) -{ -	struct phy_8x16 *qphy = platform_get_drvdata(pdev); - -	unregister_reboot_notifier(&qphy->reboot_notify); - -	/* -	 * Ensure that D+/D- lines are routed to uB connector, so -	 * we could load bootloader/kernel at next reboot_notify -	 */ -	gpiod_set_value_cansleep(qphy->switch_gpio, 0); - -	usb_remove_phy(&qphy->phy); - -	clk_disable_unprepare(qphy->iface_clk); -	clk_disable_unprepare(qphy->core_clk); -	regulator_bulk_disable(ARRAY_SIZE(qphy->regulator), qphy->regulator); -	return 0; -} - -static const struct of_device_id phy_8x16_dt_match[] = { -	{ .compatible = "qcom,usb-8x16-phy" }, -	{ } -}; -MODULE_DEVICE_TABLE(of, phy_8x16_dt_match); - -static struct platform_driver phy_8x16_driver = { -	.probe	= phy_8x16_probe, -	.remove = phy_8x16_remove, -	.driver = { -		.name = "phy-qcom-8x16-usb", -		.of_match_table = phy_8x16_dt_match, -	}, -}; -module_platform_driver(phy_8x16_driver); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("Qualcomm APQ8016/MSM8916 chipsets USB transceiver driver"); diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c index 8babd318c0ed..b3ce42edb373 100644 --- a/drivers/usb/phy/phy-tahvo.c +++ b/drivers/usb/phy/phy-tahvo.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Tahvo USB transceiver driver   * @@ -9,21 +10,12 @@   *   * Original driver written by Juha Yrjölä, Tony Lindgren and Timo Teräs.   * Modified for Retu/Tahvo MFD by Aaro Koskinen. - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file "COPYING" in the main directory of this - * archive for more details. - * - * 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 <linux/io.h>  #include <linux/clk.h>  #include <linux/usb.h> -#include <linux/extcon.h> +#include <linux/extcon-provider.h>  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/usb/otg.h> @@ -368,7 +360,8 @@ static int tahvo_usb_probe(struct platform_device *pdev)  	tu->extcon = devm_extcon_dev_allocate(&pdev->dev, tahvo_cable);  	if (IS_ERR(tu->extcon)) {  		dev_err(&pdev->dev, "failed to allocate memory for extcon\n"); -		return -ENOMEM; +		ret = PTR_ERR(tu->extcon); +		goto err_disable_clk;  	}  	ret = devm_extcon_dev_register(&pdev->dev, tu->extcon); diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index 5fe4a5704bde..f668bfb708d3 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Copyright (C) 2010 Google, Inc.   * Copyright (C) 2013 NVIDIA Corporation @@ -6,16 +7,6 @@   *	Erik Gilling <konkers@google.com>   *	Benoit Goby <benoit@android.com>   *	Venu Byravarasu <vbyravarasu@nvidia.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 <linux/resource.h> @@ -329,6 +320,14 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)  	unsigned long val;  	void __iomem *base = phy->regs; +	/* +	 * The USB driver may have already initiated the phy clock +	 * disable so wait to see if the clock turns off and if not +	 * then proceed with gating the clock. +	 */ +	if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) == 0) +		return; +  	if (phy->is_legacy_phy) {  		val = readl(base + USB_SUSP_CTRL);  		val |= USB_SUSP_SET; @@ -351,6 +350,15 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)  	unsigned long val;  	void __iomem *base = phy->regs; +	/* +	 * The USB driver may have already initiated the phy clock +	 * enable so wait to see if the clock turns on and if not +	 * then proceed with ungating the clock. +	 */ +	if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, +			       USB_PHY_CLK_VALID) == 0) +		return; +  	if (phy->is_legacy_phy) {  		val = readl(base + USB_SUSP_CTRL);  		val |= USB_SUSP_CLR; diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c index b5dc077ed7d3..e78ed52339e6 100644 --- a/drivers/usb/phy/phy-twl6030-usb.c +++ b/drivers/usb/phy/phy-twl6030-usb.c @@ -1,23 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+  /*   * twl6030_usb - TWL6030 USB transceiver, talking to OMAP OTG driver.   *   * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com - * 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.   *   * Author: Hema HK <hemahk@ti.com> - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - *   */  #include <linux/module.h> diff --git a/drivers/usb/phy/phy-ulpi-viewport.c b/drivers/usb/phy/phy-ulpi-viewport.c index 18bb8264b5a0..7a14e0e3b635 100644 --- a/drivers/usb/phy/phy-ulpi-viewport.c +++ b/drivers/usb/phy/phy-ulpi-viewport.c @@ -1,15 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * Copyright (C) 2011 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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 <linux/export.h> diff --git a/drivers/usb/phy/phy-ulpi.c b/drivers/usb/phy/phy-ulpi.c index f48a7a21e3c2..a43c49369a60 100644 --- a/drivers/usb/phy/phy-ulpi.c +++ b/drivers/usb/phy/phy-ulpi.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+  /*   * Generic ULPI USB transceiver support   * @@ -7,20 +8,6 @@   *   *   Sascha Hauer <s.hauer@pengutronix.de>   *   Freescale Semiconductors - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */  #include <linux/kernel.h> diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c index 89f4ac4cd93e..f97cb47577fc 100644 --- a/drivers/usb/phy/phy.c +++ b/drivers/usb/phy/phy.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+  /*   * phy.c -- USB phy handling   *   * Copyright (C) 2004-2013 Texas Instruments - * - * 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.   */  #include <linux/kernel.h>  #include <linux/export.h>  | 

