root/drivers/usb/host/uhci-platform.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. uhci_platform_init
  2. uhci_hcd_platform_probe
  3. uhci_hcd_platform_remove
  4. uhci_hcd_platform_shutdown

   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 
  15 static 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 
  37 static 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 
  67 static 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                         uhci->is_aspeed = 1;
 118                         dev_info(&pdev->dev,
 119                                  "Enabled Aspeed implementation workarounds\n");
 120                 }
 121         }
 122 
 123         /* Get and enable clock if any specified */
 124         uhci->clk = devm_clk_get(&pdev->dev, NULL);
 125         if (IS_ERR(uhci->clk)) {
 126                 ret = PTR_ERR(uhci->clk);
 127                 goto err_rmr;
 128         }
 129         ret = clk_prepare_enable(uhci->clk);
 130         if (ret) {
 131                 dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", ret);
 132                 goto err_rmr;
 133         }
 134 
 135         ret = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED);
 136         if (ret)
 137                 goto err_clk;
 138 
 139         device_wakeup_enable(hcd->self.controller);
 140         return 0;
 141 
 142 err_clk:
 143         clk_disable_unprepare(uhci->clk);
 144 err_rmr:
 145         usb_put_hcd(hcd);
 146 
 147         return ret;
 148 }
 149 
 150 static int uhci_hcd_platform_remove(struct platform_device *pdev)
 151 {
 152         struct usb_hcd *hcd = platform_get_drvdata(pdev);
 153         struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 154 
 155         clk_disable_unprepare(uhci->clk);
 156         usb_remove_hcd(hcd);
 157         usb_put_hcd(hcd);
 158 
 159         return 0;
 160 }
 161 
 162 /* Make sure the controller is quiescent and that we're not using it
 163  * any more.  This is mainly for the benefit of programs which, like kexec,
 164  * expect the hardware to be idle: not doing DMA or generating IRQs.
 165  *
 166  * This routine may be called in a damaged or failing kernel.  Hence we
 167  * do not acquire the spinlock before shutting down the controller.
 168  */
 169 static void uhci_hcd_platform_shutdown(struct platform_device *op)
 170 {
 171         struct usb_hcd *hcd = platform_get_drvdata(op);
 172 
 173         uhci_hc_died(hcd_to_uhci(hcd));
 174 }
 175 
 176 static const struct of_device_id platform_uhci_ids[] = {
 177         { .compatible = "generic-uhci", },
 178         { .compatible = "platform-uhci", },
 179         {}
 180 };
 181 MODULE_DEVICE_TABLE(of, platform_uhci_ids);
 182 
 183 static struct platform_driver uhci_platform_driver = {
 184         .probe          = uhci_hcd_platform_probe,
 185         .remove         = uhci_hcd_platform_remove,
 186         .shutdown       = uhci_hcd_platform_shutdown,
 187         .driver = {
 188                 .name = "platform-uhci",
 189                 .of_match_table = platform_uhci_ids,
 190         },
 191 };

/* [<][>][^][v][top][bottom][index][help] */