Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
  1/*
  2 * Copyright 2008 Cavium Networks
  3 *
  4 * This file is free software; you can redistribute it and/or modify
  5 * it under the terms of the GNU General Public License, Version 2, as
  6 * published by the Free Software Foundation.
  7 */
  8
  9#include <linux/platform_device.h>
 10#include <linux/atomic.h>
 11#include <mach/cns3xxx.h>
 12#include <mach/pm.h>
 13
 14static int cns3xxx_ehci_init(struct usb_hcd *hcd)
 15{
 16	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 17	int retval;
 18
 19	/*
 20	 * EHCI and OHCI share the same clock and power,
 21	 * resetting twice would cause the 1st controller been reset.
 22	 * Therefore only do power up  at the first up device, and
 23	 * power down at the last down device.
 24	 *
 25	 * Set USB AHB INCR length to 16
 26	 */
 27	if (atomic_inc_return(&usb_pwr_ref) == 1) {
 28		cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
 29		cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
 30		cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
 31		__raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
 32			MISC_CHIP_CONFIG_REG);
 33	}
 34
 35	ehci->caps = hcd->regs;
 36	ehci->regs = hcd->regs
 37		+ HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
 38	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 39
 40	hcd->has_tt = 0;
 41	ehci_reset(ehci);
 42
 43	retval = ehci_init(hcd);
 44	if (retval)
 45		return retval;
 46
 47	ehci_port_power(ehci, 0);
 48
 49	return retval;
 50}
 51
 52static const struct hc_driver cns3xxx_ehci_hc_driver = {
 53	.description		= hcd_name,
 54	.product_desc		= "CNS3XXX EHCI Host Controller",
 55	.hcd_priv_size		= sizeof(struct ehci_hcd),
 56	.irq			= ehci_irq,
 57	.flags			= HCD_MEMORY | HCD_USB2,
 58	.reset			= cns3xxx_ehci_init,
 59	.start			= ehci_run,
 60	.stop			= ehci_stop,
 61	.shutdown		= ehci_shutdown,
 62	.urb_enqueue		= ehci_urb_enqueue,
 63	.urb_dequeue		= ehci_urb_dequeue,
 64	.endpoint_disable	= ehci_endpoint_disable,
 65	.endpoint_reset		= ehci_endpoint_reset,
 66	.get_frame_number	= ehci_get_frame,
 67	.hub_status_data	= ehci_hub_status_data,
 68	.hub_control		= ehci_hub_control,
 69#ifdef CONFIG_PM
 70	.bus_suspend		= ehci_bus_suspend,
 71	.bus_resume		= ehci_bus_resume,
 72#endif
 73	.relinquish_port	= ehci_relinquish_port,
 74	.port_handed_over	= ehci_port_handed_over,
 75
 76	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 77};
 78
 79static int cns3xxx_ehci_probe(struct platform_device *pdev)
 80{
 81	struct device *dev = &pdev->dev;
 82	struct usb_hcd *hcd;
 83	const struct hc_driver *driver = &cns3xxx_ehci_hc_driver;
 84	struct resource *res;
 85	int irq;
 86	int retval;
 87
 88	if (usb_disabled())
 89		return -ENODEV;
 90
 91	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 92	if (!res) {
 93		dev_err(dev, "Found HC with no IRQ.\n");
 94		return -ENODEV;
 95	}
 96	irq = res->start;
 97
 98	hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
 99	if (!hcd)
100		return -ENOMEM;
101
102	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
103	if (!res) {
104		dev_err(dev, "Found HC with no register addr.\n");
105		retval = -ENODEV;
106		goto err1;
107	}
108
109	hcd->rsrc_start = res->start;
110	hcd->rsrc_len = resource_size(res);
111
112	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
113				driver->description)) {
114		dev_dbg(dev, "controller already in use\n");
115		retval = -EBUSY;
116		goto err1;
117	}
118
119	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
120	if (hcd->regs == NULL) {
121		dev_dbg(dev, "error mapping memory\n");
122		retval = -EFAULT;
123		goto err2;
124	}
125
126	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
127	if (retval == 0)
128		return retval;
129
130	iounmap(hcd->regs);
131err2:
132	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
133err1:
134	usb_put_hcd(hcd);
135
136	return retval;
137}
138
139static int cns3xxx_ehci_remove(struct platform_device *pdev)
140{
141	struct usb_hcd *hcd = platform_get_drvdata(pdev);
142
143	usb_remove_hcd(hcd);
144	iounmap(hcd->regs);
145	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
146
147	/*
148	 * EHCI and OHCI share the same clock and power,
149	 * resetting twice would cause the 1st controller been reset.
150	 * Therefore only do power up  at the first up device, and
151	 * power down at the last down device.
152	 */
153	if (atomic_dec_return(&usb_pwr_ref) == 0)
154		cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
155
156	usb_put_hcd(hcd);
157
158	platform_set_drvdata(pdev, NULL);
159
160	return 0;
161}
162
163MODULE_ALIAS("platform:cns3xxx-ehci");
164
165static struct platform_driver cns3xxx_ehci_driver = {
166	.probe = cns3xxx_ehci_probe,
167	.remove = cns3xxx_ehci_remove,
168	.driver = {
169		.name = "cns3xxx-ehci",
170	},
171};