diff options
| -rw-r--r-- | drivers/spi/Kconfig | 13 | ||||
| -rw-r--r-- | drivers/spi/Makefile | 1 | ||||
| -rw-r--r-- | drivers/spi/pxa2xx_spi.c | 1 | ||||
| -rw-r--r-- | drivers/spi/pxa2xx_spi_pci.c | 201 | ||||
| -rw-r--r-- | include/linux/spi/pxa2xx_spi.h | 105 |
5 files changed, 314 insertions, 7 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 78f9fd02c1b..537759011d1 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
| @@ -267,12 +267,15 @@ config SPI_PPC4xx | |||
| 267 | 267 | ||
| 268 | config SPI_PXA2XX | 268 | config 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 | |||
| 277 | config SPI_PXA2XX_PCI | ||
| 278 | def_bool SPI_PXA2XX && X86_32 && PCI | ||
| 276 | 279 | ||
| 277 | config SPI_S3C24XX | 280 | config 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 8bc1a5abac1..bdc4c400fd7 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile | |||
| @@ -24,6 +24,7 @@ obj-$(CONFIG_SPI_GPIO) += spi_gpio.o | |||
| 24 | obj-$(CONFIG_SPI_IMX) += spi_imx.o | 24 | obj-$(CONFIG_SPI_IMX) += spi_imx.o |
| 25 | obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o | 25 | obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o |
| 26 | obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o | 26 | obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o |
| 27 | obj-$(CONFIG_SPI_PXA2XX_PCI) += pxa2xx_spi_pci.o | ||
| 27 | obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o | 28 | obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o |
| 28 | obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o | 29 | obj-$(CONFIG_SPI_OMAP24XX) += omap2_mcspi.o |
| 29 | obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o | 30 | obj-$(CONFIG_SPI_OMAP_100K) += omap_spi_100k.o |
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 98d9c8b0918..ed212c2583a 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 00000000000..351d8a375b5 --- /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 | |||
| 10 | struct awesome_struct { | ||
| 11 | struct ssp_device ssp; | ||
| 12 | struct platform_device spi_pdev; | ||
| 13 | struct pxa2xx_spi_master spi_pdata; | ||
| 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 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 | |||
| 62 | static 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 | |||
| 131 | err_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 | |||
| 138 | err_remap: | ||
| 139 | kfree(spi_info); | ||
| 140 | |||
| 141 | err_kz: | ||
| 142 | release_mem_region(phys_beg, phys_len); | ||
| 143 | |||
| 144 | return ret; | ||
| 145 | } | ||
| 146 | |||
| 147 | static 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), | ||
