Skip to content

Commit 8ecef00

Browse files
uliFelipe Balbi
authored andcommitted
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 <[email protected]> Signed-off-by: Felipe Balbi <[email protected]>
1 parent f226708 commit 8ecef00

File tree

6 files changed

+151
-6
lines changed

6 files changed

+151
-6
lines changed

drivers/usb/renesas_usbhs/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs.o
66

7-
renesas_usbhs-y := common.o mod.o pipe.o fifo.o
7+
renesas_usbhs-y := common.o mod.o pipe.o fifo.o rcar2.o
88

99
ifneq ($(CONFIG_USB_RENESAS_USBHS_HCD),)
1010
renesas_usbhs-y += mod_host.o

drivers/usb/renesas_usbhs/common.c

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
*
1616
*/
1717
#include <linux/err.h>
18+
#include <linux/gpio.h>
1819
#include <linux/io.h>
1920
#include <linux/module.h>
2021
#include <linux/pm_runtime.h>
2122
#include <linux/slab.h>
2223
#include <linux/sysfs.h>
2324
#include "common.h"
25+
#include "rcar2.h"
2426

2527
/*
2628
* image of renesas_usbhs
@@ -284,6 +286,8 @@ static void usbhsc_set_buswait(struct usbhs_priv *priv)
284286
/*
285287
* platform default param
286288
*/
289+
290+
/* commonly used on old SH-Mobile SoCs */
287291
static u32 usbhsc_default_pipe_type[] = {
288292
USB_ENDPOINT_XFER_CONTROL,
289293
USB_ENDPOINT_XFER_ISOC,
@@ -297,6 +301,26 @@ static u32 usbhsc_default_pipe_type[] = {
297301
USB_ENDPOINT_XFER_INT,
298302
};
299303

304+
/* commonly used on newer SH-Mobile and R-Car SoCs */
305+
static u32 usbhsc_new_pipe_type[] = {
306+
USB_ENDPOINT_XFER_CONTROL,
307+
USB_ENDPOINT_XFER_ISOC,
308+
USB_ENDPOINT_XFER_ISOC,
309+
USB_ENDPOINT_XFER_BULK,
310+
USB_ENDPOINT_XFER_BULK,
311+
USB_ENDPOINT_XFER_BULK,
312+
USB_ENDPOINT_XFER_INT,
313+
USB_ENDPOINT_XFER_INT,
314+
USB_ENDPOINT_XFER_INT,
315+
USB_ENDPOINT_XFER_BULK,
316+
USB_ENDPOINT_XFER_BULK,
317+
USB_ENDPOINT_XFER_BULK,
318+
USB_ENDPOINT_XFER_BULK,
319+
USB_ENDPOINT_XFER_BULK,
320+
USB_ENDPOINT_XFER_BULK,
321+
USB_ENDPOINT_XFER_BULK,
322+
};
323+
300324
/*
301325
* power control
302326
*/
@@ -423,8 +447,7 @@ static int usbhs_probe(struct platform_device *pdev)
423447
int ret;
424448

425449
/* check platform information */
426-
if (!info ||
427-
!info->platform_callback.get_id) {
450+
if (!info) {
428451
dev_err(&pdev->dev, "no platform information\n");
429452
return -EINVAL;
430453
}
@@ -451,13 +474,32 @@ static int usbhs_probe(struct platform_device *pdev)
451474
/*
452475
* care platform info
453476
*/
454-
memcpy(&priv->pfunc,
455-
&info->platform_callback,
456-
sizeof(struct renesas_usbhs_platform_callback));
477+
457478
memcpy(&priv->dparam,
458479
&info->driver_param,
459480
sizeof(struct renesas_usbhs_driver_param));
460481

482+
switch (priv->dparam.type) {
483+
case USBHS_TYPE_R8A7790:
484+
case USBHS_TYPE_R8A7791:
485+
priv->pfunc = usbhs_rcar2_ops;
486+
if (!priv->dparam.pipe_type) {
487+
priv->dparam.pipe_type = usbhsc_new_pipe_type;
488+
priv->dparam.pipe_size =
489+
ARRAY_SIZE(usbhsc_new_pipe_type);
490+
}
491+
break;
492+
default:
493+
if (!info->platform_callback.get_id) {
494+
dev_err(&pdev->dev, "no platform callbacks");
495+
return -EINVAL;
496+
}
497+
memcpy(&priv->pfunc,
498+
&info->platform_callback,
499+
sizeof(struct renesas_usbhs_platform_callback));
500+
break;
501+
}
502+
461503
/* set driver callback functions for platform */
462504
dfunc = &info->driver_callback;
463505
dfunc->notify_hotplug = usbhsc_drvcllbck_notify_hotplug;
@@ -507,6 +549,20 @@ static int usbhs_probe(struct platform_device *pdev)
507549
*/
508550
usbhs_sys_clock_ctrl(priv, 0);
509551

552+
/* check GPIO determining if USB function should be enabled */
553+
if (priv->dparam.enable_gpio) {
554+
gpio_request_one(priv->dparam.enable_gpio, GPIOF_IN, NULL);
555+
ret = !gpio_get_value(priv->dparam.enable_gpio);
556+
gpio_free(priv->dparam.enable_gpio);
557+
if (ret) {
558+
dev_warn(&pdev->dev,
559+
"USB function not selected (GPIO %d)\n",
560+
priv->dparam.enable_gpio);
561+
ret = -ENOTSUPP;
562+
goto probe_end_mod_exit;
563+
}
564+
}
565+
510566
/*
511567
* platform call
512568
*

drivers/usb/renesas_usbhs/common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,8 @@ struct usbhs_priv {
268268
* fifo control
269269
*/
270270
struct usbhs_fifo_info fifo_info;
271+
272+
struct usb_phy *phy;
271273
};
272274

273275
/*

drivers/usb/renesas_usbhs/rcar2.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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/platform_data/gpio-rcar.h>
16+
#include <linux/usb/phy.h>
17+
#include "common.h"
18+
#include "rcar2.h"
19+
20+
static int usbhs_rcar2_hardware_init(struct platform_device *pdev)
21+
{
22+
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
23+
struct usb_phy *phy;
24+
25+
phy = usb_get_phy_dev(&pdev->dev, 0);
26+
if (IS_ERR(phy))
27+
return PTR_ERR(phy);
28+
29+
priv->phy = phy;
30+
return 0;
31+
}
32+
33+
static int usbhs_rcar2_hardware_exit(struct platform_device *pdev)
34+
{
35+
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
36+
37+
if (!priv->phy)
38+
return 0;
39+
40+
usb_put_phy(priv->phy);
41+
priv->phy = NULL;
42+
43+
return 0;
44+
}
45+
46+
static int usbhs_rcar2_power_ctrl(struct platform_device *pdev,
47+
void __iomem *base, int enable)
48+
{
49+
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
50+
51+
if (!priv->phy)
52+
return -ENODEV;
53+
54+
if (enable) {
55+
int retval = usb_phy_init(priv->phy);
56+
57+
if (!retval)
58+
retval = usb_phy_set_suspend(priv->phy, 0);
59+
return retval;
60+
}
61+
62+
usb_phy_set_suspend(priv->phy, 1);
63+
usb_phy_shutdown(priv->phy);
64+
return 0;
65+
}
66+
67+
static int usbhs_rcar2_get_id(struct platform_device *pdev)
68+
{
69+
return USBHS_GADGET;
70+
}
71+
72+
const struct renesas_usbhs_platform_callback usbhs_rcar2_ops = {
73+
.hardware_init = usbhs_rcar2_hardware_init,
74+
.hardware_exit = usbhs_rcar2_hardware_exit,
75+
.power_ctrl = usbhs_rcar2_power_ctrl,
76+
.get_id = usbhs_rcar2_get_id,
77+
};

drivers/usb/renesas_usbhs/rcar2.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#include "common.h"
2+
3+
extern const struct renesas_usbhs_platform_callback
4+
usbhs_rcar2_ops;

include/linux/usb/renesas_usbhs.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,19 @@ struct renesas_usbhs_driver_param {
153153
*/
154154
int pio_dma_border; /* default is 64byte */
155155

156+
u32 type;
157+
u32 enable_gpio;
158+
156159
/*
157160
* option:
158161
*/
159162
u32 has_otg:1; /* for controlling PWEN/EXTLP */
160163
u32 has_sudmac:1; /* for SUDMAC */
161164
};
162165

166+
#define USBHS_TYPE_R8A7790 1
167+
#define USBHS_TYPE_R8A7791 2
168+
163169
/*
164170
* option:
165171
*

0 commit comments

Comments
 (0)