Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8ecef00f authored by Ulrich Hecht's avatar Ulrich Hecht Committed by Felipe Balbi
Browse files

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: default avatarUlrich Hecht <ulrich.hecht+renesas@gmail.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent f2267089
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@

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),)
	renesas_usbhs-y		+= mod_host.o
+61 −5
Original line number Diff line number Diff line
@@ -15,12 +15,14 @@
 *
 */
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include "common.h"
#include "rcar2.h"

/*
 *		image of renesas_usbhs
@@ -284,6 +286,8 @@ static void usbhsc_set_buswait(struct usbhs_priv *priv)
/*
 *		platform default param
 */

/* commonly used on old SH-Mobile SoCs */
static u32 usbhsc_default_pipe_type[] = {
		USB_ENDPOINT_XFER_CONTROL,
		USB_ENDPOINT_XFER_ISOC,
@@ -297,6 +301,26 @@ static u32 usbhsc_default_pipe_type[] = {
		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
 */
@@ -423,8 +447,7 @@ static int usbhs_probe(struct platform_device *pdev)
	int ret;

	/* check platform information */
	if (!info ||
	    !info->platform_callback.get_id) {
	if (!info) {
		dev_err(&pdev->dev, "no platform information\n");
		return -EINVAL;
	}
@@ -451,13 +474,32 @@ static int usbhs_probe(struct platform_device *pdev)
	/*
	 * care platform info
	 */
	memcpy(&priv->pfunc,
	       &info->platform_callback,
	       sizeof(struct renesas_usbhs_platform_callback));

	memcpy(&priv->dparam,
	       &info->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 */
	dfunc			= &info->driver_callback;
	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);

	/* 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
	 *
+2 −0
Original line number Diff line number Diff line
@@ -268,6 +268,8 @@ struct usbhs_priv {
	 * fifo control
	 */
	struct usbhs_fifo_info fifo_info;

	struct usb_phy *phy;
};

/*
+77 −0
Original line number Diff line number Diff line
/*
 * 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 −0
Original line number Diff line number Diff line
#include "common.h"

extern const struct renesas_usbhs_platform_callback
	usbhs_rcar2_ops;
Loading