Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1/*
  2 * ci13xxx_pci.c - MIPS USB IP core family device controller
  3 *
  4 * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
  5 *
  6 * Author: David Lopo
  7 *
  8 * This program is free software; you can redistribute it and/or modify
  9 * it under the terms of the GNU General Public License version 2 as
 10 * published by the Free Software Foundation.
 11 */
 12
 13#include <linux/platform_device.h>
 14#include <linux/module.h>
 15#include <linux/pci.h>
 16#include <linux/interrupt.h>
 17#include <linux/usb/gadget.h>
 18#include <linux/usb/chipidea.h>
 19
 20/* driver name */
 21#define UDC_DRIVER_NAME   "ci13xxx_pci"
 22
 23/******************************************************************************
 24 * PCI block
 25 *****************************************************************************/
 26struct ci13xxx_udc_driver pci_driver = {
 27	.name		= UDC_DRIVER_NAME,
 28	.capoffset	= DEF_CAPOFFSET,
 29};
 30
 31struct ci13xxx_udc_driver langwell_pci_driver = {
 32	.name		= UDC_DRIVER_NAME,
 33	.capoffset	= 0,
 34};
 35
 36struct ci13xxx_udc_driver penwell_pci_driver = {
 37	.name		= UDC_DRIVER_NAME,
 38	.capoffset	= 0,
 39	.power_budget	= 200,
 40};
 41
 42/**
 43 * ci13xxx_pci_probe: PCI probe
 44 * @pdev: USB device controller being probed
 45 * @id:   PCI hotplug ID connecting controller to UDC framework
 46 *
 47 * This function returns an error code
 48 * Allocates basic PCI resources for this USB device controller, and then
 49 * invokes the udc_probe() method to start the UDC associated with it
 50 */
 51static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
 52				       const struct pci_device_id *id)
 53{
 54	struct ci13xxx_udc_driver *driver = (void *)id->driver_data;
 55	struct platform_device *plat_ci;
 56	struct resource res[3];
 57	int retval = 0, nres = 2;
 58
 59	if (!driver) {
 60		dev_err(&pdev->dev, "device doesn't provide driver data\n");
 61		return -ENODEV;
 62	}
 63
 64	retval = pci_enable_device(pdev);
 65	if (retval)
 66		goto done;
 67
 68	if (!pdev->irq) {
 69		dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!");
 70		retval = -ENODEV;
 71		goto disable_device;
 72	}
 73
 74	pci_set_power_state(pdev, PCI_D0);
 75	pci_set_master(pdev);
 76	pci_try_set_mwi(pdev);
 77
 78	plat_ci = platform_device_alloc("ci_hdrc", -1);
 79	if (!plat_ci) {
 80		dev_err(&pdev->dev, "can't allocate ci_hdrc platform device\n");
 81		retval = -ENOMEM;
 82		goto disable_device;
 83	}
 84
 85	memset(res, 0, sizeof(res));
 86	res[0].start	= pci_resource_start(pdev, 0);
 87	res[0].end	= pci_resource_end(pdev, 0);
 88	res[0].flags	= IORESOURCE_MEM;
 89	res[1].start	= pdev->irq;
 90	res[1].flags	= IORESOURCE_IRQ;
 91
 92	retval = platform_device_add_resources(plat_ci, res, nres);
 93	if (retval) {
 94		dev_err(&pdev->dev, "can't add resources to platform device\n");
 95		goto put_platform;
 96	}
 97
 98	retval = platform_device_add_data(plat_ci, driver, sizeof(*driver));
 99	if (retval)
100		goto put_platform;
101
102	dma_set_coherent_mask(&plat_ci->dev, pdev->dev.coherent_dma_mask);
103	plat_ci->dev.dma_mask = pdev->dev.dma_mask;
104	plat_ci->dev.dma_parms = pdev->dev.dma_parms;
105	plat_ci->dev.parent = &pdev->dev;
106
107	pci_set_drvdata(pdev, plat_ci);
108
109	retval = platform_device_add(plat_ci);
110	if (retval)
111		goto put_platform;
112
113	return 0;
114
115 put_platform:
116	pci_set_drvdata(pdev, NULL);
117	platform_device_put(plat_ci);
118 disable_device:
119	pci_disable_device(pdev);
120 done:
121	return retval;
122}
123
124/**
125 * ci13xxx_pci_remove: PCI remove
126 * @pdev: USB Device Controller being removed
127 *
128 * Reverses the effect of ci13xxx_pci_probe(),
129 * first invoking the udc_remove() and then releases
130 * all PCI resources allocated for this USB device controller
131 */
132static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
133{
134	struct platform_device *plat_ci = pci_get_drvdata(pdev);
135
136	platform_device_unregister(plat_ci);
137	pci_set_drvdata(pdev, NULL);
138	pci_disable_device(pdev);
139}
140
141/**
142 * PCI device table
143 * PCI device structure
144 *
145 * Check "pci.h" for details
146 */
147static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = {
148	{
149		PCI_DEVICE(0x153F, 0x1004),
150		.driver_data = (kernel_ulong_t)&pci_driver,
151	},
152	{
153		PCI_DEVICE(0x153F, 0x1006),
154		.driver_data = (kernel_ulong_t)&pci_driver,
155	},
156	{
157		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811),
158		.driver_data = (kernel_ulong_t)&langwell_pci_driver,
159	},
160	{
161		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829),
162		.driver_data = (kernel_ulong_t)&penwell_pci_driver,
163	},
164	{ 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ }
165};
166MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table);
167
168static struct pci_driver ci13xxx_pci_driver = {
169	.name         =	UDC_DRIVER_NAME,
170	.id_table     =	ci13xxx_pci_id_table,
171	.probe        =	ci13xxx_pci_probe,
172	.remove       =	__devexit_p(ci13xxx_pci_remove),
173};
174
175module_pci_driver(ci13xxx_pci_driver);
176
177MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
178MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
179MODULE_LICENSE("GPL");
180MODULE_VERSION("June 2008");