1 /* 2 * host.c - ChipIdea USB host controller driver 3 * 4 * Copyright (c) 2012 Intel Corporation 5 * 6 * Author: Alexander Shishkin 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 version 2 as 10 * published by the Free Software Foundation. 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., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22 #include <linux/kernel.h> 23 #include <linux/usb.h> 24 #include <linux/usb/hcd.h> 25 #include <linux/usb/chipidea.h> 26 27 #define CHIPIDEA_EHCI 28 #include "../host/ehci-hcd.c" 29 30 #include "ci.h" 31 #include "bits.h" 32 #include "host.h" 33 34 static int ci_ehci_setup(struct usb_hcd *hcd) 35 { 36 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 37 int ret; 38 39 hcd->has_tt = 1; 40 41 ret = ehci_setup(hcd); 42 if (ret) 43 return ret; 44 45 ehci_port_power(ehci, 0); 46 47 return ret; 48 } 49 50 static const struct hc_driver ci_ehci_hc_driver = { 51 .description = "ehci_hcd", 52 .product_desc = "ChipIdea HDRC EHCI", 53 .hcd_priv_size = sizeof(struct ehci_hcd), 54 55 /* 56 * generic hardware linkage 57 */ 58 .irq = ehci_irq, 59 .flags = HCD_MEMORY | HCD_USB2, 60 61 /* 62 * basic lifecycle operations 63 */ 64 .reset = ci_ehci_setup, 65 .start = ehci_run, 66 .stop = ehci_stop, 67 .shutdown = ehci_shutdown, 68 69 /* 70 * managing i/o requests and associated device resources 71 */ 72 .urb_enqueue = ehci_urb_enqueue, 73 .urb_dequeue = ehci_urb_dequeue, 74 .endpoint_disable = ehci_endpoint_disable, 75 .endpoint_reset = ehci_endpoint_reset, 76 77 /* 78 * scheduling support 79 */ 80 .get_frame_number = ehci_get_frame, 81 82 /* 83 * root hub support 84 */ 85 .hub_status_data = ehci_hub_status_data, 86 .hub_control = ehci_hub_control, 87 .bus_suspend = ehci_bus_suspend, 88 .bus_resume = ehci_bus_resume, 89 .relinquish_port = ehci_relinquish_port, 90 .port_handed_over = ehci_port_handed_over, 91 92 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 93 }; 94 95 static irqreturn_t host_irq(struct ci13xxx *ci) 96 { 97 return usb_hcd_irq(ci->irq, ci->hcd); 98 } 99 100 static int host_start(struct ci13xxx *ci) 101 { 102 struct usb_hcd *hcd; 103 struct ehci_hcd *ehci; 104 int ret; 105 106 if (usb_disabled()) 107 return -ENODEV; 108 109 hcd = usb_create_hcd(&ci_ehci_hc_driver, ci->dev, dev_name(ci->dev)); 110 if (!hcd) 111 return -ENOMEM; 112 113 dev_set_drvdata(ci->dev, ci); 114 hcd->rsrc_start = ci->hw_bank.phys; 115 hcd->rsrc_len = ci->hw_bank.size; 116 hcd->regs = ci->hw_bank.abs; 117 hcd->has_tt = 1; 118 119 hcd->power_budget = ci->platdata->power_budget; 120 hcd->phy = ci->transceiver; 121 122 ehci = hcd_to_ehci(hcd); 123 ehci->caps = ci->hw_bank.cap; 124 ehci->has_hostpc = ci->hw_bank.lpm; 125 126 ret = usb_add_hcd(hcd, 0, 0); 127 if (ret) 128 usb_put_hcd(hcd); 129 else 130 ci->hcd = hcd; 131 132 return ret; 133 } 134 135 static void host_stop(struct ci13xxx *ci) 136 { 137 struct usb_hcd *hcd = ci->hcd; 138 139 usb_remove_hcd(hcd); 140 usb_put_hcd(hcd); 141 } 142 143 int ci_hdrc_host_init(struct ci13xxx *ci) 144 { 145 struct ci_role_driver *rdrv; 146 147 if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_HC)) 148 return -ENXIO; 149 150 rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL); 151 if (!rdrv) 152 return -ENOMEM; 153 154 rdrv->start = host_start; 155 rdrv->stop = host_stop; 156 rdrv->irq = host_irq; 157 rdrv->name = "host"; 158 ci->roles[CI_ROLE_HOST] = rdrv; 159 160 return 0; 161 } 162