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/platform_data/gpio-rcar.h> 17 #include <linux/usb/phy.h> 18 #include "common.h" 19 #include "rcar2.h" 20 21 static int usbhs_rcar2_hardware_init(struct platform_device *pdev) 22 { 23 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 24 25 if (IS_ENABLED(CONFIG_GENERIC_PHY)) { 26 struct phy *phy = phy_get(&pdev->dev, "usb"); 27 28 if (IS_ERR(phy)) 29 return PTR_ERR(phy); 30 31 priv->phy = phy; 32 return 0; 33 } 34 35 if (IS_ENABLED(CONFIG_USB_PHY)) { 36 struct usb_phy *usb_phy = usb_get_phy_dev(&pdev->dev, 0); 37 38 if (IS_ERR(usb_phy)) 39 return PTR_ERR(usb_phy); 40 41 priv->usb_phy = usb_phy; 42 return 0; 43 } 44 45 return -ENXIO; 46 } 47 48 static int usbhs_rcar2_hardware_exit(struct platform_device *pdev) 49 { 50 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 51 52 if (priv->phy) { 53 phy_put(priv->phy); 54 priv->phy = NULL; 55 } 56 57 if (priv->usb_phy) { 58 usb_put_phy(priv->usb_phy); 59 priv->usb_phy = NULL; 60 } 61 62 return 0; 63 } 64 65 static int usbhs_rcar2_power_ctrl(struct platform_device *pdev, 66 void __iomem *base, int enable) 67 { 68 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev); 69 int retval = -ENODEV; 70 71 if (priv->phy) { 72 if (enable) { 73 retval = phy_init(priv->phy); 74 75 if (!retval) 76 retval = phy_power_on(priv->phy); 77 } else { 78 phy_power_off(priv->phy); 79 phy_exit(priv->phy); 80 retval = 0; 81 } 82 } 83 84 if (priv->usb_phy) { 85 if (enable) { 86 retval = usb_phy_init(priv->usb_phy); 87 88 if (!retval) 89 retval = usb_phy_set_suspend(priv->usb_phy, 0); 90 } else { 91 usb_phy_set_suspend(priv->usb_phy, 1); 92 usb_phy_shutdown(priv->usb_phy); 93 retval = 0; 94 } 95 } 96 97 return retval; 98 } 99 100 static int usbhs_rcar2_get_id(struct platform_device *pdev) 101 { 102 return USBHS_GADGET; 103 } 104 105 const struct renesas_usbhs_platform_callback usbhs_rcar2_ops = { 106 .hardware_init = usbhs_rcar2_hardware_init, 107 .hardware_exit = usbhs_rcar2_hardware_exit, 108 .power_ctrl = usbhs_rcar2_power_ctrl, 109 .get_id = usbhs_rcar2_get_id, 110 }; 111