Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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
 14static 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
 34static 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
 64static 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
108err_rmr:
109	usb_put_hcd(hcd);
110
111	return ret;
112}
113
114static 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 */
131static 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
138static const struct of_device_id platform_uhci_ids[] = {
139	{ .compatible = "generic-uhci", },
140	{ .compatible = "platform-uhci", },
141	{}
142};
143MODULE_DEVICE_TABLE(of, platform_uhci_ids);
144
145static 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};