Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
spi-pxa2xx-pci.c
Go to the documentation of this file.
1 /*
2  * CE4100's SPI device is more or less the same one as found on PXA
3  *
4  */
5 #include <linux/pci.h>
7 #include <linux/of_device.h>
8 #include <linux/module.h>
9 #include <linux/spi/pxa2xx_spi.h>
10 
11 struct ce4100_info {
12  struct ssp_device ssp;
14 };
15 
16 static DEFINE_MUTEX(ssp_lock);
17 static LIST_HEAD(ssp_list);
18 
19 struct ssp_device *pxa_ssp_request(int port, const char *label)
20 {
21  struct ssp_device *ssp = NULL;
22 
23  mutex_lock(&ssp_lock);
24 
25  list_for_each_entry(ssp, &ssp_list, node) {
26  if (ssp->port_id == port && ssp->use_count == 0) {
27  ssp->use_count++;
28  ssp->label = label;
29  break;
30  }
31  }
32 
33  mutex_unlock(&ssp_lock);
34 
35  if (&ssp->node == &ssp_list)
36  return NULL;
37 
38  return ssp;
39 }
41 
43 {
44  mutex_lock(&ssp_lock);
45  if (ssp->use_count) {
46  ssp->use_count--;
47  ssp->label = NULL;
48  } else
49  dev_err(&ssp->pdev->dev, "device already free\n");
50  mutex_unlock(&ssp_lock);
51 }
53 
54 static int __devinit ce4100_spi_probe(struct pci_dev *dev,
55  const struct pci_device_id *ent)
56 {
57  int ret;
58  resource_size_t phys_beg;
59  resource_size_t phys_len;
60  struct ce4100_info *spi_info;
61  struct platform_device *pdev;
62  struct pxa2xx_spi_master spi_pdata;
63  struct ssp_device *ssp;
64 
65  ret = pci_enable_device(dev);
66  if (ret)
67  return ret;
68 
69  phys_beg = pci_resource_start(dev, 0);
70  phys_len = pci_resource_len(dev, 0);
71 
72  if (!request_mem_region(phys_beg, phys_len,
73  "CE4100 SPI")) {
74  dev_err(&dev->dev, "Can't request register space.\n");
75  ret = -EBUSY;
76  return ret;
77  }
78 
79  pdev = platform_device_alloc("pxa2xx-spi", dev->devfn);
80  spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL);
81  if (!pdev || !spi_info ) {
82  ret = -ENOMEM;
83  goto err_nomem;
84  }
85  memset(&spi_pdata, 0, sizeof(spi_pdata));
86  spi_pdata.num_chipselect = dev->devfn;
87 
88  ret = platform_device_add_data(pdev, &spi_pdata, sizeof(spi_pdata));
89  if (ret)
90  goto err_nomem;
91 
92  pdev->dev.parent = &dev->dev;
93  pdev->dev.of_node = dev->dev.of_node;
94  ssp = &spi_info->ssp;
95  ssp->phys_base = pci_resource_start(dev, 0);
96  ssp->mmio_base = ioremap(phys_beg, phys_len);
97  if (!ssp->mmio_base) {
98  dev_err(&pdev->dev, "failed to ioremap() registers\n");
99  ret = -EIO;
100  goto err_nomem;
101  }
102  ssp->irq = dev->irq;
103  ssp->port_id = pdev->id;
104  ssp->type = PXA25x_SSP;
105 
106  mutex_lock(&ssp_lock);
107  list_add(&ssp->node, &ssp_list);
108  mutex_unlock(&ssp_lock);
109 
110  pci_set_drvdata(dev, spi_info);
111 
112  ret = platform_device_add(pdev);
113  if (ret)
114  goto err_dev_add;
115 
116  return ret;
117 
118 err_dev_add:
119  pci_set_drvdata(dev, NULL);
120  mutex_lock(&ssp_lock);
121  list_del(&ssp->node);
122  mutex_unlock(&ssp_lock);
123  iounmap(ssp->mmio_base);
124 
125 err_nomem:
126  release_mem_region(phys_beg, phys_len);
127  platform_device_put(pdev);
128  kfree(spi_info);
129  return ret;
130 }
131 
132 static void __devexit ce4100_spi_remove(struct pci_dev *dev)
133 {
134  struct ce4100_info *spi_info;
135  struct ssp_device *ssp;
136 
137  spi_info = pci_get_drvdata(dev);
138  ssp = &spi_info->ssp;
140 
141  iounmap(ssp->mmio_base);
143  pci_resource_len(dev, 0));
144 
145  mutex_lock(&ssp_lock);
146  list_del(&ssp->node);
147  mutex_unlock(&ssp_lock);
148 
149  pci_set_drvdata(dev, NULL);
150  pci_disable_device(dev);
151  kfree(spi_info);
152 }
153 
154 static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = {
155  { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) },
156  { },
157 };
158 MODULE_DEVICE_TABLE(pci, ce4100_spi_devices);
159 
160 static struct pci_driver ce4100_spi_driver = {
161  .name = "ce4100_spi",
162  .id_table = ce4100_spi_devices,
163  .probe = ce4100_spi_probe,
164  .remove = __devexit_p(ce4100_spi_remove),
165 };
166 
167 module_pci_driver(ce4100_spi_driver);
168 
169 MODULE_DESCRIPTION("CE4100 PCI-SPI glue code for PXA's driver");
170 MODULE_LICENSE("GPL v2");
171 MODULE_AUTHOR("Sebastian Andrzej Siewior <[email protected]>");