linux/drivers/usb/renesas_usbhs/rcar2.c
<<
>>
Prefs
   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
  20static 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
  47static 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
  64static 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
  99static int usbhs_rcar2_get_id(struct platform_device *pdev)
 100{
 101        return USBHS_GADGET;
 102}
 103
 104const 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