Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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 __devinit
 15cns3xxx_ohci_start(struct usb_hcd *hcd)
 16{
 17	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
 18	int ret;
 19
 20	/*
 21	 * EHCI and OHCI share the same clock and power,
 22	 * resetting twice would cause the 1st controller been reset.
 23	 * Therefore only do power up  at the first up device, and
 24	 * power down at the last down device.
 25	 *
 26	 * Set USB AHB INCR length to 16
 27	 */
 28	if (atomic_inc_return(&usb_pwr_ref) == 1) {
 29		cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
 30		cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
 31		cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
 32		__raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
 33			MISC_CHIP_CONFIG_REG);
 34	}
 35
 36	ret = ohci_init(ohci);
 37	if (ret < 0)
 38		return ret;
 39
 40	ohci->num_ports = 1;
 41
 42	ret = ohci_run(ohci);
 43	if (ret < 0) {
 44		err("can't start %s", hcd->self.bus_name);
 45		ohci_stop(hcd);
 46		return ret;
 47	}
 48	return 0;
 49}
 50
 51static const struct hc_driver cns3xxx_ohci_hc_driver = {
 52	.description		= hcd_name,
 53	.product_desc		= "CNS3XXX OHCI Host controller",
 54	.hcd_priv_size		= sizeof(struct ohci_hcd),
 55	.irq			= ohci_irq,
 56	.flags			= HCD_USB11 | HCD_MEMORY,
 57	.start			= cns3xxx_ohci_start,
 58	.stop			= ohci_stop,
 59	.shutdown		= ohci_shutdown,
 60	.urb_enqueue		= ohci_urb_enqueue,
 61	.urb_dequeue		= ohci_urb_dequeue,
 62	.endpoint_disable	= ohci_endpoint_disable,
 63	.get_frame_number	= ohci_get_frame,
 64	.hub_status_data	= ohci_hub_status_data,
 65	.hub_control		= ohci_hub_control,
 66#ifdef CONFIG_PM
 67	.bus_suspend		= ohci_bus_suspend,
 68	.bus_resume		= ohci_bus_resume,
 69#endif
 70	.start_port_reset	= ohci_start_port_reset,
 71};
 72
 73static int cns3xxx_ohci_probe(struct platform_device *pdev)
 74{
 75	struct device *dev = &pdev->dev;
 76	struct usb_hcd *hcd;
 77	const struct hc_driver *driver = &cns3xxx_ohci_hc_driver;
 78	struct resource *res;
 79	int irq;
 80	int retval;
 81
 82	if (usb_disabled())
 83		return -ENODEV;
 84
 85	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 86	if (!res) {
 87		dev_err(dev, "Found HC with no IRQ.\n");
 88		return -ENODEV;
 89	}
 90	irq = res->start;
 91
 92	hcd = usb_create_hcd(driver, dev, dev_name(dev));
 93	if (!hcd)
 94		return -ENOMEM;
 95
 96	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 97	if (!res) {
 98		dev_err(dev, "Found HC with no register addr.\n");
 99		retval = -ENODEV;
100		goto err1;
101	}
102	hcd->rsrc_start = res->start;
103	hcd->rsrc_len = resource_size(res);
104
105	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
106			driver->description)) {
107		dev_dbg(dev, "controller already in use\n");
108		retval = -EBUSY;
109		goto err1;
110	}
111
112	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
113	if (!hcd->regs) {
114		dev_dbg(dev, "error mapping memory\n");
115		retval = -EFAULT;
116		goto err2;
117	}
118
119	ohci_hcd_init(hcd_to_ohci(hcd));
120
121	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
122	if (retval == 0)
123		return retval;
124
125	iounmap(hcd->regs);
126err2:
127	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
128err1:
129	usb_put_hcd(hcd);
130	return retval;
131}
132
133static int cns3xxx_ohci_remove(struct platform_device *pdev)
134{
135	struct usb_hcd *hcd = platform_get_drvdata(pdev);
136
137	usb_remove_hcd(hcd);
138	iounmap(hcd->regs);
139	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
140
141	/*
142	 * EHCI and OHCI share the same clock and power,
143	 * resetting twice would cause the 1st controller been reset.
144	 * Therefore only do power up  at the first up device, and
145	 * power down at the last down device.
146	 */
147	if (atomic_dec_return(&usb_pwr_ref) == 0)
148		cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
149
150	usb_put_hcd(hcd);
151
152	platform_set_drvdata(pdev, NULL);
153
154	return 0;
155}
156
157MODULE_ALIAS("platform:cns3xxx-ohci");
158
159static struct platform_driver ohci_hcd_cns3xxx_driver = {
160	.probe = cns3xxx_ohci_probe,
161	.remove = cns3xxx_ohci_remove,
162	.driver = {
163		.name = "cns3xxx-ohci",
164	},
165};