Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.4-rc5 176 lines 4.3 kB view raw
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/module.h> 14#include <linux/pci.h> 15 16#include "ci13xxx_udc.c" 17 18/* driver name */ 19#define UDC_DRIVER_NAME "ci13xxx_pci" 20 21/****************************************************************************** 22 * PCI block 23 *****************************************************************************/ 24/** 25 * ci13xxx_pci_irq: interrut handler 26 * @irq: irq number 27 * @pdev: USB Device Controller interrupt source 28 * 29 * This function returns IRQ_HANDLED if the IRQ has been handled 30 * This is an ISR don't trace, use attribute interface instead 31 */ 32static irqreturn_t ci13xxx_pci_irq(int irq, void *pdev) 33{ 34 if (irq == 0) { 35 dev_err(&((struct pci_dev *)pdev)->dev, "Invalid IRQ0 usage!"); 36 return IRQ_HANDLED; 37 } 38 return udc_irq(); 39} 40 41static struct ci13xxx_udc_driver ci13xxx_pci_udc_driver = { 42 .name = UDC_DRIVER_NAME, 43}; 44 45/** 46 * ci13xxx_pci_probe: PCI probe 47 * @pdev: USB device controller being probed 48 * @id: PCI hotplug ID connecting controller to UDC framework 49 * 50 * This function returns an error code 51 * Allocates basic PCI resources for this USB device controller, and then 52 * invokes the udc_probe() method to start the UDC associated with it 53 */ 54static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev, 55 const struct pci_device_id *id) 56{ 57 void __iomem *regs = NULL; 58 int retval = 0; 59 60 if (id == NULL) 61 return -EINVAL; 62 63 retval = pci_enable_device(pdev); 64 if (retval) 65 goto done; 66 67 if (!pdev->irq) { 68 dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!"); 69 retval = -ENODEV; 70 goto disable_device; 71 } 72 73 retval = pci_request_regions(pdev, UDC_DRIVER_NAME); 74 if (retval) 75 goto disable_device; 76 77 /* BAR 0 holds all the registers */ 78 regs = pci_iomap(pdev, 0, 0); 79 if (!regs) { 80 dev_err(&pdev->dev, "Error mapping memory!"); 81 retval = -EFAULT; 82 goto release_regions; 83 } 84 pci_set_drvdata(pdev, (__force void *)regs); 85 86 pci_set_master(pdev); 87 pci_try_set_mwi(pdev); 88 89 retval = udc_probe(&ci13xxx_pci_udc_driver, &pdev->dev, regs); 90 if (retval) 91 goto iounmap; 92 93 /* our device does not have MSI capability */ 94 95 retval = request_irq(pdev->irq, ci13xxx_pci_irq, IRQF_SHARED, 96 UDC_DRIVER_NAME, pdev); 97 if (retval) 98 goto gadget_remove; 99 100 return 0; 101 102 gadget_remove: 103 udc_remove(); 104 iounmap: 105 pci_iounmap(pdev, regs); 106 release_regions: 107 pci_release_regions(pdev); 108 disable_device: 109 pci_disable_device(pdev); 110 done: 111 return retval; 112} 113 114/** 115 * ci13xxx_pci_remove: PCI remove 116 * @pdev: USB Device Controller being removed 117 * 118 * Reverses the effect of ci13xxx_pci_probe(), 119 * first invoking the udc_remove() and then releases 120 * all PCI resources allocated for this USB device controller 121 */ 122static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev) 123{ 124 free_irq(pdev->irq, pdev); 125 udc_remove(); 126 pci_iounmap(pdev, (__force void __iomem *)pci_get_drvdata(pdev)); 127 pci_release_regions(pdev); 128 pci_disable_device(pdev); 129} 130 131/** 132 * PCI device table 133 * PCI device structure 134 * 135 * Check "pci.h" for details 136 */ 137static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = { 138 { PCI_DEVICE(0x153F, 0x1004) }, 139 { PCI_DEVICE(0x153F, 0x1006) }, 140 { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ } 141}; 142MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table); 143 144static struct pci_driver ci13xxx_pci_driver = { 145 .name = UDC_DRIVER_NAME, 146 .id_table = ci13xxx_pci_id_table, 147 .probe = ci13xxx_pci_probe, 148 .remove = __devexit_p(ci13xxx_pci_remove), 149}; 150 151/** 152 * ci13xxx_pci_init: module init 153 * 154 * Driver load 155 */ 156static int __init ci13xxx_pci_init(void) 157{ 158 return pci_register_driver(&ci13xxx_pci_driver); 159} 160module_init(ci13xxx_pci_init); 161 162/** 163 * ci13xxx_pci_exit: module exit 164 * 165 * Driver unload 166 */ 167static void __exit ci13xxx_pci_exit(void) 168{ 169 pci_unregister_driver(&ci13xxx_pci_driver); 170} 171module_exit(ci13xxx_pci_exit); 172 173MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>"); 174MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller"); 175MODULE_LICENSE("GPL"); 176MODULE_VERSION("June 2008");