usb: renesas_usbhs: add R-Car Gen. 2 init and power control
In preparation for DT conversion to reduce reliance on platform device callbacks. Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
f2267089ea
commit
8ecef00fe1
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs.o
|
obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs.o
|
||||||
|
|
||||||
renesas_usbhs-y := common.o mod.o pipe.o fifo.o
|
renesas_usbhs-y := common.o mod.o pipe.o fifo.o rcar2.o
|
||||||
|
|
||||||
ifneq ($(CONFIG_USB_RENESAS_USBHS_HCD),)
|
ifneq ($(CONFIG_USB_RENESAS_USBHS_HCD),)
|
||||||
renesas_usbhs-y += mod_host.o
|
renesas_usbhs-y += mod_host.o
|
||||||
|
@ -15,12 +15,14 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/sysfs.h>
|
#include <linux/sysfs.h>
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "rcar2.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* image of renesas_usbhs
|
* image of renesas_usbhs
|
||||||
@ -284,6 +286,8 @@ static void usbhsc_set_buswait(struct usbhs_priv *priv)
|
|||||||
/*
|
/*
|
||||||
* platform default param
|
* platform default param
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* commonly used on old SH-Mobile SoCs */
|
||||||
static u32 usbhsc_default_pipe_type[] = {
|
static u32 usbhsc_default_pipe_type[] = {
|
||||||
USB_ENDPOINT_XFER_CONTROL,
|
USB_ENDPOINT_XFER_CONTROL,
|
||||||
USB_ENDPOINT_XFER_ISOC,
|
USB_ENDPOINT_XFER_ISOC,
|
||||||
@ -297,6 +301,26 @@ static u32 usbhsc_default_pipe_type[] = {
|
|||||||
USB_ENDPOINT_XFER_INT,
|
USB_ENDPOINT_XFER_INT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* commonly used on newer SH-Mobile and R-Car SoCs */
|
||||||
|
static u32 usbhsc_new_pipe_type[] = {
|
||||||
|
USB_ENDPOINT_XFER_CONTROL,
|
||||||
|
USB_ENDPOINT_XFER_ISOC,
|
||||||
|
USB_ENDPOINT_XFER_ISOC,
|
||||||
|
USB_ENDPOINT_XFER_BULK,
|
||||||
|
USB_ENDPOINT_XFER_BULK,
|
||||||
|
USB_ENDPOINT_XFER_BULK,
|
||||||
|
USB_ENDPOINT_XFER_INT,
|
||||||
|
USB_ENDPOINT_XFER_INT,
|
||||||
|
USB_ENDPOINT_XFER_INT,
|
||||||
|
USB_ENDPOINT_XFER_BULK,
|
||||||
|
USB_ENDPOINT_XFER_BULK,
|
||||||
|
USB_ENDPOINT_XFER_BULK,
|
||||||
|
USB_ENDPOINT_XFER_BULK,
|
||||||
|
USB_ENDPOINT_XFER_BULK,
|
||||||
|
USB_ENDPOINT_XFER_BULK,
|
||||||
|
USB_ENDPOINT_XFER_BULK,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* power control
|
* power control
|
||||||
*/
|
*/
|
||||||
@ -423,8 +447,7 @@ static int usbhs_probe(struct platform_device *pdev)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* check platform information */
|
/* check platform information */
|
||||||
if (!info ||
|
if (!info) {
|
||||||
!info->platform_callback.get_id) {
|
|
||||||
dev_err(&pdev->dev, "no platform information\n");
|
dev_err(&pdev->dev, "no platform information\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -451,13 +474,32 @@ static int usbhs_probe(struct platform_device *pdev)
|
|||||||
/*
|
/*
|
||||||
* care platform info
|
* care platform info
|
||||||
*/
|
*/
|
||||||
memcpy(&priv->pfunc,
|
|
||||||
&info->platform_callback,
|
|
||||||
sizeof(struct renesas_usbhs_platform_callback));
|
|
||||||
memcpy(&priv->dparam,
|
memcpy(&priv->dparam,
|
||||||
&info->driver_param,
|
&info->driver_param,
|
||||||
sizeof(struct renesas_usbhs_driver_param));
|
sizeof(struct renesas_usbhs_driver_param));
|
||||||
|
|
||||||
|
switch (priv->dparam.type) {
|
||||||
|
case USBHS_TYPE_R8A7790:
|
||||||
|
case USBHS_TYPE_R8A7791:
|
||||||
|
priv->pfunc = usbhs_rcar2_ops;
|
||||||
|
if (!priv->dparam.pipe_type) {
|
||||||
|
priv->dparam.pipe_type = usbhsc_new_pipe_type;
|
||||||
|
priv->dparam.pipe_size =
|
||||||
|
ARRAY_SIZE(usbhsc_new_pipe_type);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!info->platform_callback.get_id) {
|
||||||
|
dev_err(&pdev->dev, "no platform callbacks");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
memcpy(&priv->pfunc,
|
||||||
|
&info->platform_callback,
|
||||||
|
sizeof(struct renesas_usbhs_platform_callback));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* set driver callback functions for platform */
|
/* set driver callback functions for platform */
|
||||||
dfunc = &info->driver_callback;
|
dfunc = &info->driver_callback;
|
||||||
dfunc->notify_hotplug = usbhsc_drvcllbck_notify_hotplug;
|
dfunc->notify_hotplug = usbhsc_drvcllbck_notify_hotplug;
|
||||||
@ -507,6 +549,20 @@ static int usbhs_probe(struct platform_device *pdev)
|
|||||||
*/
|
*/
|
||||||
usbhs_sys_clock_ctrl(priv, 0);
|
usbhs_sys_clock_ctrl(priv, 0);
|
||||||
|
|
||||||
|
/* check GPIO determining if USB function should be enabled */
|
||||||
|
if (priv->dparam.enable_gpio) {
|
||||||
|
gpio_request_one(priv->dparam.enable_gpio, GPIOF_IN, NULL);
|
||||||
|
ret = !gpio_get_value(priv->dparam.enable_gpio);
|
||||||
|
gpio_free(priv->dparam.enable_gpio);
|
||||||
|
if (ret) {
|
||||||
|
dev_warn(&pdev->dev,
|
||||||
|
"USB function not selected (GPIO %d)\n",
|
||||||
|
priv->dparam.enable_gpio);
|
||||||
|
ret = -ENOTSUPP;
|
||||||
|
goto probe_end_mod_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* platform call
|
* platform call
|
||||||
*
|
*
|
||||||
|
@ -268,6 +268,8 @@ struct usbhs_priv {
|
|||||||
* fifo control
|
* fifo control
|
||||||
*/
|
*/
|
||||||
struct usbhs_fifo_info fifo_info;
|
struct usbhs_fifo_info fifo_info;
|
||||||
|
|
||||||
|
struct usb_phy *phy;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
77
drivers/usb/renesas_usbhs/rcar2.c
Normal file
77
drivers/usb/renesas_usbhs/rcar2.c
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Renesas USB driver R-Car Gen. 2 initialization and power control
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Ulrich Hecht
|
||||||
|
*
|
||||||
|
* 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/gpio.h>
|
||||||
|
#include <linux/of_gpio.h>
|
||||||
|
#include <linux/platform_data/gpio-rcar.h>
|
||||||
|
#include <linux/usb/phy.h>
|
||||||
|
#include "common.h"
|
||||||
|
#include "rcar2.h"
|
||||||
|
|
||||||
|
static int usbhs_rcar2_hardware_init(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
|
||||||
|
struct usb_phy *phy;
|
||||||
|
|
||||||
|
phy = usb_get_phy_dev(&pdev->dev, 0);
|
||||||
|
if (IS_ERR(phy))
|
||||||
|
return PTR_ERR(phy);
|
||||||
|
|
||||||
|
priv->phy = phy;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbhs_rcar2_hardware_exit(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
|
||||||
|
|
||||||
|
if (!priv->phy)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
usb_put_phy(priv->phy);
|
||||||
|
priv->phy = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbhs_rcar2_power_ctrl(struct platform_device *pdev,
|
||||||
|
void __iomem *base, int enable)
|
||||||
|
{
|
||||||
|
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
|
||||||
|
|
||||||
|
if (!priv->phy)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
int retval = usb_phy_init(priv->phy);
|
||||||
|
|
||||||
|
if (!retval)
|
||||||
|
retval = usb_phy_set_suspend(priv->phy, 0);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_phy_set_suspend(priv->phy, 1);
|
||||||
|
usb_phy_shutdown(priv->phy);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usbhs_rcar2_get_id(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
return USBHS_GADGET;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct renesas_usbhs_platform_callback usbhs_rcar2_ops = {
|
||||||
|
.hardware_init = usbhs_rcar2_hardware_init,
|
||||||
|
.hardware_exit = usbhs_rcar2_hardware_exit,
|
||||||
|
.power_ctrl = usbhs_rcar2_power_ctrl,
|
||||||
|
.get_id = usbhs_rcar2_get_id,
|
||||||
|
};
|
4
drivers/usb/renesas_usbhs/rcar2.h
Normal file
4
drivers/usb/renesas_usbhs/rcar2.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
extern const struct renesas_usbhs_platform_callback
|
||||||
|
usbhs_rcar2_ops;
|
@ -153,6 +153,9 @@ struct renesas_usbhs_driver_param {
|
|||||||
*/
|
*/
|
||||||
int pio_dma_border; /* default is 64byte */
|
int pio_dma_border; /* default is 64byte */
|
||||||
|
|
||||||
|
u32 type;
|
||||||
|
u32 enable_gpio;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* option:
|
* option:
|
||||||
*/
|
*/
|
||||||
@ -160,6 +163,9 @@ struct renesas_usbhs_driver_param {
|
|||||||
u32 has_sudmac:1; /* for SUDMAC */
|
u32 has_sudmac:1; /* for SUDMAC */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define USBHS_TYPE_R8A7790 1
|
||||||
|
#define USBHS_TYPE_R8A7791 2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* option:
|
* option:
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user