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 v2.6.34-rc1 171 lines 4.1 kB view raw
1/* 2 * mrst_spi_pci.c - PCI interface driver for DW SPI Core 3 * 4 * Copyright (c) 2009, Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20#include <linux/interrupt.h> 21#include <linux/pci.h> 22#include <linux/spi/dw_spi.h> 23#include <linux/spi/spi.h> 24 25#define DRIVER_NAME "dw_spi_pci" 26 27struct dw_spi_pci { 28 struct pci_dev *pdev; 29 struct dw_spi dws; 30}; 31 32static int __devinit spi_pci_probe(struct pci_dev *pdev, 33 const struct pci_device_id *ent) 34{ 35 struct dw_spi_pci *dwpci; 36 struct dw_spi *dws; 37 int pci_bar = 0; 38 int ret; 39 40 printk(KERN_INFO "DW: found PCI SPI controller(ID: %04x:%04x)\n", 41 pdev->vendor, pdev->device); 42 43 ret = pci_enable_device(pdev); 44 if (ret) 45 return ret; 46 47 dwpci = kzalloc(sizeof(struct dw_spi_pci), GFP_KERNEL); 48 if (!dwpci) { 49 ret = -ENOMEM; 50 goto err_disable; 51 } 52 53 dwpci->pdev = pdev; 54 dws = &dwpci->dws; 55 56 /* Get basic io resource and map it */ 57 dws->paddr = pci_resource_start(pdev, pci_bar); 58 dws->iolen = pci_resource_len(pdev, pci_bar); 59 60 ret = pci_request_region(pdev, pci_bar, dev_name(&pdev->dev)); 61 if (ret) 62 goto err_kfree; 63 64 dws->regs = ioremap_nocache((unsigned long)dws->paddr, 65 pci_resource_len(pdev, pci_bar)); 66 if (!dws->regs) { 67 ret = -ENOMEM; 68 goto err_release_reg; 69 } 70 71 dws->parent_dev = &pdev->dev; 72 dws->bus_num = 0; 73 dws->num_cs = 4; 74 dws->max_freq = 25000000; /* for Moorestwon */ 75 dws->irq = pdev->irq; 76 dws->fifo_len = 40; /* FIFO has 40 words buffer */ 77 78 ret = dw_spi_add_host(dws); 79 if (ret) 80 goto err_unmap; 81 82 /* PCI hook and SPI hook use the same drv data */ 83 pci_set_drvdata(pdev, dwpci); 84 return 0; 85 86err_unmap: 87 iounmap(dws->regs); 88err_release_reg: 89 pci_release_region(pdev, pci_bar); 90err_kfree: 91 kfree(dwpci); 92err_disable: 93 pci_disable_device(pdev); 94 return ret; 95} 96 97static void __devexit spi_pci_remove(struct pci_dev *pdev) 98{ 99 struct dw_spi_pci *dwpci = pci_get_drvdata(pdev); 100 101 pci_set_drvdata(pdev, NULL); 102 dw_spi_remove_host(&dwpci->dws); 103 iounmap(dwpci->dws.regs); 104 pci_release_region(pdev, 0); 105 kfree(dwpci); 106 pci_disable_device(pdev); 107} 108 109#ifdef CONFIG_PM 110static int spi_suspend(struct pci_dev *pdev, pm_message_t state) 111{ 112 struct dw_spi_pci *dwpci = pci_get_drvdata(pdev); 113 int ret; 114 115 ret = dw_spi_suspend_host(&dwpci->dws); 116 if (ret) 117 return ret; 118 pci_save_state(pdev); 119 pci_disable_device(pdev); 120 pci_set_power_state(pdev, pci_choose_state(pdev, state)); 121 return ret; 122} 123 124static int spi_resume(struct pci_dev *pdev) 125{ 126 struct dw_spi_pci *dwpci = pci_get_drvdata(pdev); 127 int ret; 128 129 pci_set_power_state(pdev, PCI_D0); 130 pci_restore_state(pdev); 131 ret = pci_enable_device(pdev); 132 if (ret) 133 return ret; 134 return dw_spi_resume_host(&dwpci->dws); 135} 136#else 137#define spi_suspend NULL 138#define spi_resume NULL 139#endif 140 141static const struct pci_device_id pci_ids[] __devinitdata = { 142 /* Intel Moorestown platform SPI controller 0 */ 143 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0800) }, 144 {}, 145}; 146 147static struct pci_driver dw_spi_driver = { 148 .name = DRIVER_NAME, 149 .id_table = pci_ids, 150 .probe = spi_pci_probe, 151 .remove = __devexit_p(spi_pci_remove), 152 .suspend = spi_suspend, 153 .resume = spi_resume, 154}; 155 156static int __init mrst_spi_init(void) 157{ 158 return pci_register_driver(&dw_spi_driver); 159} 160 161static void __exit mrst_spi_exit(void) 162{ 163 pci_unregister_driver(&dw_spi_driver); 164} 165 166module_init(mrst_spi_init); 167module_exit(mrst_spi_exit); 168 169MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>"); 170MODULE_DESCRIPTION("PCI interface driver for DW SPI Core"); 171MODULE_LICENSE("GPL v2");