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 21static 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 48static 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 65static 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 100static int usbhs_rcar2_get_id(struct platform_device *pdev) 101{ 102 return USBHS_GADGET; 103} 104 105const 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