aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2010-11-24 04:17:14 -0500
committerSebastian Andrzej Siewior <bigeasy@linutronix.de>2010-12-01 07:48:30 -0500
commitd6ea3df0d470fb9260db93883f97764cf9f0e562 (patch)
tree277838ea93d6dc0c7d2a05be757dfa1b8bedb619
parent8348c259dd6a6019a8fa01b0a3443409480f7b9d (diff)
spi/pxa2xx: Add CE4100 support
Sodaville's SPI controller is very much the same as in PXA25x. The difference: - The RX/TX FIFO is only 4 words deep instead of 16 - No DMA support - The SPI controller offers a CS functionality Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com>
-rw-r--r--drivers/spi/Kconfig13
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/pxa2xx_spi.c1
-rw-r--r--drivers/spi/pxa2xx_spi_pci.c201
-rw-r--r--include/linux/spi/pxa2xx_spi.h105
5 files changed, 314 insertions, 7 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 78f9fd02c1b2..537759011d1d 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -267,12 +267,15 @@ config SPI_PPC4xx
267 267
268config SPI_PXA2XX 268config SPI_PXA2XX
269 tristate "PXA2xx SSP SPI master" 269 tristate "PXA2xx SSP SPI master"
270 depends on ARCH_PXA && EXPERIMENTAL 270 depends on (ARCH_PXA || (X86_32 && PCI)) && EXPERIMENTAL
271 select PXA_SSP 271 select PXA_SSP if ARCH_PXA
272 help 272 help
273 This enables using a PXA2xx SSP port as a SPI master controller. 273 This enables using a PXA2xx or Sodaville SSP port as a SPI master
274 The driver can be configured to use any SSP port and additional 274 controller. The driver can be configured to use any SSP port and
275 documentation can be found a Documentation/spi/pxa2xx. 275 additional documentation can be found a Documentation/spi/pxa2xx.
276
277config SPI_PXA2XX_PCI
278 def_bool SPI_PXA2XX && X86_32 && PCI
276 279
277config SPI_S3C24XX 280config SPI_S3C24XX
278 tristate "Samsung S3C24XX series SPI" 281 tristate "Samsung S3C24XX series SPI"
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 8bc1a5abac1f..bdc4c400fd71 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
24obj-$(CONFIG_SPI_IMX) += spi_imx.o 24obj-$(CONFIG_SPI_IMX) += spi_imx.o
25obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o 25obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o
26obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o 26obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o
27obj-$(CONFIG_SPI_PXA2XX_PCI) += pxa2xx_spi_pci.o
27obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o 28obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o
28obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o 29obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o
29obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o 30obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 98d9c8b09182..ed212c2583ab 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -28,7 +28,6 @@
28#include <linux/spi/spi.h> 28#include <linux/spi/spi.h>
29#include <linux/workqueue.h> 29#include <linux/workqueue.h>
30#include <linux/delay.h> 30#include <linux/delay.h>
31#include <linux/clk.h>
32#include <linux/gpio.h> 31#include <linux/gpio.h>
33#include <linux/slab.h> 32#include <linux/slab.h>
34 33
diff --git a/drivers/spi/pxa2xx_spi_pci.c b/drivers/spi/pxa2xx_spi_pci.c
new file mode 100644
index 000000000000..351d8a375b57
--- /dev/null
+++ b/drivers/spi/pxa2xx_spi_pci.c
@@ -0,0 +1,201 @@
1/*
2 * CE4100's SPI device is more or less the same one as found on PXA
3 *
4 */
5#include <linux/pci.h>
6#include <linux/platform_device.h>
7#include <linux/of_device.h>
8#include <linux/spi/pxa2xx_spi.h>
9
10struct awesome_struct {
11 struct ssp_device ssp;
12 struct platform_device spi_pdev;
13 struct pxa2xx_spi_master spi_pdata;
14};
15
16static DEFINE_MUTEX(ssp_lock);
17static LIST_HEAD(ssp_list);
18
19struct 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}
40EXPORT_SYMBOL_GPL(pxa_ssp_request);
41
42void 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}
52EXPORT_SYMBOL_GPL(pxa_ssp_free);
53
54static void plat_dev_release(struct device *dev)
55{
56 struct awesome_struct *as = container_of(dev,
57 struct awesome_struct, spi_pdev.dev);
58
59 of_device_node_put(&as->spi_pdev.dev);
60}
61
62static int __devinit ce4100_spi_probe(struct pci_dev *dev,
63 const struct pci_device_id *ent)
64{
65 int ret;
66 resource_size_t phys_beg;
67 resource_size_t phys_len;
68 struct awesome_struct *spi_info;
69 struct platform_device *pdev;
70 struct pxa2xx_spi_master *spi_pdata;
71 struct ssp_device *ssp;
72
73 ret = pci_enable_device(dev);
74 if (ret)
75 return ret;
76
77 phys_beg = pci_resource_start(dev, 0);
78 phys_len = pci_resource_len(dev, 0);
79
80 if (!request_mem_region(phys_beg, phys_len,
81 "CE4100 SPI")) {
82 dev_err(&dev->dev, "Can't request register space.\n");
83 ret = -EBUSY;
84 return ret;
85 }
86
87 spi_info = kzalloc(sizeof(*spi_info), GFP_KERNEL);
88 if (!spi_info) {
89 ret = -ENOMEM;
90 goto err_kz;
91 }
92 ssp = &spi_info->ssp;
93 pdev = &spi_info->spi_pdev;
94 spi_pdata = &spi_info->spi_pdata;
95
96 pdev->name = "pxa2xx-spi";
97 pdev->id = dev->devfn;
98 pdev->dev.parent = &dev->dev;
99 pdev->dev.platform_data = &spi_info->spi_pdata;
100
101#ifdef CONFIG_OF
102 pdev->dev.of_node = dev->dev.of_node;
103#endif
104 pdev->dev.release = plat_dev_release;
105
106 spi_pdata->num_chipselect = dev->devfn;
107
108 ssp->phys_base = pci_resource_start(dev, 0);
109 ssp->mmio_base = ioremap(phys_beg, phys_len);
110 if (!ssp->mmio_base) {
111 dev_err(&pdev->dev, "failed to ioremap() registers\n");
112 ret = -EIO;
113 goto err_remap;
114 }
115 ssp->irq = dev->irq;
116 ssp->port_id = pdev->id;
117 ssp->type = PXA25x_SSP;
118
119 mutex_lock(&ssp_lock);
120 list_add(&ssp->node, &ssp_list);
121 mutex_unlock(&ssp_lock);
122
123 pci_set_drvdata(dev, spi_info);
124
125 ret = platform_device_register(pdev);
126 if (ret)
127 goto err_dev_add;
128
129 return ret;
130
131err_dev_add:
132 pci_set_drvdata(dev, NULL);
133 mutex_lock(&ssp_lock);
134 list_del(&ssp->node);
135 mutex_unlock(&ssp_lock);
136 iounmap(ssp->mmio_base);
137
138err_remap:
139 kfree(spi_info);
140
141err_kz:
142 release_mem_region(phys_beg, phys_len);
143
144 return ret;
145}
146
147static void __devexit ce4100_spi_remove(struct pci_dev *dev)
148{
149 struct awesome_struct *spi_info;
150 struct platform_device *pdev;
151 struct ssp_device *ssp;
152
153 spi_info = pci_get_drvdata(dev);
154
155 ssp = &spi_info->ssp;
156 pdev = &spi_info->spi_pdev;
157
158 platform_device_unregister(pdev);
159
160 iounmap(ssp->mmio_base);
161 release_mem_region(pci_resource_start(dev, 0),
162 pci_resource_len(dev, 0));
163
164 mutex_lock(&ssp_lock);
165 list_del(&ssp->node);
166 mutex_unlock(&ssp_lock);
167
168 pci_set_drvdata(dev, NULL);
169 pci_disable_device(dev);
170 kfree(spi_info);
171}
172
173static struct pci_device_id ce4100_spi_devices[] __devinitdata = {
174
175 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e6a) },
176 { },
177};
178MODULE_DEVICE_TABLE(pci, ce4100_spi_devices);
179
180static struct pci_driver ce4100_spi_driver = {
181 .name = "ce4100_spi",
182 .id_table = ce4100_spi_devices,
183 .probe = ce4100_spi_probe,
184 .remove = __devexit_p(ce4100_spi_remove),
185};
186
187static int __init ce4100_spi_init(void)
188{
189 return pci_register_driver(&ce4100_spi_driver);
190}
191module_init(ce4100_spi_init);
192
193static void __exit ce4100_spi_exit(void)
194{
195 pci_unregister_driver(&ce4100_spi_driver);
196}
197module_exit(ce4100_spi_exit);
198
199MODULE_DESCRIPTION("CE4100 PCI-SPI glue code for PXA's driver");
200MODULE_LICENSE("GPL v2");
201MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
diff --git a/include/linux/spi/pxa2xx_spi.h b/include/linux/spi/pxa2xx_spi.h
index 471ed6889113..d3e1075f7b60 100644
--- a/include/linux/spi/pxa2xx_spi.h
+++ b/include/linux/spi/pxa2xx_spi.h
@@ -19,7 +19,6 @@
19#define __linux_pxa2xx_spi_h 19#define __linux_pxa2xx_spi_h
20 20
21#include <linux/pxa2xx_ssp.h> 21#include <linux/pxa2xx_ssp.h>
22#include <mach/dma.h>
23 22
24#define PXA2XX_CS_ASSERT (0x01) 23#define PXA2XX_CS_ASSERT (0x01)
25#define PXA2XX_CS_DEASSERT (0x02) 24#define PXA2XX_CS_DEASSERT (0x02)
@@ -44,6 +43,110 @@ struct pxa2xx_spi_chip {
44 void (*cs_control)(u32 command); 43 void (*cs_control)(u32 command);
45}; 44};
46 45
46#ifdef CONFIG_ARCH_PXA
47
48#include <linux/clk.h>
49#include <mach/dma.h>
50
47extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info); 51extern void pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_master *info);
48 52
53#else
54/*
55 * This is the implemtation for CE4100 on x86. ARM defines them in mach/ or
56 * plat/ include path.
57 * The CE4100 does not provide DMA support. This bits are here to let the driver
58 * compile and will never be used. Maybe we get DMA support at a later point in
59 * time.
60 */
61
62#define DCSR(n) (n)
63#define DSADR(n) (n)
64#define DTADR(n) (n)
65#define DCMD(n) (n)
66#define DRCMR(n) (n)
67
68#define DCSR_RUN (1 << 31) /* Run Bit */
69#define DCSR_NODESC (1 << 30) /* No-Descriptor Fetch */
70#define DCSR_STOPIRQEN (1 << 29) /* Stop Interrupt Enable */
71#define DCSR_REQPEND (1 << 8) /* Request Pending (read-only) */
72#define DCSR_STOPSTATE (1 << 3) /* Stop State (read-only) */
73#define DCSR_ENDINTR (1 << 2) /* End Interrupt */
74#define DCSR_STARTINTR (1 << 1) /* Start Interrupt */
75#define DCSR_BUSERR (1 << 0) /* Bus Error Interrupt */
76
77#define DCSR_EORIRQEN (1 << 28) /* End of Receive Interrupt Enable */
78#define DCSR_EORJMPEN (1 << 27) /* Jump to next descriptor on EOR */
79#define DCSR_EORSTOPEN (1 << 26) /* STOP on an EOR */
80#define DCSR_SETCMPST (1 << 25) /* Set Descriptor Compare Status */
81#define DCSR_CLRCMPST (1 << 24) /* Clear Descriptor Compare Status */
82#define DCSR_CMPST (1 << 10) /* The Descriptor Compare Status */
83#define DCSR_EORINTR (1 << 9) /* The end of Receive */
84
85#define DRCMR_MAPVLD (1 << 7) /* Map Valid */
86#define DRCMR_CHLNUM 0x1f /* mask for Channel Number */
87
88#define DDADR_DESCADDR 0xfffffff0 /* Address of next descriptor */
89#define DDADR_STOP (1 << 0) /* Stop */
90
91#define DCMD_INCSRCADDR (1 << 31) /* Source Address Increment Setting. */
92#define DCMD_INCTRGADDR (1 << 30) /* Target Address Increment Setting. */
93#define DCMD_FLOWSRC (1 << 29) /* Flow Control by the source. */
94#define DCMD_FLOWTRG (1 << 28) /* Flow Control by the target. */
95#define DCMD_STARTIRQEN (1 << 22) /* Start Interrupt Enable */
96#define DCMD_ENDIRQEN (1 << 21) /* End Interrupt Enable */
97#define DCMD_ENDIAN (1 << 18) /* Device Endian-ness. */
98#define DCMD_BURST8 (1 << 16) /* 8 byte burst */
99#define DCMD_BURST16 (2 << 16) /* 16 byte burst */
100#define DCMD_BURST32 (3 << 16) /* 32 byte burst */
101#define DCMD_WIDTH1 (1 << 14) /* 1 byte width */
102#define DCMD_WIDTH2 (2 << 14) /* 2 byte width (HalfWord) */
103#define DCMD_WIDTH4 (3 << 14) /* 4 byte width (Word) */
104#define DCMD_LENGTH 0x01fff /* length mask (max = 8K - 1) */
105
106/*
107 * Descriptor structure for PXA's DMA engine
108 * Note: this structure must always be aligned to a 16-byte boundary.
109 */
110
111typedef enum {
112 DMA_PRIO_HIGH = 0,
113 DMA_PRIO_MEDIUM = 1,
114 DMA_PRIO_LOW = 2
115} pxa_dma_prio;
116
117/*
118 * DMA registration
119 */
120
121static inline int pxa_request_dma(char *name,
122 pxa_dma_prio prio,
123 void (*irq_handler)(int, void *),
124 void *data)
125{
126 return -ENODEV;
127}
128
129static inline void pxa_free_dma(int dma_ch)
130{
131}
132
133/*
134 * The CE4100 does not have the clk framework implemented and SPI clock can
135 * not be switched on/off or the divider changed.
136 */
137static inline void clk_disable(struct clk *clk)
138{
139}
140
141static inline int clk_enable(struct clk *clk)
142{
143 return 0;
144}
145
146static inline unsigned long clk_get_rate(struct clk *clk)
147{
148 return 3686400;
149}
150
151#endif
49#endif 152#endif