0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/err.h>
0015 #include <linux/signal.h>
0016
0017 #include <linux/of.h>
0018 #include <linux/of_platform.h>
0019 #include <linux/of_address.h>
0020 #include <linux/of_irq.h>
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 static int ehci_xilinx_port_handed_over(struct usb_hcd *hcd, int portnum)
0039 {
0040 dev_warn(hcd->self.controller, "port %d cannot be enabled\n", portnum);
0041 if (hcd->has_tt) {
0042 dev_warn(hcd->self.controller,
0043 "Maybe you have connected a low speed device?\n");
0044
0045 dev_warn(hcd->self.controller,
0046 "We do not support low speed devices\n");
0047 } else {
0048 dev_warn(hcd->self.controller,
0049 "Maybe your device is not a high speed device?\n");
0050 dev_warn(hcd->self.controller,
0051 "The USB host controller does not support full speed nor low speed devices\n");
0052 dev_warn(hcd->self.controller,
0053 "You can reconfigure the host controller to have full speed support\n");
0054 }
0055
0056 return 0;
0057 }
0058
0059
0060 static const struct hc_driver ehci_xilinx_of_hc_driver = {
0061 .description = hcd_name,
0062 .product_desc = "OF EHCI",
0063 .hcd_priv_size = sizeof(struct ehci_hcd),
0064
0065
0066
0067
0068 .irq = ehci_irq,
0069 .flags = HCD_MEMORY | HCD_DMA | HCD_USB2 | HCD_BH,
0070
0071
0072
0073
0074 .reset = ehci_setup,
0075 .start = ehci_run,
0076 .stop = ehci_stop,
0077 .shutdown = ehci_shutdown,
0078
0079
0080
0081
0082 .urb_enqueue = ehci_urb_enqueue,
0083 .urb_dequeue = ehci_urb_dequeue,
0084 .endpoint_disable = ehci_endpoint_disable,
0085 .endpoint_reset = ehci_endpoint_reset,
0086
0087
0088
0089
0090 .get_frame_number = ehci_get_frame,
0091
0092
0093
0094
0095 .hub_status_data = ehci_hub_status_data,
0096 .hub_control = ehci_hub_control,
0097 #ifdef CONFIG_PM
0098 .bus_suspend = ehci_bus_suspend,
0099 .bus_resume = ehci_bus_resume,
0100 #endif
0101 .relinquish_port = NULL,
0102 .port_handed_over = ehci_xilinx_port_handed_over,
0103
0104 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
0105 };
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 static int ehci_hcd_xilinx_of_probe(struct platform_device *op)
0119 {
0120 struct device_node *dn = op->dev.of_node;
0121 struct usb_hcd *hcd;
0122 struct ehci_hcd *ehci;
0123 struct resource res;
0124 int irq;
0125 int rv;
0126 int *value;
0127
0128 if (usb_disabled())
0129 return -ENODEV;
0130
0131 dev_dbg(&op->dev, "initializing XILINX-OF USB Controller\n");
0132
0133 rv = of_address_to_resource(dn, 0, &res);
0134 if (rv)
0135 return rv;
0136
0137 hcd = usb_create_hcd(&ehci_xilinx_of_hc_driver, &op->dev,
0138 "XILINX-OF USB");
0139 if (!hcd)
0140 return -ENOMEM;
0141
0142 hcd->rsrc_start = res.start;
0143 hcd->rsrc_len = resource_size(&res);
0144
0145 irq = irq_of_parse_and_map(dn, 0);
0146 if (!irq) {
0147 dev_err(&op->dev, "%s: irq_of_parse_and_map failed\n",
0148 __FILE__);
0149 rv = -EBUSY;
0150 goto err_irq;
0151 }
0152
0153 hcd->regs = devm_ioremap_resource(&op->dev, &res);
0154 if (IS_ERR(hcd->regs)) {
0155 rv = PTR_ERR(hcd->regs);
0156 goto err_irq;
0157 }
0158
0159 ehci = hcd_to_ehci(hcd);
0160
0161
0162
0163
0164 ehci->big_endian_mmio = 1;
0165 ehci->big_endian_desc = 1;
0166
0167
0168
0169 value = (int *)of_get_property(dn, "xlnx,support-usb-fs", NULL);
0170 if (value && (*value == 1)) {
0171 ehci_dbg(ehci, "USB host controller supports FS devices\n");
0172 hcd->has_tt = 1;
0173 } else {
0174 ehci_dbg(ehci,
0175 "USB host controller is HS only\n");
0176 hcd->has_tt = 0;
0177 }
0178
0179
0180
0181 ehci->caps = hcd->regs + 0x100;
0182
0183 rv = usb_add_hcd(hcd, irq, 0);
0184 if (rv == 0) {
0185 device_wakeup_enable(hcd->self.controller);
0186 return 0;
0187 }
0188
0189 err_irq:
0190 usb_put_hcd(hcd);
0191
0192 return rv;
0193 }
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204 static int ehci_hcd_xilinx_of_remove(struct platform_device *op)
0205 {
0206 struct usb_hcd *hcd = platform_get_drvdata(op);
0207
0208 dev_dbg(&op->dev, "stopping XILINX-OF USB Controller\n");
0209
0210 usb_remove_hcd(hcd);
0211
0212 usb_put_hcd(hcd);
0213
0214 return 0;
0215 }
0216
0217 static const struct of_device_id ehci_hcd_xilinx_of_match[] = {
0218 {.compatible = "xlnx,xps-usb-host-1.00.a",},
0219 {},
0220 };
0221 MODULE_DEVICE_TABLE(of, ehci_hcd_xilinx_of_match);
0222
0223 static struct platform_driver ehci_hcd_xilinx_of_driver = {
0224 .probe = ehci_hcd_xilinx_of_probe,
0225 .remove = ehci_hcd_xilinx_of_remove,
0226 .shutdown = usb_hcd_platform_shutdown,
0227 .driver = {
0228 .name = "xilinx-of-ehci",
0229 .of_match_table = ehci_hcd_xilinx_of_match,
0230 },
0231 };