diff options
author | Mika Westerberg <mika.westerberg@linux.intel.com> | 2013-01-07 05:44:33 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-01-08 06:00:32 -0500 |
commit | 851bacf5902cad15f9bb789d278a1ee9608c8f25 (patch) | |
tree | 521b8652658684d9a6ff1ad5a7263d361c77114a | |
parent | 0202775bc3a28f2436ea6ee13ef3eb0e8f237857 (diff) |
spi/pxa2xx: embed the ssp_device to platform data
The spi-pxa2xx-pci glue driver had to implement pxa_ssp_request()/free() in
order to support the spi-pxa2xx platform driver. Since the ACPI enabled
platforms can use the same platform driver we would need to implement
pxa_ssp_request()/free() in some central place that can be shared by the
ACPI and PCI glue code.
Instead of doing that we can make pxa_ssp_request()/free() to be available
only when CONFIG_ARCH_PXA is set. On other arches these are being stubbed
out in preference to passing the ssp_device from the platform data
directly.
We also change the SPI bus number to be taken from ssp->port_id instead of
platform device id. This way the supporting code that passes the ssp can
decide the number (or it can set it to the same as pdev->id).
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | drivers/spi/spi-pxa2xx-pci.c | 73 | ||||
-rw-r--r-- | drivers/spi/spi-pxa2xx.c | 15 | ||||
-rw-r--r-- | include/linux/pxa2xx_ssp.h | 9 | ||||
-rw-r--r-- | include/linux/spi/pxa2xx_spi.h | 3 |
4 files changed, 28 insertions, 72 deletions
diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index ece979e9c642..364964d2ed04 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c | |||
@@ -8,55 +8,11 @@ | |||
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/spi/pxa2xx_spi.h> | 9 | #include <linux/spi/pxa2xx_spi.h> |
10 | 10 | ||
11 | struct ce4100_info { | ||
12 | struct ssp_device ssp; | ||
13 | struct platform_device *spi_pdev; | ||
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 | } | ||
40 | EXPORT_SYMBOL_GPL(pxa_ssp_request); | ||
41 | |||
42 | void pxa_ssp_free(struct ssp_device *ssp) | ||
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 | } | ||
52 | EXPORT_SYMBOL_GPL(pxa_ssp_free); | ||
53 | |||
54 | static int ce4100_spi_probe(struct pci_dev *dev, | 11 | static int ce4100_spi_probe(struct pci_dev *dev, |
55 | const struct pci_device_id *ent) | 12 | const struct pci_device_id *ent) |
56 | { | 13 | { |
57 | struct platform_device_info pi; | 14 | struct platform_device_info pi; |
58 | int ret; | 15 | int ret; |
59 | struct ce4100_info *spi_info; | ||
60 | struct platform_device *pdev; | 16 | struct platform_device *pdev; |
61 | struct pxa2xx_spi_master spi_pdata; | 17 | struct pxa2xx_spi_master spi_pdata; |
62 | struct ssp_device *ssp; | 18 | struct ssp_device *ssp; |
@@ -69,14 +25,10 @@ static int ce4100_spi_probe(struct pci_dev *dev, | |||
69 | if (!ret) | 25 | if (!ret) |
70 | return ret; | 26 | return ret; |
71 | 27 | ||
72 | spi_info = devm_kzalloc(&dev->dev, sizeof(*spi_info), GFP_KERNEL); | ||
73 | if (!spi_info) | ||
74 | return -ENOMEM; | ||
75 | |||
76 | memset(&spi_pdata, 0, sizeof(spi_pdata)); | 28 | memset(&spi_pdata, 0, sizeof(spi_pdata)); |
77 | spi_pdata.num_chipselect = dev->devfn; | 29 | spi_pdata.num_chipselect = dev->devfn; |
78 | 30 | ||
79 | ssp = &spi_info->ssp; | 31 | ssp = &spi_pdata.ssp; |
80 | ssp->phys_base = pci_resource_start(dev, 0); | 32 | ssp->phys_base = pci_resource_start(dev, 0); |
81 | ssp->mmio_base = pcim_iomap_table(dev)[0]; | 33 | ssp->mmio_base = pcim_iomap_table(dev)[0]; |
82 | if (!ssp->mmio_base) { | 34 | if (!ssp->mmio_base) { |
@@ -87,10 +39,6 @@ static int ce4100_spi_probe(struct pci_dev *dev, | |||
87 | ssp->port_id = dev->devfn; | 39 | ssp->port_id = dev->devfn; |
88 | ssp->type = PXA25x_SSP; | 40 | ssp->type = PXA25x_SSP; |
89 | 41 | ||
90 | mutex_lock(&ssp_lock); | ||
91 | list_add(&ssp->node, &ssp_list); | ||
92 | mutex_unlock(&ssp_lock); | ||
93 | |||
94 | memset(&pi, 0, sizeof(pi)); | 42 | memset(&pi, 0, sizeof(pi)); |
95 | pi.parent = &dev->dev; | 43 | pi.parent = &dev->dev; |
96 | pi.name = "pxa2xx-spi"; | 44 | pi.name = "pxa2xx-spi"; |
@@ -99,30 +47,19 @@ static int ce4100_spi_probe(struct pci_dev *dev, | |||
99 | pi.size_data = sizeof(spi_pdata); | 47 | pi.size_data = sizeof(spi_pdata); |
100 | 48 | ||
101 | pdev = platform_device_register_full(&pi); | 49 | pdev = platform_device_register_full(&pi); |
102 | if (!pdev) { | 50 | if (!pdev) |
103 | mutex_lock(&ssp_lock); | ||
104 | list_del(&ssp->node); | ||
105 | mutex_unlock(&ssp_lock); | ||
106 | |||
107 | return -ENOMEM; | 51 | return -ENOMEM; |
108 | } | ||
109 | 52 | ||
110 | spi_info->spi_pdev = pdev; | 53 | pci_set_drvdata(dev, pdev); |
111 | pci_set_drvdata(dev, spi_info); | ||
112 | 54 | ||
113 | return 0; | 55 | return 0; |
114 | } | 56 | } |
115 | 57 | ||
116 | static void ce4100_spi_remove(struct pci_dev *dev) | 58 | static void ce4100_spi_remove(struct pci_dev *dev) |
117 | { | 59 | { |
118 | struct ce4100_info *spi_info = pci_get_drvdata(dev); | 60 | struct platform_device *pdev = pci_get_drvdata(dev); |
119 | struct ssp_device *ssp = &spi_info->ssp; | ||
120 | |||
121 | platform_device_unregister(spi_info->spi_pdev); | ||
122 | 61 | ||
123 | mutex_lock(&ssp_lock); | 62 | platform_device_unregister(pdev); |
124 | list_del(&ssp->node); | ||
125 | mutex_unlock(&ssp_lock); | ||
126 | } | 63 | } |
127 | 64 | ||
128 | static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = { | 65 | static DEFINE_PCI_DEVICE_TABLE(ce4100_spi_devices) = { |
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 5c8c4f5883c4..54097ad76356 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c | |||
@@ -1535,11 +1535,18 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) | |||
1535 | struct ssp_device *ssp; | 1535 | struct ssp_device *ssp; |
1536 | int status; | 1536 | int status; |
1537 | 1537 | ||
1538 | platform_info = dev->platform_data; | 1538 | platform_info = dev_get_platdata(dev); |
1539 | if (!platform_info) { | ||
1540 | dev_err(&pdev->dev, "missing platform data\n"); | ||
1541 | return -ENODEV; | ||
1542 | } | ||
1539 | 1543 | ||
1540 | ssp = pxa_ssp_request(pdev->id, pdev->name); | 1544 | ssp = pxa_ssp_request(pdev->id, pdev->name); |
1541 | if (ssp == NULL) { | 1545 | if (!ssp) |
1542 | dev_err(&pdev->dev, "failed to request SSP%d\n", pdev->id); | 1546 | ssp = &platform_info->ssp; |
1547 | |||
1548 | if (!ssp->mmio_base) { | ||
1549 | dev_err(&pdev->dev, "failed to get ssp\n"); | ||
1543 | return -ENODEV; | 1550 | return -ENODEV; |
1544 | } | 1551 | } |
1545 | 1552 | ||
@@ -1561,7 +1568,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) | |||
1561 | /* the spi->mode bits understood by this driver: */ | 1568 | /* the spi->mode bits understood by this driver: */ |
1562 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | 1569 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; |
1563 | 1570 | ||
1564 | master->bus_num = pdev->id; | 1571 | master->bus_num = ssp->port_id; |
1565 | master->num_chipselect = platform_info->num_chipselect; | 1572 | master->num_chipselect = platform_info->num_chipselect; |
1566 | master->dma_alignment = DMA_ALIGNMENT; | 1573 | master->dma_alignment = DMA_ALIGNMENT; |
1567 | master->cleanup = cleanup; | 1574 | master->cleanup = cleanup; |
diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h index f36632061c66..065e7f6c3ad7 100644 --- a/include/linux/pxa2xx_ssp.h +++ b/include/linux/pxa2xx_ssp.h | |||
@@ -206,6 +206,15 @@ static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg) | |||
206 | return __raw_readl(dev->mmio_base + reg); | 206 | return __raw_readl(dev->mmio_base + reg); |
207 | } | 207 | } |
208 | 208 | ||
209 | #ifdef CONFIG_ARCH_PXA | ||
209 | struct ssp_device *pxa_ssp_request(int port, const char *label); | 210 | struct ssp_device *pxa_ssp_request(int port, const char *label); |
210 | void pxa_ssp_free(struct ssp_device *); | 211 | void pxa_ssp_free(struct ssp_device *); |
212 | #else | ||
213 | static inline struct ssp_device *pxa_ssp_request(int port, const char *label) | ||
214 | { | ||
215 | return NULL; | ||
216 | } | ||
217 | static inline void pxa_ssp_free(struct ssp_device *ssp) {} | ||
218 | #endif | ||
219 | |||
211 | #endif | 220 | #endif |
diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h index c73d1445c77e..6b99f09b717d 100644 --- a/include/linux/spi/pxa2xx_spi.h +++ b/include/linux/spi/pxa2xx_spi.h | |||
@@ -28,6 +28,9 @@ struct pxa2xx_spi_master { | |||
28 | u32 clock_enable; | 28 | u32 clock_enable; |
29 | u16 num_chipselect; | 29 | u16 num_chipselect; |
30 | u8 enable_dma; | 30 | u8 enable_dma; |
31 | |||
32 | /* For non-PXA arches */ | ||
33 | struct ssp_device ssp; | ||
31 | }; | 34 | }; |
32 | 35 | ||
33 | /* spi_board_info.controller_data for SPI slave devices, | 36 | /* spi_board_info.controller_data for SPI slave devices, |