1/* 2 * OHCI HCD (Host Controller Driver) for USB. 3 * 4 * Copyright (C) 2008 Renesas Solutions Corp. 5 * 6 * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; version 2 of the License. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 * 21 */ 22 23#include <linux/platform_device.h> 24 25static int ohci_sh_start(struct usb_hcd *hcd) 26{ 27 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 28 29 ohci_hcd_init(ohci); 30 ohci_init(ohci); 31 ohci_run(ohci); 32 hcd->state = HC_STATE_RUNNING; 33 return 0; 34} 35 36static const struct hc_driver ohci_sh_hc_driver = { 37 .description = hcd_name, 38 .product_desc = "SuperH OHCI", 39 .hcd_priv_size = sizeof(struct ohci_hcd), 40 41 /* 42 * generic hardware linkage 43 */ 44 .irq = ohci_irq, 45 .flags = HCD_USB11 | HCD_MEMORY, 46 47 /* 48 * basic lifecycle operations 49 */ 50 .start = ohci_sh_start, 51 .stop = ohci_stop, 52 .shutdown = ohci_shutdown, 53 54 /* 55 * managing i/o requests and associated device resources 56 */ 57 .urb_enqueue = ohci_urb_enqueue, 58 .urb_dequeue = ohci_urb_dequeue, 59 .endpoint_disable = ohci_endpoint_disable, 60 61 /* 62 * scheduling support 63 */ 64 .get_frame_number = ohci_get_frame, 65 66 /* 67 * root hub support 68 */ 69 .hub_status_data = ohci_hub_status_data, 70 .hub_control = ohci_hub_control, 71#ifdef CONFIG_PM 72 .bus_suspend = ohci_bus_suspend, 73 .bus_resume = ohci_bus_resume, 74#endif 75 .start_port_reset = ohci_start_port_reset, 76}; 77 78/*-------------------------------------------------------------------------*/ 79 80#define resource_len(r) (((r)->end - (r)->start) + 1) 81static int ohci_hcd_sh_probe(struct platform_device *pdev) 82{ 83 struct resource *res = NULL; 84 struct usb_hcd *hcd = NULL; 85 int irq = -1; 86 int ret; 87 88 if (usb_disabled()) 89 return -ENODEV; 90 91 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 92 if (!res) { 93 err("platform_get_resource error."); 94 return -ENODEV; 95 } 96 97 irq = platform_get_irq(pdev, 0); 98 if (irq < 0) { 99 err("platform_get_irq error."); 100 return -ENODEV; 101 } 102 103 /* initialize hcd */ 104 hcd = usb_create_hcd(&ohci_sh_hc_driver, &pdev->dev, (char *)hcd_name); 105 if (!hcd) { 106 err("Failed to create hcd"); 107 return -ENOMEM; 108 } 109 110 hcd->regs = (void __iomem *)res->start; 111 hcd->rsrc_start = res->start; 112 hcd->rsrc_len = resource_len(res); 113 ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); 114 if (ret != 0) { 115 err("Failed to add hcd"); 116 usb_put_hcd(hcd); 117 return ret; 118 } 119 120 return ret; 121} 122 123static int ohci_hcd_sh_remove(struct platform_device *pdev) 124{ 125 struct usb_hcd *hcd = platform_get_drvdata(pdev); 126 127 usb_remove_hcd(hcd); 128 usb_put_hcd(hcd); 129 130 return 0; 131} 132 133static struct platform_driver ohci_hcd_sh_driver = { 134 .probe = ohci_hcd_sh_probe, 135 .remove = ohci_hcd_sh_remove, 136 .shutdown = usb_hcd_platform_shutdown, 137 .driver = { 138 .name = "sh_ohci", 139 .owner = THIS_MODULE, 140 }, 141}; 142 143MODULE_ALIAS("platform:sh_ohci"); 144