ehci-xls.c 3.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * EHCI HCD for Netlogic XLS processors.
 *
 * (C) Copyright 2011 Netlogic Microsystems Inc.
 *
 *  Based on various ehci-*.c drivers
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file COPYING in the main directory of this archive for
 * more details.
 */

#include <linux/platform_device.h>

static int ehci_xls_setup(struct usb_hcd *hcd)
{
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);

	ehci->caps = hcd->regs;

21
	return ehci_setup(hcd);
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
}

int ehci_xls_probe_internal(const struct hc_driver *driver,
	struct platform_device *pdev)
{
	struct usb_hcd  *hcd;
	struct resource *res;
	int retval, irq;

	/* Get our IRQ from an earlier registered Platform Resource */
	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(&pdev->dev, "Found HC with no IRQ. Check %s setup!\n",
				dev_name(&pdev->dev));
		return -ENODEV;
	}

	/* Get our Memory Handle */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "Error: MMIO Handle %s setup!\n",
				dev_name(&pdev->dev));
		return -ENODEV;
	}
	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
	if (!hcd) {
		retval = -ENOMEM;
		goto err1;
	}

	hcd->rsrc_start = res->start;
53
	hcd->rsrc_len = resource_size(res);
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142

	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
				driver->description)) {
		dev_dbg(&pdev->dev, "controller already in use\n");
		retval = -EBUSY;
		goto err2;
	}
	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);

	if (hcd->regs == NULL) {
		dev_dbg(&pdev->dev, "error mapping memory\n");
		retval = -EFAULT;
		goto err3;
	}

	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
	if (retval != 0)
		goto err4;
	return retval;

err4:
	iounmap(hcd->regs);
err3:
	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err2:
	usb_put_hcd(hcd);
err1:
	dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev),
			retval);
	return retval;
}

static struct hc_driver ehci_xls_hc_driver = {
	.description	= hcd_name,
	.product_desc	= "XLS EHCI Host Controller",
	.hcd_priv_size	= sizeof(struct ehci_hcd),
	.irq		= ehci_irq,
	.flags		= HCD_USB2 | HCD_MEMORY,
	.reset		= ehci_xls_setup,
	.start		= ehci_run,
	.stop		= ehci_stop,
	.shutdown	= ehci_shutdown,

	.urb_enqueue	= ehci_urb_enqueue,
	.urb_dequeue	= ehci_urb_dequeue,
	.endpoint_disable = ehci_endpoint_disable,
	.endpoint_reset	= ehci_endpoint_reset,

	.get_frame_number = ehci_get_frame,

	.hub_status_data = ehci_hub_status_data,
	.hub_control	= ehci_hub_control,
	.bus_suspend	= ehci_bus_suspend,
	.bus_resume	= ehci_bus_resume,
	.relinquish_port = ehci_relinquish_port,
	.port_handed_over = ehci_port_handed_over,

	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};

static int ehci_xls_probe(struct platform_device *pdev)
{
	if (usb_disabled())
		return -ENODEV;

	return ehci_xls_probe_internal(&ehci_xls_hc_driver, pdev);
}

static int ehci_xls_remove(struct platform_device *pdev)
{
	struct usb_hcd *hcd = platform_get_drvdata(pdev);

	usb_remove_hcd(hcd);
	iounmap(hcd->regs);
	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
	usb_put_hcd(hcd);
	return 0;
}

MODULE_ALIAS("ehci-xls");

static struct platform_driver ehci_xls_driver = {
	.probe		= ehci_xls_probe,
	.remove		= ehci_xls_remove,
	.shutdown	= usb_hcd_platform_shutdown,
	.driver		= {
		.name = "ehci-xls",
	},
};