1 /* 2 * Renesas USB driver R-Car Gen. 2 initialization and power control 3 * 4 * Copyright (C) 2014 Ulrich Hecht 5 * 6 * This program is distributed in the hope that it will be useful, 7 * but WITHOUT ANY WARRANTY; without even the implied warranty of 8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 * GNU General Public License for more details. 10 * 11 */ 12 13 #include <linux/gpio.h> 14 #include <linux/of_gpio.h> 15 #include <linux/phy/phy.h> 16 #include <linux/usb/phy.h> 17 #include "common.h" 18 #include "rcar2.h" 19 20 static int usbhs_rcar2_hardware_init(struct platform_device *pdev) 21 { 22 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 23 24 if (IS_ENABLED(CONFIG_GENERIC_PHY)) { 25 struct phy *phy = phy_get(&pdev->dev, "usb"); 26 27 if (IS_ERR(phy)) 28 return PTR_ERR(phy); 29 30 priv->phy = phy; 31 return 0; 32 } 33 34 if (IS_ENABLED(CONFIG_USB_PHY)) { 35 struct usb_phy *usb_phy = usb_get_phy_dev(&pdev->dev, 0); 36 37 if (IS_ERR(usb_phy)) 38 return PTR_ERR(usb_phy); 39 40 priv->usb_phy = usb_phy; 41 return 0; 42 } 43 44 return -ENXIO; 45 } 46 47 static int usbhs_rcar2_hardware_exit(struct platform_device *pdev) 48 { 49 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 50 51 if (priv->phy) { 52 phy_put(priv->phy); 53 priv->phy = NULL; 54 } 55 56 if (priv->usb_phy) { 57 usb_put_phy(priv->usb_phy); 58 priv->usb_phy = NULL; 59 } 60 61 return 0; 62 } 63 64 static int usbhs_rcar2_power_ctrl(struct platform_device *pdev, 65 void __iomem *base, int enable) 66 { 67 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 68 int retval = -ENODEV; 69 70 if (priv->phy) { 71 if (enable) { 72 retval = phy_init(priv->phy); 73 74 if (!retval) 75 retval = phy_power_on(priv->phy); 76 } else { 77 phy_power_off(priv->phy); 78 phy_exit(priv->phy); 79 retval = 0; 80 } 81 } 82 83 if (priv->usb_phy) { 84 if (enable) { 85 retval = usb_phy_init(priv->usb_phy); 86 87 if (!retval) 88 retval = usb_phy_set_suspend(priv->usb_phy, 0); 89 } else { 90 usb_phy_set_suspend(priv->usb_phy, 1); 91 usb_phy_shutdown(priv->usb_phy); 92 retval = 0; 93 } 94 } 95 96 return retval; 97 } 98 99 static int usbhs_rcar2_get_id(struct platform_device *pdev) 100 { 101 return USBHS_GADGET; 102 } 103 104 const struct renesas_usbhs_platform_callback usbhs_rcar2_ops = { 105 .hardware_init = usbhs_rcar2_hardware_init, 106 .hardware_exit = usbhs_rcar2_hardware_exit, 107 .power_ctrl = usbhs_rcar2_power_ctrl, 108 .get_id = usbhs_rcar2_get_id, 109 }; 110