4 * Copyright (C) 2011 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 #include <linux/module.h>
19 #include <linux/pm_runtime.h>
20 #include <linux/slab.h>
21 #include <linux/sysfs.h>
27 * renesas usb support platform callback function.
28 * Below macro call it.
29 * if platform doesn't have callback, it return 0 (no error)
31 #define usbhs_platform_call(priv, func, args...)\
32 (!(priv) ? -ENODEV : \
33 !((priv)->pfunc->func) ? 0 : \
34 (priv)->pfunc->func(args))
39 u16
usbhs_read(struct usbhs_priv
*priv
, u32 reg
)
41 return ioread16(priv
->base
+ reg
);
44 void usbhs_write(struct usbhs_priv
*priv
, u32 reg
, u16 data
)
46 iowrite16(data
, priv
->base
+ reg
);
49 void usbhs_bset(struct usbhs_priv
*priv
, u32 reg
, u16 mask
, u16 data
)
51 u16 val
= usbhs_read(priv
, reg
);
56 usbhs_write(priv
, reg
, val
);
59 struct usbhs_priv
*usbhs_pdev_to_priv(struct platform_device
*pdev
)
61 return dev_get_drvdata(&pdev
->dev
);
67 void usbhs_sys_clock_ctrl(struct usbhs_priv
*priv
, int enable
)
69 usbhs_bset(priv
, SYSCFG
, SCKE
, enable
? SCKE
: 0);
72 void usbhs_sys_hispeed_ctrl(struct usbhs_priv
*priv
, int enable
)
74 usbhs_bset(priv
, SYSCFG
, HSE
, enable
? HSE
: 0);
77 void usbhs_sys_usb_ctrl(struct usbhs_priv
*priv
, int enable
)
79 usbhs_bset(priv
, SYSCFG
, USBE
, enable
? USBE
: 0);
82 void usbhs_sys_host_ctrl(struct usbhs_priv
*priv
, int enable
)
84 u16 mask
= DCFM
| DRPD
| DPRPU
;
85 u16 val
= DCFM
| DRPD
;
91 * - D+ Line/D- Line Pull-down
93 usbhs_bset(priv
, SYSCFG
, mask
, enable
? val
: 0);
96 void usbhs_sys_function_ctrl(struct usbhs_priv
*priv
, int enable
)
98 u16 mask
= DCFM
| DRPD
| DPRPU
;
104 * - select Function mode
107 usbhs_bset(priv
, SYSCFG
, mask
, enable
? val
: 0);
113 int usbhs_frame_get_num(struct usbhs_priv
*priv
)
115 return usbhs_read(priv
, FRMNUM
) & FRNM_MASK
;
121 static void usbhsc_bus_ctrl(struct usbhs_priv
*priv
, int enable
)
123 int wait
= usbhs_get_dparam(priv
, buswait_bwait
);
127 /* set bus wait if platform have */
129 usbhs_bset(priv
, BUSWAIT
, 0x000F, wait
);
131 usbhs_write(priv
, DVSTCTR
, data
);
135 * platform default param
137 static u32 usbhsc_default_pipe_type
[] = {
138 USB_ENDPOINT_XFER_CONTROL
,
139 USB_ENDPOINT_XFER_ISOC
,
140 USB_ENDPOINT_XFER_ISOC
,
141 USB_ENDPOINT_XFER_BULK
,
142 USB_ENDPOINT_XFER_BULK
,
143 USB_ENDPOINT_XFER_BULK
,
144 USB_ENDPOINT_XFER_INT
,
145 USB_ENDPOINT_XFER_INT
,
146 USB_ENDPOINT_XFER_INT
,
147 USB_ENDPOINT_XFER_INT
,
153 static void usbhsc_power_ctrl(struct usbhs_priv
*priv
, int enable
)
155 struct device
*dev
= usbhs_priv_to_dev(priv
);
159 pm_runtime_get_sync(dev
);
162 usbhs_sys_clock_ctrl(priv
, enable
);
163 usbhsc_bus_ctrl(priv
, enable
);
166 usbhsc_bus_ctrl(priv
, enable
);
167 usbhs_sys_clock_ctrl(priv
, enable
);
170 pm_runtime_put_sync(dev
);
177 static void usbhsc_notify_hotplug(struct work_struct
*work
)
179 struct usbhs_priv
*priv
= container_of(work
,
181 notify_hotplug_work
.work
);
182 struct platform_device
*pdev
= usbhs_priv_to_pdev(priv
);
183 struct usbhs_mod
*mod
= usbhs_mod_get_current(priv
);
189 * get vbus status from platform
191 enable
= usbhs_platform_call(priv
, get_vbus
, pdev
);
194 * get id from platform
196 id
= usbhs_platform_call(priv
, get_id
, pdev
);
198 if (enable
&& !mod
) {
199 ret
= usbhs_mod_change(priv
, id
);
203 dev_dbg(&pdev
->dev
, "%s enable\n", __func__
);
206 usbhsc_power_ctrl(priv
, enable
);
209 usbhs_mod_call(priv
, start
, priv
);
211 } else if (!enable
&& mod
) {
212 dev_dbg(&pdev
->dev
, "%s disable\n", __func__
);
215 usbhs_mod_call(priv
, stop
, priv
);
218 usbhsc_power_ctrl(priv
, enable
);
220 usbhs_mod_change(priv
, -1);
222 /* reset phy for next connection */
223 usbhs_platform_call(priv
, phy_reset
, pdev
);
227 int usbhsc_drvcllbck_notify_hotplug(struct platform_device
*pdev
)
229 struct usbhs_priv
*priv
= usbhs_pdev_to_priv(pdev
);
230 int delay
= usbhs_get_dparam(priv
, detection_delay
);
233 * This functions will be called in interrupt.
234 * To make sure safety context,
235 * use workqueue for usbhs_notify_hotplug
237 schedule_delayed_work(&priv
->notify_hotplug_work
, delay
);
244 static int __devinit
usbhs_probe(struct platform_device
*pdev
)
246 struct renesas_usbhs_platform_info
*info
= pdev
->dev
.platform_data
;
247 struct renesas_usbhs_driver_callback
*dfunc
;
248 struct usbhs_priv
*priv
;
249 struct resource
*res
;
253 /* check platform information */
255 !info
->platform_callback
.get_id
||
256 !info
->platform_callback
.get_vbus
) {
257 dev_err(&pdev
->dev
, "no platform information\n");
262 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
263 irq
= platform_get_irq(pdev
, 0);
264 if (!res
|| (int)irq
<= 0) {
265 dev_err(&pdev
->dev
, "Not enough Renesas USB platform resources.\n");
269 /* usb private data */
270 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
272 dev_err(&pdev
->dev
, "Could not allocate priv\n");
276 priv
->base
= ioremap_nocache(res
->start
, resource_size(res
));
278 dev_err(&pdev
->dev
, "ioremap error.\n");
280 goto probe_end_kfree
;
286 priv
->pfunc
= &info
->platform_callback
;
287 priv
->dparam
= &info
->driver_param
;
289 /* set driver callback functions for platform */
290 dfunc
= &info
->driver_callback
;
291 dfunc
->notify_hotplug
= usbhsc_drvcllbck_notify_hotplug
;
293 /* set default param if platform doesn't have */
294 if (!priv
->dparam
->pipe_type
) {
295 priv
->dparam
->pipe_type
= usbhsc_default_pipe_type
;
296 priv
->dparam
->pipe_size
= ARRAY_SIZE(usbhsc_default_pipe_type
);
304 INIT_DELAYED_WORK(&priv
->notify_hotplug_work
, usbhsc_notify_hotplug
);
305 spin_lock_init(usbhs_priv_to_lock(priv
));
307 /* call pipe and module init */
308 ret
= usbhs_pipe_probe(priv
);
310 goto probe_end_mod_exit
;
312 ret
= usbhs_mod_probe(priv
);
314 goto probe_end_iounmap
;
316 /* dev_set_drvdata should be called after usbhs_mod_init */
317 dev_set_drvdata(&pdev
->dev
, priv
);
320 * deviece reset here because
321 * USB device might be used in boot loader.
323 usbhs_sys_clock_ctrl(priv
, 0);
328 * USB phy setup might depend on CPU/Board.
329 * If platform has its callback functions,
332 ret
= usbhs_platform_call(priv
, hardware_init
, pdev
);
334 dev_err(&pdev
->dev
, "platform prove failed.\n");
335 goto probe_end_pipe_exit
;
338 /* reset phy for connection */
339 usbhs_platform_call(priv
, phy_reset
, pdev
);
342 * manual call notify_hotplug for cold plug
344 pm_runtime_enable(&pdev
->dev
);
345 ret
= usbhsc_drvcllbck_notify_hotplug(pdev
);
347 goto probe_end_call_remove
;
349 dev_info(&pdev
->dev
, "probed\n");
353 probe_end_call_remove
:
354 usbhs_platform_call(priv
, hardware_exit
, pdev
);
356 usbhs_pipe_remove(priv
);
358 usbhs_mod_remove(priv
);
364 dev_info(&pdev
->dev
, "probe failed\n");
369 static int __devexit
usbhs_remove(struct platform_device
*pdev
)
371 struct usbhs_priv
*priv
= usbhs_pdev_to_priv(pdev
);
372 struct renesas_usbhs_platform_info
*info
= pdev
->dev
.platform_data
;
373 struct renesas_usbhs_driver_callback
*dfunc
= &info
->driver_callback
;
375 dev_dbg(&pdev
->dev
, "usb remove\n");
377 dfunc
->notify_hotplug
= NULL
;
379 pm_runtime_disable(&pdev
->dev
);
381 usbhsc_bus_ctrl(priv
, 0);
383 usbhs_platform_call(priv
, hardware_exit
, pdev
);
384 usbhs_pipe_remove(priv
);
385 usbhs_mod_remove(priv
);
392 static struct platform_driver renesas_usbhs_driver
= {
394 .name
= "renesas_usbhs",
396 .probe
= usbhs_probe
,
397 .remove
= __devexit_p(usbhs_remove
),
400 static int __init
usbhs_init(void)
402 return platform_driver_register(&renesas_usbhs_driver
);
405 static void __exit
usbhs_exit(void)
407 platform_driver_unregister(&renesas_usbhs_driver
);
410 module_init(usbhs_init
);
411 module_exit(usbhs_exit
);
413 MODULE_LICENSE("GPL");
414 MODULE_DESCRIPTION("Renesas USB driver");
415 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");