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