uhci-platform.c (5066B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Generic UHCI HCD (Host Controller Driver) for Platform Devices 4 * 5 * Copyright (c) 2011 Tony Prisk <linux@prisktech.co.nz> 6 * 7 * This file is based on uhci-grlib.c 8 * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu 9 */ 10 11#include <linux/of.h> 12#include <linux/device.h> 13#include <linux/platform_device.h> 14 15static int uhci_platform_init(struct usb_hcd *hcd) 16{ 17 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 18 19 /* Probe number of ports if not already provided by DT */ 20 if (!uhci->rh_numports) 21 uhci->rh_numports = uhci_count_ports(hcd); 22 23 /* Set up pointers to to generic functions */ 24 uhci->reset_hc = uhci_generic_reset_hc; 25 uhci->check_and_reset_hc = uhci_generic_check_and_reset_hc; 26 27 /* No special actions need to be taken for the functions below */ 28 uhci->configure_hc = NULL; 29 uhci->resume_detect_interrupts_are_broken = NULL; 30 uhci->global_suspend_mode_is_broken = NULL; 31 32 /* Reset if the controller isn't already safely quiescent. */ 33 check_and_reset_hc(uhci); 34 return 0; 35} 36 37static const struct hc_driver uhci_platform_hc_driver = { 38 .description = hcd_name, 39 .product_desc = "Generic UHCI Host Controller", 40 .hcd_priv_size = sizeof(struct uhci_hcd), 41 42 /* Generic hardware linkage */ 43 .irq = uhci_irq, 44 .flags = HCD_MEMORY | HCD_DMA | HCD_USB11, 45 46 /* Basic lifecycle operations */ 47 .reset = uhci_platform_init, 48 .start = uhci_start, 49#ifdef CONFIG_PM 50 .pci_suspend = NULL, 51 .pci_resume = NULL, 52 .bus_suspend = uhci_rh_suspend, 53 .bus_resume = uhci_rh_resume, 54#endif 55 .stop = uhci_stop, 56 57 .urb_enqueue = uhci_urb_enqueue, 58 .urb_dequeue = uhci_urb_dequeue, 59 60 .endpoint_disable = uhci_hcd_endpoint_disable, 61 .get_frame_number = uhci_hcd_get_frame_number, 62 63 .hub_status_data = uhci_hub_status_data, 64 .hub_control = uhci_hub_control, 65}; 66 67static int uhci_hcd_platform_probe(struct platform_device *pdev) 68{ 69 struct device_node *np = pdev->dev.of_node; 70 struct usb_hcd *hcd; 71 struct uhci_hcd *uhci; 72 struct resource *res; 73 int ret; 74 75 if (usb_disabled()) 76 return -ENODEV; 77 78 /* 79 * Right now device-tree probed devices don't get dma_mask set. 80 * Since shared usb code relies on it, set it here for now. 81 * Once we have dma capability bindings this can go away. 82 */ 83 ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 84 if (ret) 85 return ret; 86 87 hcd = usb_create_hcd(&uhci_platform_hc_driver, &pdev->dev, 88 pdev->name); 89 if (!hcd) 90 return -ENOMEM; 91 92 uhci = hcd_to_uhci(hcd); 93 94 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 95 hcd->regs = devm_ioremap_resource(&pdev->dev, res); 96 if (IS_ERR(hcd->regs)) { 97 ret = PTR_ERR(hcd->regs); 98 goto err_rmr; 99 } 100 hcd->rsrc_start = res->start; 101 hcd->rsrc_len = resource_size(res); 102 103 uhci->regs = hcd->regs; 104 105 /* Grab some things from the device-tree */ 106 if (np) { 107 u32 num_ports; 108 109 if (of_property_read_u32(np, "#ports", &num_ports) == 0) { 110 uhci->rh_numports = num_ports; 111 dev_info(&pdev->dev, 112 "Detected %d ports from device-tree\n", 113 num_ports); 114 } 115 if (of_device_is_compatible(np, "aspeed,ast2400-uhci") || 116 of_device_is_compatible(np, "aspeed,ast2500-uhci") || 117 of_device_is_compatible(np, "aspeed,ast2600-uhci")) { 118 uhci->is_aspeed = 1; 119 dev_info(&pdev->dev, 120 "Enabled Aspeed implementation workarounds\n"); 121 } 122 } 123 124 /* Get and enable clock if any specified */ 125 uhci->clk = devm_clk_get(&pdev->dev, NULL); 126 if (IS_ERR(uhci->clk)) { 127 ret = PTR_ERR(uhci->clk); 128 goto err_rmr; 129 } 130 ret = clk_prepare_enable(uhci->clk); 131 if (ret) { 132 dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", ret); 133 goto err_rmr; 134 } 135 136 ret = platform_get_irq(pdev, 0); 137 if (ret < 0) 138 goto err_clk; 139 140 ret = usb_add_hcd(hcd, ret, IRQF_SHARED); 141 if (ret) 142 goto err_clk; 143 144 device_wakeup_enable(hcd->self.controller); 145 return 0; 146 147err_clk: 148 clk_disable_unprepare(uhci->clk); 149err_rmr: 150 usb_put_hcd(hcd); 151 152 return ret; 153} 154 155static int uhci_hcd_platform_remove(struct platform_device *pdev) 156{ 157 struct usb_hcd *hcd = platform_get_drvdata(pdev); 158 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 159 160 clk_disable_unprepare(uhci->clk); 161 usb_remove_hcd(hcd); 162 usb_put_hcd(hcd); 163 164 return 0; 165} 166 167/* Make sure the controller is quiescent and that we're not using it 168 * any more. This is mainly for the benefit of programs which, like kexec, 169 * expect the hardware to be idle: not doing DMA or generating IRQs. 170 * 171 * This routine may be called in a damaged or failing kernel. Hence we 172 * do not acquire the spinlock before shutting down the controller. 173 */ 174static void uhci_hcd_platform_shutdown(struct platform_device *op) 175{ 176 struct usb_hcd *hcd = platform_get_drvdata(op); 177 178 uhci_hc_died(hcd_to_uhci(hcd)); 179} 180 181static const struct of_device_id platform_uhci_ids[] = { 182 { .compatible = "generic-uhci", }, 183 { .compatible = "platform-uhci", }, 184 {} 185}; 186MODULE_DEVICE_TABLE(of, platform_uhci_ids); 187 188static struct platform_driver uhci_platform_driver = { 189 .probe = uhci_hcd_platform_probe, 190 .remove = uhci_hcd_platform_remove, 191 .shutdown = uhci_hcd_platform_shutdown, 192 .driver = { 193 .name = "platform-uhci", 194 .of_match_table = platform_uhci_ids, 195 }, 196};