2 * Renesas R-Car Gen2 USB phy driver
4 * Copyright (C) 2013 Renesas Solutions Corp.
5 * Copyright (C) 2013 Cogent Embedded, Inc.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/clk.h>
13 #include <linux/delay.h>
15 #include <linux/module.h>
16 #include <linux/platform_data/usb-rcar-gen2-phy.h>
17 #include <linux/platform_device.h>
18 #include <linux/spinlock.h>
19 #include <linux/usb/otg.h>
21 struct rcar_gen2_usb_phy_priv
{
30 #define usb_phy_to_priv(p) container_of(p, struct rcar_gen2_usb_phy_priv, phy)
32 /* Low Power Status register */
33 #define USBHS_LPSTS_REG 0x02
34 #define USBHS_LPSTS_SUSPM (1 << 14)
36 /* USB General control register */
37 #define USBHS_UGCTRL_REG 0x80
38 #define USBHS_UGCTRL_CONNECT (1 << 2)
39 #define USBHS_UGCTRL_PLLRESET (1 << 0)
41 /* USB General control register 2 */
42 #define USBHS_UGCTRL2_REG 0x84
43 #define USBHS_UGCTRL2_USB0_PCI (1 << 4)
44 #define USBHS_UGCTRL2_USB0_HS (3 << 4)
45 #define USBHS_UGCTRL2_USB2_PCI (0 << 31)
46 #define USBHS_UGCTRL2_USB2_SS (1 << 31)
48 /* USB General status register */
49 #define USBHS_UGSTS_REG 0x88
50 #define USBHS_UGSTS_LOCK (3 << 8)
52 /* Enable USBHS internal phy */
53 static int __rcar_gen2_usbhs_phy_enable(void __iomem
*base
)
58 /* USBHS PHY power on */
59 val
= ioread32(base
+ USBHS_UGCTRL_REG
);
60 val
&= ~USBHS_UGCTRL_PLLRESET
;
61 iowrite32(val
, base
+ USBHS_UGCTRL_REG
);
63 val
= ioread16(base
+ USBHS_LPSTS_REG
);
64 val
|= USBHS_LPSTS_SUSPM
;
65 iowrite16(val
, base
+ USBHS_LPSTS_REG
);
67 for (i
= 0; i
< 20; i
++) {
68 val
= ioread32(base
+ USBHS_UGSTS_REG
);
69 if ((val
& USBHS_UGSTS_LOCK
) == USBHS_UGSTS_LOCK
) {
70 val
= ioread32(base
+ USBHS_UGCTRL_REG
);
71 val
|= USBHS_UGCTRL_CONNECT
;
72 iowrite32(val
, base
+ USBHS_UGCTRL_REG
);
78 /* Timed out waiting for the PLL lock */
82 /* Disable USBHS internal phy */
83 static int __rcar_gen2_usbhs_phy_disable(void __iomem
*base
)
87 /* USBHS PHY power off */
88 val
= ioread32(base
+ USBHS_UGCTRL_REG
);
89 val
&= ~USBHS_UGCTRL_CONNECT
;
90 iowrite32(val
, base
+ USBHS_UGCTRL_REG
);
92 val
= ioread16(base
+ USBHS_LPSTS_REG
);
93 val
&= ~USBHS_LPSTS_SUSPM
;
94 iowrite16(val
, base
+ USBHS_LPSTS_REG
);
96 val
= ioread32(base
+ USBHS_UGCTRL_REG
);
97 val
|= USBHS_UGCTRL_PLLRESET
;
98 iowrite32(val
, base
+ USBHS_UGCTRL_REG
);
102 /* Setup USB channels */
103 static void __rcar_gen2_usb_phy_init(struct rcar_gen2_usb_phy_priv
*priv
)
107 clk_prepare_enable(priv
->clk
);
109 /* Set USB channels in the USBHS UGCTRL2 register */
110 val
= ioread32(priv
->base
);
111 val
&= ~(USBHS_UGCTRL2_USB0_HS
| USBHS_UGCTRL2_USB2_SS
);
112 val
|= priv
->ugctrl2
;
113 iowrite32(val
, priv
->base
);
116 /* Shutdown USB channels */
117 static void __rcar_gen2_usb_phy_shutdown(struct rcar_gen2_usb_phy_priv
*priv
)
119 __rcar_gen2_usbhs_phy_disable(priv
->base
);
120 clk_disable_unprepare(priv
->clk
);
123 static int rcar_gen2_usb_phy_set_suspend(struct usb_phy
*phy
, int suspend
)
125 struct rcar_gen2_usb_phy_priv
*priv
= usb_phy_to_priv(phy
);
129 spin_lock_irqsave(&priv
->lock
, flags
);
130 retval
= suspend
? __rcar_gen2_usbhs_phy_disable(priv
->base
) :
131 __rcar_gen2_usbhs_phy_enable(priv
->base
);
132 spin_unlock_irqrestore(&priv
->lock
, flags
);
136 static int rcar_gen2_usb_phy_init(struct usb_phy
*phy
)
138 struct rcar_gen2_usb_phy_priv
*priv
= usb_phy_to_priv(phy
);
141 spin_lock_irqsave(&priv
->lock
, flags
);
143 * Enable the clock and setup USB channels
144 * if it's the first user
146 if (!priv
->usecount
++)
147 __rcar_gen2_usb_phy_init(priv
);
148 spin_unlock_irqrestore(&priv
->lock
, flags
);
152 static void rcar_gen2_usb_phy_shutdown(struct usb_phy
*phy
)
154 struct rcar_gen2_usb_phy_priv
*priv
= usb_phy_to_priv(phy
);
157 spin_lock_irqsave(&priv
->lock
, flags
);
158 if (!priv
->usecount
) {
159 dev_warn(phy
->dev
, "Trying to disable phy with 0 usecount\n");
163 /* Disable everything if it's the last user */
164 if (!--priv
->usecount
)
165 __rcar_gen2_usb_phy_shutdown(priv
);
167 spin_unlock_irqrestore(&priv
->lock
, flags
);
170 static int rcar_gen2_usb_phy_probe(struct platform_device
*pdev
)
172 struct device
*dev
= &pdev
->dev
;
173 struct rcar_gen2_phy_platform_data
*pdata
;
174 struct rcar_gen2_usb_phy_priv
*priv
;
175 struct resource
*res
;
180 pdata
= dev_get_platdata(&pdev
->dev
);
182 dev_err(dev
, "No platform data\n");
186 clk
= devm_clk_get(&pdev
->dev
, "usbhs");
188 dev_err(&pdev
->dev
, "Can't get the clock\n");
192 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
193 base
= devm_ioremap_resource(dev
, res
);
195 return PTR_ERR(base
);
197 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
199 dev_err(dev
, "Memory allocation failed\n");
203 spin_lock_init(&priv
->lock
);
206 priv
->ugctrl2
= pdata
->chan0_pci
?
207 USBHS_UGCTRL2_USB0_PCI
: USBHS_UGCTRL2_USB0_HS
;
208 priv
->ugctrl2
|= pdata
->chan2_pci
?
209 USBHS_UGCTRL2_USB2_PCI
: USBHS_UGCTRL2_USB2_SS
;
211 priv
->phy
.label
= dev_name(dev
);
212 priv
->phy
.init
= rcar_gen2_usb_phy_init
;
213 priv
->phy
.shutdown
= rcar_gen2_usb_phy_shutdown
;
214 priv
->phy
.set_suspend
= rcar_gen2_usb_phy_set_suspend
;
216 retval
= usb_add_phy(&priv
->phy
, USB_PHY_TYPE_USB2
);
218 dev_err(dev
, "Failed to add USB phy\n");
222 platform_set_drvdata(pdev
, priv
);
227 static int rcar_gen2_usb_phy_remove(struct platform_device
*pdev
)
229 struct rcar_gen2_usb_phy_priv
*priv
= platform_get_drvdata(pdev
);
231 usb_remove_phy(&priv
->phy
);
236 static struct platform_driver rcar_gen2_usb_phy_driver
= {
238 .name
= "usb_phy_rcar_gen2",
240 .probe
= rcar_gen2_usb_phy_probe
,
241 .remove
= rcar_gen2_usb_phy_remove
,
244 module_platform_driver(rcar_gen2_usb_phy_driver
);
246 MODULE_LICENSE("GPL v2");
247 MODULE_DESCRIPTION("Renesas R-Car Gen2 USB phy");
248 MODULE_AUTHOR("Valentine Barshak <valentine.barshak@cogentembedded.com>");