0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/of.h>
0012 #include <linux/device.h>
0013 #include <linux/platform_device.h>
0014
0015 static int uhci_platform_init(struct usb_hcd *hcd)
0016 {
0017 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
0018
0019
0020 if (!uhci->rh_numports)
0021 uhci->rh_numports = uhci_count_ports(hcd);
0022
0023
0024 uhci->reset_hc = uhci_generic_reset_hc;
0025 uhci->check_and_reset_hc = uhci_generic_check_and_reset_hc;
0026
0027
0028 uhci->configure_hc = NULL;
0029 uhci->resume_detect_interrupts_are_broken = NULL;
0030 uhci->global_suspend_mode_is_broken = NULL;
0031
0032
0033 check_and_reset_hc(uhci);
0034 return 0;
0035 }
0036
0037 static const struct hc_driver uhci_platform_hc_driver = {
0038 .description = hcd_name,
0039 .product_desc = "Generic UHCI Host Controller",
0040 .hcd_priv_size = sizeof(struct uhci_hcd),
0041
0042
0043 .irq = uhci_irq,
0044 .flags = HCD_MEMORY | HCD_DMA | HCD_USB11,
0045
0046
0047 .reset = uhci_platform_init,
0048 .start = uhci_start,
0049 #ifdef CONFIG_PM
0050 .pci_suspend = NULL,
0051 .pci_resume = NULL,
0052 .bus_suspend = uhci_rh_suspend,
0053 .bus_resume = uhci_rh_resume,
0054 #endif
0055 .stop = uhci_stop,
0056
0057 .urb_enqueue = uhci_urb_enqueue,
0058 .urb_dequeue = uhci_urb_dequeue,
0059
0060 .endpoint_disable = uhci_hcd_endpoint_disable,
0061 .get_frame_number = uhci_hcd_get_frame_number,
0062
0063 .hub_status_data = uhci_hub_status_data,
0064 .hub_control = uhci_hub_control,
0065 };
0066
0067 static int uhci_hcd_platform_probe(struct platform_device *pdev)
0068 {
0069 struct device_node *np = pdev->dev.of_node;
0070 struct usb_hcd *hcd;
0071 struct uhci_hcd *uhci;
0072 struct resource *res;
0073 int ret;
0074
0075 if (usb_disabled())
0076 return -ENODEV;
0077
0078
0079
0080
0081
0082
0083 ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
0084 if (ret)
0085 return ret;
0086
0087 hcd = usb_create_hcd(&uhci_platform_hc_driver, &pdev->dev,
0088 pdev->name);
0089 if (!hcd)
0090 return -ENOMEM;
0091
0092 uhci = hcd_to_uhci(hcd);
0093
0094 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0095 hcd->regs = devm_ioremap_resource(&pdev->dev, res);
0096 if (IS_ERR(hcd->regs)) {
0097 ret = PTR_ERR(hcd->regs);
0098 goto err_rmr;
0099 }
0100 hcd->rsrc_start = res->start;
0101 hcd->rsrc_len = resource_size(res);
0102
0103 uhci->regs = hcd->regs;
0104
0105
0106 if (np) {
0107 u32 num_ports;
0108
0109 if (of_property_read_u32(np, "#ports", &num_ports) == 0) {
0110 uhci->rh_numports = num_ports;
0111 dev_info(&pdev->dev,
0112 "Detected %d ports from device-tree\n",
0113 num_ports);
0114 }
0115 if (of_device_is_compatible(np, "aspeed,ast2400-uhci") ||
0116 of_device_is_compatible(np, "aspeed,ast2500-uhci") ||
0117 of_device_is_compatible(np, "aspeed,ast2600-uhci")) {
0118 uhci->is_aspeed = 1;
0119 dev_info(&pdev->dev,
0120 "Enabled Aspeed implementation workarounds\n");
0121 }
0122 }
0123
0124
0125 uhci->clk = devm_clk_get(&pdev->dev, NULL);
0126 if (IS_ERR(uhci->clk)) {
0127 ret = PTR_ERR(uhci->clk);
0128 goto err_rmr;
0129 }
0130 ret = clk_prepare_enable(uhci->clk);
0131 if (ret) {
0132 dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", ret);
0133 goto err_rmr;
0134 }
0135
0136 ret = platform_get_irq(pdev, 0);
0137 if (ret < 0)
0138 goto err_clk;
0139
0140 ret = usb_add_hcd(hcd, ret, IRQF_SHARED);
0141 if (ret)
0142 goto err_clk;
0143
0144 device_wakeup_enable(hcd->self.controller);
0145 return 0;
0146
0147 err_clk:
0148 clk_disable_unprepare(uhci->clk);
0149 err_rmr:
0150 usb_put_hcd(hcd);
0151
0152 return ret;
0153 }
0154
0155 static int uhci_hcd_platform_remove(struct platform_device *pdev)
0156 {
0157 struct usb_hcd *hcd = platform_get_drvdata(pdev);
0158 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
0159
0160 clk_disable_unprepare(uhci->clk);
0161 usb_remove_hcd(hcd);
0162 usb_put_hcd(hcd);
0163
0164 return 0;
0165 }
0166
0167
0168
0169
0170
0171
0172
0173
0174 static void uhci_hcd_platform_shutdown(struct platform_device *op)
0175 {
0176 struct usb_hcd *hcd = platform_get_drvdata(op);
0177
0178 uhci_hc_died(hcd_to_uhci(hcd));
0179 }
0180
0181 static const struct of_device_id platform_uhci_ids[] = {
0182 { .compatible = "generic-uhci", },
0183 { .compatible = "platform-uhci", },
0184 {}
0185 };
0186 MODULE_DEVICE_TABLE(of, platform_uhci_ids);
0187
0188 static struct platform_driver uhci_platform_driver = {
0189 .probe = uhci_hcd_platform_probe,
0190 .remove = uhci_hcd_platform_remove,
0191 .shutdown = uhci_hcd_platform_shutdown,
0192 .driver = {
0193 .name = "platform-uhci",
0194 .of_match_table = platform_uhci_ids,
0195 },
0196 };