forked from mirrors/linux
		
	phy: for 4.2 merge window
*) new Broadcom SATA3 PHY driver for Broadcom STB SoCs
 *) new phy API to get PHY by index which is used in EHCI and
    OHCI controller drivers
 *) support specifying supply at port level used for multi-port PHYs
 *) sparse warning fixes in miphy PHYs
 *) fix pm_runtime issues in twl4030 driver
 
 Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJVbbvfAAoJEA5ceFyATYLZdAIP/2mFENq9DIRDqU7LV4aQRDlC
 TlL+DLGwElAGKkq7bL3UaWy+10kooTmVaYVB1MACAPXZgKguTkjsSdWXDSxFHDyG
 tq32CqkeMx1uhsZBMhdxsIsTnAPfEo1s2lO7O/HaJTq38aqKixC5+A3IYXttSvET
 jF4XCx7IGNK7YIMylTzAW1FN9rHvsp4RRKIkPjS8EAiAbQIcu7rxKdSbfwJ69Zxt
 EUep3u7jvlQK6SmOig3nkoQFf70G6d7p0VsBPrU6l6Dg9Ciu/5ZvzCkg5ukGotOl
 1GIpowjW3abIaX6yGOD95phU8+JPZbncG/vrQ5Hf/FDZtvCgs6tYqY+Zqmxf7SlK
 4Jj43+sjvDt05Ty9K1sP2FnQqBq9XKEmX5K1pYCrHDbDiH0L9gKeX9/46dJhDrMS
 F3rfrcgBxqBqT96BsqPHmuN0uUvXaF7pGKyFWoGodblBsYee6z4XAl8Up62Lqq3U
 QglegTz9ICKDU1j8xmjLHN9l21BfXANdirFTyjtV3XIGR6mcmzd3R3qk7x2ulaQ8
 lA4gfUhm9X8f55FTqLIw+7Ld+rgEW9NYHSX4fFvtzB/T5SPdOrslgjby4i0a81Pv
 IfQcLaQZ75QIj+22sy27cXrQsmUCe6sNXrms190uknh3hEHDeNOtPupYIMJcXiO+
 n2YJ6QCOnly3tSMFNWfM
 =vPk6
 -----END PGP SIGNATURE-----
Merge tag 'phy-for-v4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy into usb-next
Kishon writes:
phy: for 4.2 merge window
*) new Broadcom SATA3 PHY driver for Broadcom STB SoCs
*) new phy API to get PHY by index which is used in EHCI and
   OHCI controller drivers
*) support specifying supply at port level used for multi-port PHYs
*) sparse warning fixes in miphy PHYs
*) fix pm_runtime issues in twl4030 driver
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
			
			
This commit is contained in:
		
						commit
						b3d424e3dc
					
				
					 15 changed files with 415 additions and 139 deletions
				
			
		
							
								
								
									
										8
									
								
								Documentation/ABI/testing/sysfs-platform-twl4030-usb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Documentation/ABI/testing/sysfs-platform-twl4030-usb
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| What: /sys/bus/platform/devices/*twl4030-usb/vbus | ||||
| Description: | ||||
| 	Read-only status reporting if VBUS (approx 5V) | ||||
| 	is being supplied by the USB bus. | ||||
| 
 | ||||
| 	Possible values: "on", "off". | ||||
| 
 | ||||
| 	Changes are notified via select/poll. | ||||
|  | @ -0,0 +1,40 @@ | |||
| * Broadcom SATA3 PHY for STB | ||||
| 
 | ||||
| Required properties: | ||||
| - compatible: should be one or more of | ||||
|      "brcm,bcm7445-sata-phy" | ||||
|      "brcm,phy-sata3" | ||||
| - address-cells: should be 1 | ||||
| - size-cells: should be 0 | ||||
| - reg: register range for the PHY PCB interface | ||||
| - reg-names: should be "phy" | ||||
| 
 | ||||
| Sub-nodes: | ||||
|   Each port's PHY should be represented as a sub-node. | ||||
| 
 | ||||
| Sub-nodes required properties: | ||||
| - reg: the PHY number | ||||
| - phy-cells: generic PHY binding; must be 0 | ||||
| Optional: | ||||
| - brcm,enable-ssc: use spread spectrum clocking (SSC) on this port | ||||
| 
 | ||||
| 
 | ||||
| Example: | ||||
| 
 | ||||
| 	sata-phy@f0458100 { | ||||
| 		compatible = "brcm,bcm7445-sata-phy", "brcm,phy-sata3"; | ||||
| 		reg = <0xf0458100 0x1e00>, <0xf045804c 0x10>; | ||||
| 		reg-names = "phy"; | ||||
| 		#address-cells = <1>; | ||||
| 		#size-cells = <0>; | ||||
| 
 | ||||
| 		sata-phy@0 { | ||||
| 			reg = <0>; | ||||
| 			#phy-cells = <0>; | ||||
| 		}; | ||||
| 
 | ||||
| 		sata-phy@1 { | ||||
| 			reg = <1>; | ||||
| 			#phy-cells = <0>; | ||||
| 		}; | ||||
| 	}; | ||||
|  | @ -6,6 +6,7 @@ This file provides information on what the device node for the R-Car generation | |||
| Required properties: | ||||
| - compatible: "renesas,usb-phy-r8a7790" if the device is a part of R8A7790 SoC. | ||||
| 	      "renesas,usb-phy-r8a7791" if the device is a part of R8A7791 SoC. | ||||
| 	      "renesas,usb-phy-r8a7794" if the device is a part of R8A7794 SoC. | ||||
| - reg: offset and length of the register block. | ||||
| - #address-cells: number of address cells for the USB channel subnodes, must | ||||
| 		  be <1>. | ||||
|  |  | |||
|  | @ -76,6 +76,8 @@ struct phy *phy_get(struct device *dev, const char *string); | |||
| struct phy *phy_optional_get(struct device *dev, const char *string); | ||||
| struct phy *devm_phy_get(struct device *dev, const char *string); | ||||
| struct phy *devm_phy_optional_get(struct device *dev, const char *string); | ||||
| struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np, | ||||
| 				     int index); | ||||
| 
 | ||||
| phy_get, phy_optional_get, devm_phy_get and devm_phy_optional_get can | ||||
| be used to get the PHY. In the case of dt boot, the string arguments | ||||
|  | @ -86,7 +88,10 @@ successful PHY get. On driver detach, release function is invoked on | |||
| the the devres data and devres data is freed. phy_optional_get and | ||||
| devm_phy_optional_get should be used when the phy is optional. These | ||||
| two functions will never return -ENODEV, but instead returns NULL when | ||||
| the phy cannot be found. | ||||
| the phy cannot be found.Some generic drivers, such as ehci, may use multiple | ||||
| phys and for such drivers referencing phy(s) by name(s) does not make sense. In | ||||
| this case, devm_of_phy_get_by_index can be used to get a phy reference based on | ||||
| the index. | ||||
| 
 | ||||
| It should be noted that NULL is a valid phy reference. All phy | ||||
| consumer calls on the NULL phy become NOPs. That is the release calls, | ||||
|  |  | |||
|  | @ -316,4 +316,13 @@ config PHY_TUSB1210 | |||
| 	help | ||||
| 	  Support for TI TUSB1210 USB ULPI PHY. | ||||
| 
 | ||||
| config PHY_BRCMSTB_SATA | ||||
| 	tristate "Broadcom STB SATA PHY driver" | ||||
| 	depends on ARCH_BRCMSTB | ||||
| 	depends on OF | ||||
| 	select GENERIC_PHY | ||||
| 	help | ||||
| 	  Enable this to support the SATA3 PHY on 28nm Broadcom STB SoCs. | ||||
| 	  Likely useful only with CONFIG_SATA_BRCMSTB enabled. | ||||
| 
 | ||||
| endmenu | ||||
|  |  | |||
|  | @ -41,3 +41,4 @@ obj-$(CONFIG_PHY_QCOM_UFS) 	+= phy-qcom-ufs.o | |||
| obj-$(CONFIG_PHY_QCOM_UFS) 	+= phy-qcom-ufs-qmp-20nm.o | ||||
| obj-$(CONFIG_PHY_QCOM_UFS) 	+= phy-qcom-ufs-qmp-14nm.o | ||||
| obj-$(CONFIG_PHY_TUSB1210)		+= phy-tusb1210.o | ||||
| obj-$(CONFIG_PHY_BRCMSTB_SATA)		+= phy-brcmstb-sata.o | ||||
|  |  | |||
							
								
								
									
										216
									
								
								drivers/phy/phy-brcmstb-sata.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								drivers/phy/phy-brcmstb-sata.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,216 @@ | |||
| /*
 | ||||
|  * Broadcom SATA3 AHCI Controller PHY Driver | ||||
|  * | ||||
|  * Copyright © 2009-2015 Broadcom Corporation | ||||
|  * | ||||
|  * 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, or (at your option) | ||||
|  * any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/device.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/interrupt.h> | ||||
| #include <linux/io.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/of.h> | ||||
| #include <linux/phy/phy.h> | ||||
| #include <linux/platform_device.h> | ||||
| 
 | ||||
| #define SATA_MDIO_BANK_OFFSET				0x23c | ||||
| #define SATA_MDIO_REG_OFFSET(ofs)			((ofs) * 4) | ||||
| #define SATA_MDIO_REG_SPACE_SIZE			0x1000 | ||||
| #define SATA_MDIO_REG_LENGTH				0x1f00 | ||||
| 
 | ||||
| #define MAX_PORTS					2 | ||||
| 
 | ||||
| /* Register offset between PHYs in PCB space */ | ||||
| #define SATA_MDIO_REG_SPACE_SIZE			0x1000 | ||||
| 
 | ||||
| struct brcm_sata_port { | ||||
| 	int portnum; | ||||
| 	struct phy *phy; | ||||
| 	struct brcm_sata_phy *phy_priv; | ||||
| 	bool ssc_en; | ||||
| }; | ||||
| 
 | ||||
| struct brcm_sata_phy { | ||||
| 	struct device *dev; | ||||
| 	void __iomem *phy_base; | ||||
| 
 | ||||
| 	struct brcm_sata_port phys[MAX_PORTS]; | ||||
| }; | ||||
| 
 | ||||
| enum sata_mdio_phy_regs_28nm { | ||||
| 	PLL_REG_BANK_0				= 0x50, | ||||
| 	PLL_REG_BANK_0_PLLCONTROL_0		= 0x81, | ||||
| 
 | ||||
| 	TXPMD_REG_BANK				= 0x1a0, | ||||
| 	TXPMD_CONTROL1				= 0x81, | ||||
| 	TXPMD_CONTROL1_TX_SSC_EN_FRC		= BIT(0), | ||||
| 	TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL	= BIT(1), | ||||
| 	TXPMD_TX_FREQ_CTRL_CONTROL1		= 0x82, | ||||
| 	TXPMD_TX_FREQ_CTRL_CONTROL2		= 0x83, | ||||
| 	TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK	= 0x3ff, | ||||
| 	TXPMD_TX_FREQ_CTRL_CONTROL3		= 0x84, | ||||
| 	TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK	= 0x3ff, | ||||
| }; | ||||
| 
 | ||||
| static inline void __iomem *brcm_sata_phy_base(struct brcm_sata_port *port) | ||||
| { | ||||
| 	struct brcm_sata_phy *priv = port->phy_priv; | ||||
| 
 | ||||
| 	return priv->phy_base + (port->portnum * SATA_MDIO_REG_SPACE_SIZE); | ||||
| } | ||||
| 
 | ||||
| static void brcm_sata_mdio_wr(void __iomem *addr, u32 bank, u32 ofs, | ||||
| 			      u32 msk, u32 value) | ||||
| { | ||||
| 	u32 tmp; | ||||
| 
 | ||||
| 	writel(bank, addr + SATA_MDIO_BANK_OFFSET); | ||||
| 	tmp = readl(addr + SATA_MDIO_REG_OFFSET(ofs)); | ||||
| 	tmp = (tmp & msk) | value; | ||||
| 	writel(tmp, addr + SATA_MDIO_REG_OFFSET(ofs)); | ||||
| } | ||||
| 
 | ||||
| /* These defaults were characterized by H/W group */ | ||||
| #define FMIN_VAL_DEFAULT	0x3df | ||||
| #define FMAX_VAL_DEFAULT	0x3df | ||||
| #define FMAX_VAL_SSC		0x83 | ||||
| 
 | ||||
| static void brcm_sata_cfg_ssc_28nm(struct brcm_sata_port *port) | ||||
| { | ||||
| 	void __iomem *base = brcm_sata_phy_base(port); | ||||
| 	struct brcm_sata_phy *priv = port->phy_priv; | ||||
| 	u32 tmp; | ||||
| 
 | ||||
| 	/* override the TX spread spectrum setting */ | ||||
| 	tmp = TXPMD_CONTROL1_TX_SSC_EN_FRC_VAL | TXPMD_CONTROL1_TX_SSC_EN_FRC; | ||||
| 	brcm_sata_mdio_wr(base, TXPMD_REG_BANK, TXPMD_CONTROL1, ~tmp, tmp); | ||||
| 
 | ||||
| 	/* set fixed min freq */ | ||||
| 	brcm_sata_mdio_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL2, | ||||
| 			  ~TXPMD_TX_FREQ_CTRL_CONTROL2_FMIN_MASK, | ||||
| 			  FMIN_VAL_DEFAULT); | ||||
| 
 | ||||
| 	/* set fixed max freq depending on SSC config */ | ||||
| 	if (port->ssc_en) { | ||||
| 		dev_info(priv->dev, "enabling SSC on port %d\n", port->portnum); | ||||
| 		tmp = FMAX_VAL_SSC; | ||||
| 	} else { | ||||
| 		tmp = FMAX_VAL_DEFAULT; | ||||
| 	} | ||||
| 
 | ||||
| 	brcm_sata_mdio_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3, | ||||
| 			  ~TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK, tmp); | ||||
| } | ||||
| 
 | ||||
| static int brcm_sata_phy_init(struct phy *phy) | ||||
| { | ||||
| 	struct brcm_sata_port *port = phy_get_drvdata(phy); | ||||
| 
 | ||||
| 	brcm_sata_cfg_ssc_28nm(port); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static struct phy_ops phy_ops_28nm = { | ||||
| 	.init		= brcm_sata_phy_init, | ||||
| 	.owner		= THIS_MODULE, | ||||
| }; | ||||
| 
 | ||||
| static const struct of_device_id brcm_sata_phy_of_match[] = { | ||||
| 	{ .compatible	= "brcm,bcm7445-sata-phy" }, | ||||
| 	{}, | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match); | ||||
| 
 | ||||
| static int brcm_sata_phy_probe(struct platform_device *pdev) | ||||
| { | ||||
| 	struct device *dev = &pdev->dev; | ||||
| 	struct device_node *dn = dev->of_node, *child; | ||||
| 	struct brcm_sata_phy *priv; | ||||
| 	struct resource *res; | ||||
| 	struct phy_provider *provider; | ||||
| 	int count = 0; | ||||
| 
 | ||||
| 	if (of_get_child_count(dn) == 0) | ||||
| 		return -ENODEV; | ||||
| 
 | ||||
| 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | ||||
| 	if (!priv) | ||||
| 		return -ENOMEM; | ||||
| 	dev_set_drvdata(dev, priv); | ||||
| 	priv->dev = dev; | ||||
| 
 | ||||
| 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); | ||||
| 	priv->phy_base = devm_ioremap_resource(dev, res); | ||||
| 	if (IS_ERR(priv->phy_base)) | ||||
| 		return PTR_ERR(priv->phy_base); | ||||
| 
 | ||||
| 	for_each_available_child_of_node(dn, child) { | ||||
| 		unsigned int id; | ||||
| 		struct brcm_sata_port *port; | ||||
| 
 | ||||
| 		if (of_property_read_u32(child, "reg", &id)) { | ||||
| 			dev_err(dev, "missing reg property in node %s\n", | ||||
| 					child->name); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 
 | ||||
| 		if (id >= MAX_PORTS) { | ||||
| 			dev_err(dev, "invalid reg: %u\n", id); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 		if (priv->phys[id].phy) { | ||||
| 			dev_err(dev, "already registered port %u\n", id); | ||||
| 			return -EINVAL; | ||||
| 		} | ||||
| 
 | ||||
| 		port = &priv->phys[id]; | ||||
| 		port->portnum = id; | ||||
| 		port->phy_priv = priv; | ||||
| 		port->phy = devm_phy_create(dev, child, &phy_ops_28nm); | ||||
| 		port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc"); | ||||
| 		if (IS_ERR(port->phy)) { | ||||
| 			dev_err(dev, "failed to create PHY\n"); | ||||
| 			return PTR_ERR(port->phy); | ||||
| 		} | ||||
| 
 | ||||
| 		phy_set_drvdata(port->phy, port); | ||||
| 		count++; | ||||
| 	} | ||||
| 
 | ||||
| 	provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||||
| 	if (IS_ERR(provider)) { | ||||
| 		dev_err(dev, "could not register PHY provider\n"); | ||||
| 		return PTR_ERR(provider); | ||||
| 	} | ||||
| 
 | ||||
| 	dev_info(dev, "registered %d port(s)\n", count); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static struct platform_driver brcm_sata_phy_driver = { | ||||
| 	.probe	= brcm_sata_phy_probe, | ||||
| 	.driver	= { | ||||
| 		.of_match_table	= brcm_sata_phy_of_match, | ||||
| 		.name		= "brcmstb-sata-phy", | ||||
| 	} | ||||
| }; | ||||
| module_platform_driver(brcm_sata_phy_driver); | ||||
| 
 | ||||
| MODULE_DESCRIPTION("Broadcom STB SATA PHY driver"); | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("Marc Carino"); | ||||
| MODULE_AUTHOR("Brian Norris"); | ||||
| MODULE_ALIAS("platform:phy-brcmstb-sata"); | ||||
|  | @ -367,13 +367,21 @@ static struct phy *_of_phy_get(struct device_node *np, int index) | |||
| 	phy_provider = of_phy_provider_lookup(args.np); | ||||
| 	if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) { | ||||
| 		phy = ERR_PTR(-EPROBE_DEFER); | ||||
| 		goto err0; | ||||
| 		goto out_unlock; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!of_device_is_available(args.np)) { | ||||
| 		dev_warn(phy_provider->dev, "Requested PHY is disabled\n"); | ||||
| 		phy = ERR_PTR(-ENODEV); | ||||
| 		goto out_put_module; | ||||
| 	} | ||||
| 
 | ||||
| 	phy = phy_provider->of_xlate(phy_provider->dev, &args); | ||||
| 
 | ||||
| out_put_module: | ||||
| 	module_put(phy_provider->owner); | ||||
| 
 | ||||
| err0: | ||||
| out_unlock: | ||||
| 	mutex_unlock(&phy_provider_mutex); | ||||
| 	of_node_put(args.np); | ||||
| 
 | ||||
|  | @ -622,6 +630,38 @@ struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, | |||
| } | ||||
| EXPORT_SYMBOL_GPL(devm_of_phy_get); | ||||
| 
 | ||||
| /**
 | ||||
|  * devm_of_phy_get_by_index() - lookup and obtain a reference to a phy by index. | ||||
|  * @dev: device that requests this phy | ||||
|  * @np: node containing the phy | ||||
|  * @index: index of the phy | ||||
|  * | ||||
|  * Gets the phy using _of_phy_get(), and associates a device with it using | ||||
|  * devres. On driver detach, release function is invoked on the devres data, | ||||
|  * then, devres data is freed. | ||||
|  * | ||||
|  */ | ||||
| struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np, | ||||
| 				     int index) | ||||
| { | ||||
| 	struct phy **ptr, *phy; | ||||
| 
 | ||||
| 	ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL); | ||||
| 	if (!ptr) | ||||
| 		return ERR_PTR(-ENOMEM); | ||||
| 
 | ||||
| 	phy = _of_phy_get(np, index); | ||||
| 	if (!IS_ERR(phy)) { | ||||
| 		*ptr = phy; | ||||
| 		devres_add(dev, ptr); | ||||
| 	} else { | ||||
| 		devres_free(ptr); | ||||
| 	} | ||||
| 
 | ||||
| 	return phy; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(devm_of_phy_get_by_index); | ||||
| 
 | ||||
| /**
 | ||||
|  * phy_create() - create a new phy | ||||
|  * @dev: device that is creating the new phy | ||||
|  | @ -651,16 +691,6 @@ struct phy *phy_create(struct device *dev, struct device_node *node, | |||
| 		goto free_phy; | ||||
| 	} | ||||
| 
 | ||||
| 	/* phy-supply */ | ||||
| 	phy->pwr = regulator_get_optional(dev, "phy"); | ||||
| 	if (IS_ERR(phy->pwr)) { | ||||
| 		if (PTR_ERR(phy->pwr) == -EPROBE_DEFER) { | ||||
| 			ret = -EPROBE_DEFER; | ||||
| 			goto free_ida; | ||||
| 		} | ||||
| 		phy->pwr = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	device_initialize(&phy->dev); | ||||
| 	mutex_init(&phy->mutex); | ||||
| 
 | ||||
|  | @ -674,6 +704,16 @@ struct phy *phy_create(struct device *dev, struct device_node *node, | |||
| 	if (ret) | ||||
| 		goto put_dev; | ||||
| 
 | ||||
| 	/* phy-supply */ | ||||
| 	phy->pwr = regulator_get_optional(&phy->dev, "phy"); | ||||
| 	if (IS_ERR(phy->pwr)) { | ||||
| 		ret = PTR_ERR(phy->pwr); | ||||
| 		if (ret == -EPROBE_DEFER) | ||||
| 			goto put_dev; | ||||
| 
 | ||||
| 		phy->pwr = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	ret = device_add(&phy->dev); | ||||
| 	if (ret) | ||||
| 		goto put_dev; | ||||
|  | @ -689,9 +729,6 @@ struct phy *phy_create(struct device *dev, struct device_node *node, | |||
| 	put_device(&phy->dev);  /* calls phy_release() which frees resources */ | ||||
| 	return ERR_PTR(ret); | ||||
| 
 | ||||
| free_ida: | ||||
| 	ida_simple_remove(&phy_ida, phy->id); | ||||
| 
 | ||||
| free_phy: | ||||
| 	kfree(phy); | ||||
| 	return ERR_PTR(ret); | ||||
|  |  | |||
|  | @ -367,7 +367,7 @@ static struct miphy28lp_pll_gen pcie_pll_gen[] = { | |||
| 
 | ||||
| static inline void miphy28lp_set_reset(struct miphy28lp_phy *miphy_phy) | ||||
| { | ||||
| 	void *base = miphy_phy->base; | ||||
| 	void __iomem *base = miphy_phy->base; | ||||
| 	u8 val; | ||||
| 
 | ||||
| 	/* Putting Macro in reset */ | ||||
|  | @ -391,7 +391,7 @@ static inline void miphy28lp_set_reset(struct miphy28lp_phy *miphy_phy) | |||
| static inline void miphy28lp_pll_calibration(struct miphy28lp_phy *miphy_phy, | ||||
| 		struct pll_ratio *pll_ratio) | ||||
| { | ||||
| 	void *base = miphy_phy->base; | ||||
| 	void __iomem *base = miphy_phy->base; | ||||
| 	u8 val; | ||||
| 
 | ||||
| 	/* Applying PLL Settings */ | ||||
|  | @ -1107,11 +1107,6 @@ static struct phy *miphy28lp_xlate(struct device *dev, | |||
| 	struct device_node *phynode = args->np; | ||||
| 	int ret, index = 0; | ||||
| 
 | ||||
| 	if (!of_device_is_available(phynode)) { | ||||
| 		dev_warn(dev, "Requested PHY is disabled\n"); | ||||
| 		return ERR_PTR(-ENODEV); | ||||
| 	} | ||||
| 
 | ||||
| 	if (args->args_count != 1) { | ||||
| 		dev_err(dev, "Invalid number of cells in 'phy' property\n"); | ||||
| 		return ERR_PTR(-EINVAL); | ||||
|  |  | |||
|  | @ -441,8 +441,8 @@ static int miphy365x_init(struct phy *phy) | |||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy, | ||||
| 		       int index) | ||||
| static int miphy365x_get_addr(struct device *dev, | ||||
| 		struct miphy365x_phy *miphy_phy, int index) | ||||
| { | ||||
| 	struct device_node *phynode = miphy_phy->phy->dev.of_node; | ||||
| 	const char *name; | ||||
|  | @ -476,11 +476,6 @@ static struct phy *miphy365x_xlate(struct device *dev, | |||
| 	struct device_node *phynode = args->np; | ||||
| 	int ret, index; | ||||
| 
 | ||||
| 	if (!of_device_is_available(phynode)) { | ||||
| 		dev_warn(dev, "Requested PHY is disabled\n"); | ||||
| 		return ERR_PTR(-ENODEV); | ||||
| 	} | ||||
| 
 | ||||
| 	if (args->args_count != 1) { | ||||
| 		dev_err(dev, "Invalid number of cells in 'phy' property\n"); | ||||
| 		return ERR_PTR(-EINVAL); | ||||
|  |  | |||
|  | @ -195,6 +195,7 @@ static struct phy_ops rcar_gen2_phy_ops = { | |||
| static const struct of_device_id rcar_gen2_phy_match_table[] = { | ||||
| 	{ .compatible = "renesas,usb-phy-r8a7790" }, | ||||
| 	{ .compatible = "renesas,usb-phy-r8a7791" }, | ||||
| 	{ .compatible = "renesas,usb-phy-r8a7794" }, | ||||
| 	{ } | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table); | ||||
|  | @ -206,11 +207,6 @@ static struct phy *rcar_gen2_phy_xlate(struct device *dev, | |||
| 	struct device_node *np = args->np; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (!of_device_is_available(np)) { | ||||
| 		dev_warn(dev, "Requested PHY is disabled\n"); | ||||
| 		return ERR_PTR(-ENODEV); | ||||
| 	} | ||||
| 
 | ||||
| 	drv = dev_get_drvdata(dev); | ||||
| 	if (!drv) | ||||
| 		return ERR_PTR(-EINVAL); | ||||
|  |  | |||
|  | @ -144,6 +144,16 @@ | |||
| #define PMBR1				0x0D | ||||
| #define GPIO_USB_4PIN_ULPI_2430C	(3 << 0) | ||||
| 
 | ||||
| /*
 | ||||
|  * If VBUS is valid or ID is ground, then we know a | ||||
|  * cable is present and we need to be runtime-enabled | ||||
|  */ | ||||
| static inline bool cable_present(enum omap_musb_vbus_id_status stat) | ||||
| { | ||||
| 	return stat == OMAP_MUSB_VBUS_VALID || | ||||
| 		stat == OMAP_MUSB_ID_GROUND; | ||||
| } | ||||
| 
 | ||||
| struct twl4030_usb { | ||||
| 	struct usb_phy		phy; | ||||
| 	struct device		*dev; | ||||
|  | @ -386,8 +396,6 @@ static int twl4030_usb_runtime_suspend(struct device *dev) | |||
| 	struct twl4030_usb *twl = dev_get_drvdata(dev); | ||||
| 
 | ||||
| 	dev_dbg(twl->dev, "%s\n", __func__); | ||||
| 	if (pm_runtime_suspended(dev)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	__twl4030_phy_power(twl, 0); | ||||
| 	regulator_disable(twl->usb1v5); | ||||
|  | @ -403,8 +411,6 @@ static int twl4030_usb_runtime_resume(struct device *dev) | |||
| 	int res; | ||||
| 
 | ||||
| 	dev_dbg(twl->dev, "%s\n", __func__); | ||||
| 	if (pm_runtime_active(dev)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	res = regulator_enable(twl->usb3v1); | ||||
| 	if (res) | ||||
|  | @ -536,8 +542,10 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) | |||
| 
 | ||||
| 	mutex_lock(&twl->lock); | ||||
| 	if (status >= 0 && status != twl->linkstat) { | ||||
| 		status_changed = | ||||
| 			cable_present(twl->linkstat) != | ||||
| 			cable_present(status); | ||||
| 		twl->linkstat = status; | ||||
| 		status_changed = true; | ||||
| 	} | ||||
| 	mutex_unlock(&twl->lock); | ||||
| 
 | ||||
|  | @ -553,15 +561,11 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) | |||
| 		 * USB_LINK_VBUS state.  musb_hdrc won't care until it | ||||
| 		 * starts to handle softconnect right. | ||||
| 		 */ | ||||
| 		if ((status == OMAP_MUSB_VBUS_VALID) || | ||||
| 		    (status == OMAP_MUSB_ID_GROUND)) { | ||||
| 			if (pm_runtime_suspended(twl->dev)) | ||||
| 				pm_runtime_get_sync(twl->dev); | ||||
| 		if (cable_present(status)) { | ||||
| 			pm_runtime_get_sync(twl->dev); | ||||
| 		} else { | ||||
| 			if (pm_runtime_active(twl->dev)) { | ||||
| 				pm_runtime_mark_last_busy(twl->dev); | ||||
| 				pm_runtime_put_autosuspend(twl->dev); | ||||
| 			} | ||||
| 			pm_runtime_mark_last_busy(twl->dev); | ||||
| 			pm_runtime_put_autosuspend(twl->dev); | ||||
| 		} | ||||
| 		omap_musb_mailbox(status); | ||||
| 	} | ||||
|  | @ -711,7 +715,6 @@ static int twl4030_usb_probe(struct platform_device *pdev) | |||
| 	pm_runtime_use_autosuspend(&pdev->dev); | ||||
| 	pm_runtime_set_autosuspend_delay(&pdev->dev, 2000); | ||||
| 	pm_runtime_enable(&pdev->dev); | ||||
| 	pm_runtime_get_sync(&pdev->dev); | ||||
| 
 | ||||
| 	/* Our job is to use irqs and status from the power module
 | ||||
| 	 * to keep the transceiver disabled when nothing's connected. | ||||
|  | @ -767,6 +770,9 @@ static int twl4030_usb_remove(struct platform_device *pdev) | |||
| 
 | ||||
| 	/* disable complete OTG block */ | ||||
| 	twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); | ||||
| 
 | ||||
| 	if (cable_present(twl->linkstat)) | ||||
| 		pm_runtime_put_noidle(twl->dev); | ||||
| 	pm_runtime_mark_last_busy(twl->dev); | ||||
| 	pm_runtime_put(twl->dev); | ||||
| 
 | ||||
|  |  | |||
|  | @ -88,15 +88,13 @@ static int ehci_platform_power_on(struct platform_device *dev) | |||
| 	} | ||||
| 
 | ||||
| 	for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { | ||||
| 		if (priv->phys[phy_num]) { | ||||
| 			ret = phy_init(priv->phys[phy_num]); | ||||
| 			if (ret) | ||||
| 				goto err_exit_phy; | ||||
| 			ret = phy_power_on(priv->phys[phy_num]); | ||||
| 			if (ret) { | ||||
| 				phy_exit(priv->phys[phy_num]); | ||||
| 				goto err_exit_phy; | ||||
| 			} | ||||
| 		ret = phy_init(priv->phys[phy_num]); | ||||
| 		if (ret) | ||||
| 			goto err_exit_phy; | ||||
| 		ret = phy_power_on(priv->phys[phy_num]); | ||||
| 		if (ret) { | ||||
| 			phy_exit(priv->phys[phy_num]); | ||||
| 			goto err_exit_phy; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | @ -104,10 +102,8 @@ static int ehci_platform_power_on(struct platform_device *dev) | |||
| 
 | ||||
| err_exit_phy: | ||||
| 	while (--phy_num >= 0) { | ||||
| 		if (priv->phys[phy_num]) { | ||||
| 			phy_power_off(priv->phys[phy_num]); | ||||
| 			phy_exit(priv->phys[phy_num]); | ||||
| 		} | ||||
| 		phy_power_off(priv->phys[phy_num]); | ||||
| 		phy_exit(priv->phys[phy_num]); | ||||
| 	} | ||||
| err_disable_clks: | ||||
| 	while (--clk >= 0) | ||||
|  | @ -123,10 +119,8 @@ static void ehci_platform_power_off(struct platform_device *dev) | |||
| 	int clk, phy_num; | ||||
| 
 | ||||
| 	for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { | ||||
| 		if (priv->phys[phy_num]) { | ||||
| 			phy_power_off(priv->phys[phy_num]); | ||||
| 			phy_exit(priv->phys[phy_num]); | ||||
| 		} | ||||
| 		phy_power_off(priv->phys[phy_num]); | ||||
| 		phy_exit(priv->phys[phy_num]); | ||||
| 	} | ||||
| 
 | ||||
| 	for (clk = EHCI_MAX_CLKS - 1; clk >= 0; clk--) | ||||
|  | @ -154,7 +148,6 @@ static int ehci_platform_probe(struct platform_device *dev) | |||
| 	struct usb_ehci_pdata *pdata = dev_get_platdata(&dev->dev); | ||||
| 	struct ehci_platform_priv *priv; | ||||
| 	struct ehci_hcd *ehci; | ||||
| 	const char *phy_name; | ||||
| 	int err, irq, phy_num, clk = 0; | ||||
| 
 | ||||
| 	if (usb_disabled()) | ||||
|  | @ -208,36 +201,22 @@ static int ehci_platform_probe(struct platform_device *dev) | |||
| 
 | ||||
| 		priv->num_phys = of_count_phandle_with_args(dev->dev.of_node, | ||||
| 				"phys", "#phy-cells"); | ||||
| 		priv->num_phys = priv->num_phys > 0 ? priv->num_phys : 1; | ||||
| 
 | ||||
| 		priv->phys = devm_kcalloc(&dev->dev, priv->num_phys, | ||||
| 				sizeof(struct phy *), GFP_KERNEL); | ||||
| 		if (!priv->phys) | ||||
| 			return -ENOMEM; | ||||
| 		if (priv->num_phys > 0) { | ||||
| 			priv->phys = devm_kcalloc(&dev->dev, priv->num_phys, | ||||
| 					    sizeof(struct phy *), GFP_KERNEL); | ||||
| 			if (!priv->phys) | ||||
| 				return -ENOMEM; | ||||
| 		} else | ||||
| 			priv->num_phys = 0; | ||||
| 
 | ||||
| 		for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { | ||||
| 				err = of_property_read_string_index( | ||||
| 						dev->dev.of_node, | ||||
| 						"phy-names", phy_num, | ||||
| 						&phy_name); | ||||
| 
 | ||||
| 				if (err < 0) { | ||||
| 					if (priv->num_phys > 1) { | ||||
| 						dev_err(&dev->dev, "phy-names not provided"); | ||||
| 						goto err_put_hcd; | ||||
| 					} else | ||||
| 						phy_name = "usb"; | ||||
| 				} | ||||
| 
 | ||||
| 				priv->phys[phy_num] = devm_phy_get(&dev->dev, | ||||
| 						phy_name); | ||||
| 				if (IS_ERR(priv->phys[phy_num])) { | ||||
| 					err = PTR_ERR(priv->phys[phy_num]); | ||||
| 					if ((priv->num_phys > 1) || | ||||
| 					    (err == -EPROBE_DEFER)) | ||||
| 						goto err_put_hcd; | ||||
| 					priv->phys[phy_num] = NULL; | ||||
| 				} | ||||
| 			priv->phys[phy_num] = devm_of_phy_get_by_index( | ||||
| 					&dev->dev, dev->dev.of_node, phy_num); | ||||
| 			if (IS_ERR(priv->phys[phy_num])) { | ||||
| 				err = PTR_ERR(priv->phys[phy_num]); | ||||
| 					goto err_put_hcd; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		for (clk = 0; clk < EHCI_MAX_CLKS; clk++) { | ||||
|  |  | |||
|  | @ -57,15 +57,13 @@ static int ohci_platform_power_on(struct platform_device *dev) | |||
| 	} | ||||
| 
 | ||||
| 	for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { | ||||
| 		if (priv->phys[phy_num]) { | ||||
| 			ret = phy_init(priv->phys[phy_num]); | ||||
| 			if (ret) | ||||
| 				goto err_exit_phy; | ||||
| 			ret = phy_power_on(priv->phys[phy_num]); | ||||
| 			if (ret) { | ||||
| 				phy_exit(priv->phys[phy_num]); | ||||
| 				goto err_exit_phy; | ||||
| 			} | ||||
| 		ret = phy_init(priv->phys[phy_num]); | ||||
| 		if (ret) | ||||
| 			goto err_exit_phy; | ||||
| 		ret = phy_power_on(priv->phys[phy_num]); | ||||
| 		if (ret) { | ||||
| 			phy_exit(priv->phys[phy_num]); | ||||
| 			goto err_exit_phy; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | @ -73,10 +71,8 @@ static int ohci_platform_power_on(struct platform_device *dev) | |||
| 
 | ||||
| err_exit_phy: | ||||
| 	while (--phy_num >= 0) { | ||||
| 		if (priv->phys[phy_num]) { | ||||
| 			phy_power_off(priv->phys[phy_num]); | ||||
| 			phy_exit(priv->phys[phy_num]); | ||||
| 		} | ||||
| 		phy_power_off(priv->phys[phy_num]); | ||||
| 		phy_exit(priv->phys[phy_num]); | ||||
| 	} | ||||
| err_disable_clks: | ||||
| 	while (--clk >= 0) | ||||
|  | @ -92,10 +88,8 @@ static void ohci_platform_power_off(struct platform_device *dev) | |||
| 	int clk, phy_num; | ||||
| 
 | ||||
| 	for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { | ||||
| 		if (priv->phys[phy_num]) { | ||||
| 			phy_power_off(priv->phys[phy_num]); | ||||
| 			phy_exit(priv->phys[phy_num]); | ||||
| 		} | ||||
| 		phy_power_off(priv->phys[phy_num]); | ||||
| 		phy_exit(priv->phys[phy_num]); | ||||
| 	} | ||||
| 
 | ||||
| 	for (clk = OHCI_MAX_CLKS - 1; clk >= 0; clk--) | ||||
|  | @ -123,7 +117,6 @@ static int ohci_platform_probe(struct platform_device *dev) | |||
| 	struct usb_ohci_pdata *pdata = dev_get_platdata(&dev->dev); | ||||
| 	struct ohci_platform_priv *priv; | ||||
| 	struct ohci_hcd *ohci; | ||||
| 	const char *phy_name; | ||||
| 	int err, irq, phy_num, clk = 0; | ||||
| 
 | ||||
| 	if (usb_disabled()) | ||||
|  | @ -174,36 +167,22 @@ static int ohci_platform_probe(struct platform_device *dev) | |||
| 
 | ||||
| 		priv->num_phys = of_count_phandle_with_args(dev->dev.of_node, | ||||
| 				"phys", "#phy-cells"); | ||||
| 		priv->num_phys = priv->num_phys > 0 ? priv->num_phys : 1; | ||||
| 
 | ||||
| 		priv->phys = devm_kcalloc(&dev->dev, priv->num_phys, | ||||
| 				sizeof(struct phy *), GFP_KERNEL); | ||||
| 		if (!priv->phys) | ||||
| 			return -ENOMEM; | ||||
| 		if (priv->num_phys > 0) { | ||||
| 			priv->phys = devm_kcalloc(&dev->dev, priv->num_phys, | ||||
| 					    sizeof(struct phy *), GFP_KERNEL); | ||||
| 			if (!priv->phys) | ||||
| 				return -ENOMEM; | ||||
| 		} else | ||||
| 			priv->num_phys = 0; | ||||
| 
 | ||||
| 		for (phy_num = 0; phy_num < priv->num_phys; phy_num++) { | ||||
| 				err = of_property_read_string_index( | ||||
| 						dev->dev.of_node, | ||||
| 						"phy-names", phy_num, | ||||
| 						&phy_name); | ||||
| 
 | ||||
| 				if (err < 0) { | ||||
| 					if (priv->num_phys > 1) { | ||||
| 						dev_err(&dev->dev, "phy-names not provided"); | ||||
| 						goto err_put_hcd; | ||||
| 					} else | ||||
| 						phy_name = "usb"; | ||||
| 				} | ||||
| 
 | ||||
| 				priv->phys[phy_num] = devm_phy_get(&dev->dev, | ||||
| 						phy_name); | ||||
| 				if (IS_ERR(priv->phys[phy_num])) { | ||||
| 					err = PTR_ERR(priv->phys[phy_num]); | ||||
| 					if ((priv->num_phys > 1) || | ||||
| 					    (err == -EPROBE_DEFER)) | ||||
| 						goto err_put_hcd; | ||||
| 					priv->phys[phy_num] = NULL; | ||||
| 				} | ||||
| 			priv->phys[phy_num] = devm_of_phy_get_by_index( | ||||
| 					&dev->dev, dev->dev.of_node, phy_num); | ||||
| 			if (IS_ERR(priv->phys[phy_num])) { | ||||
| 				err = PTR_ERR(priv->phys[phy_num]); | ||||
| 				goto err_put_hcd; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		for (clk = 0; clk < OHCI_MAX_CLKS; clk++) { | ||||
|  |  | |||
|  | @ -133,6 +133,8 @@ struct phy *devm_phy_get(struct device *dev, const char *string); | |||
| struct phy *devm_phy_optional_get(struct device *dev, const char *string); | ||||
| struct phy *devm_of_phy_get(struct device *dev, struct device_node *np, | ||||
| 			    const char *con_id); | ||||
| struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np, | ||||
| 				     int index); | ||||
| void phy_put(struct phy *phy); | ||||
| void devm_phy_put(struct device *dev, struct phy *phy); | ||||
| struct phy *of_phy_get(struct device_node *np, const char *con_id); | ||||
|  | @ -261,6 +263,13 @@ static inline struct phy *devm_of_phy_get(struct device *dev, | |||
| 	return ERR_PTR(-ENOSYS); | ||||
| } | ||||
| 
 | ||||
| static inline struct phy *devm_of_phy_get_by_index(struct device *dev, | ||||
| 						   struct device_node *np, | ||||
| 						   int index) | ||||
| { | ||||
| 	return ERR_PTR(-ENOSYS); | ||||
| } | ||||
| 
 | ||||
| static inline void phy_put(struct phy *phy) | ||||
| { | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Greg Kroah-Hartman
						Greg Kroah-Hartman