Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | /* * CE4100's SPI device is more or less the same one as found on PXA * */ #include <linux/pci.h> #include <linux/platform_device.h> #include <linux/of_device.h> #include <linux/module.h> #include <linux/spi/pxa2xx_spi.h> #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/dmaengine.h> #include <linux/platform_data/dma-dw.h> enum { PORT_CE4100, PORT_BYT, PORT_BSW0, PORT_BSW1, PORT_BSW2, PORT_QUARK_X1000, }; struct pxa_spi_info { enum pxa_ssp_type type; int port_id; int num_chipselect; unsigned long max_clk_rate; /* DMA channel request parameters */ void *tx_param; void *rx_param; }; static struct dw_dma_slave byt_tx_param = { .dst_id = 0 }; static struct dw_dma_slave byt_rx_param = { .src_id = 1 }; static struct dw_dma_slave bsw0_tx_param = { .dst_id = 0 }; static struct dw_dma_slave bsw0_rx_param = { .src_id = 1 }; static struct dw_dma_slave bsw1_tx_param = { .dst_id = 6 }; static struct dw_dma_slave bsw1_rx_param = { .src_id = 7 }; static struct dw_dma_slave bsw2_tx_param = { .dst_id = 8 }; static struct dw_dma_slave bsw2_rx_param = { .src_id = 9 }; static bool lpss_dma_filter(struct dma_chan *chan, void *param) { struct dw_dma_slave *dws = param; if (dws->dma_dev != chan->device->dev) return false; chan->private = dws; return true; } static struct pxa_spi_info spi_info_configs[] = { [PORT_CE4100] = { .type = PXA25x_SSP, .port_id = -1, .num_chipselect = -1, .max_clk_rate = 3686400, }, [PORT_BYT] = { .type = LPSS_SSP, .port_id = 0, .num_chipselect = 1, .max_clk_rate = 50000000, .tx_param = &byt_tx_param, .rx_param = &byt_rx_param, }, [PORT_BSW0] = { .type = LPSS_SSP, .port_id = 0, .num_chipselect = 1, .max_clk_rate = 50000000, .tx_param = &bsw0_tx_param, .rx_param = &bsw0_rx_param, }, [PORT_BSW1] = { .type = LPSS_SSP, .port_id = 1, .num_chipselect = 1, .max_clk_rate = 50000000, .tx_param = &bsw1_tx_param, .rx_param = &bsw1_rx_param, }, [PORT_BSW2] = { .type = LPSS_SSP, .port_id = 2, .num_chipselect = 1, .max_clk_rate = 50000000, .tx_param = &bsw2_tx_param, .rx_param = &bsw2_rx_param, }, [PORT_QUARK_X1000] = { .type = QUARK_X1000_SSP, .port_id = -1, .num_chipselect = 1, .max_clk_rate = 50000000, }, }; static int pxa2xx_spi_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { struct platform_device_info pi; int ret; struct platform_device *pdev; struct pxa2xx_spi_master spi_pdata; struct ssp_device *ssp; struct pxa_spi_info *c; char buf[40]; struct pci_dev *dma_dev; ret = pcim_enable_device(dev); if (ret) return ret; ret = pcim_iomap_regions(dev, 1 << 0, "PXA2xx SPI"); if (ret) return ret; c = &spi_info_configs[ent->driver_data]; memset(&spi_pdata, 0, sizeof(spi_pdata)); spi_pdata.num_chipselect = (c->num_chipselect > 0) ? c->num_chipselect : dev->devfn; dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); if (c->tx_param) { struct dw_dma_slave *slave = c->tx_param; slave->dma_dev = &dma_dev->dev; slave->src_master = 1; slave->dst_master = 0; } if (c->rx_param) { struct dw_dma_slave *slave = c->rx_param; slave->dma_dev = &dma_dev->dev; slave->src_master = 1; slave->dst_master = 0; } spi_pdata.dma_filter = lpss_dma_filter; spi_pdata.tx_param = c->tx_param; spi_pdata.rx_param = c->rx_param; spi_pdata.enable_dma = c->rx_param && c->tx_param; ssp = &spi_pdata.ssp; ssp->phys_base = pci_resource_start(dev, 0); ssp->mmio_base = pcim_iomap_table(dev)[0]; if (!ssp->mmio_base) { dev_err(&dev->dev, "failed to ioremap() registers\n"); return -EIO; } ssp->irq = dev->irq; ssp->port_id = (c->port_id >= 0) ? c->port_id : dev->devfn; ssp->type = c->type; snprintf(buf, sizeof(buf), "pxa2xx-spi.%d", ssp->port_id); ssp->clk = clk_register_fixed_rate(&dev->dev, buf , NULL, CLK_IS_ROOT, c->max_clk_rate); if (IS_ERR(ssp->clk)) return PTR_ERR(ssp->clk); memset(&pi, 0, sizeof(pi)); pi.parent = &dev->dev; pi.name = "pxa2xx-spi"; pi.id = ssp->port_id; pi.data = &spi_pdata; pi.size_data = sizeof(spi_pdata); pdev = platform_device_register_full(&pi); if (IS_ERR(pdev)) { clk_unregister(ssp->clk); return PTR_ERR(pdev); } pci_set_drvdata(dev, pdev); return 0; } static void pxa2xx_spi_pci_remove(struct pci_dev *dev) { struct platform_device *pdev = pci_get_drvdata(dev); struct pxa2xx_spi_master *spi_pdata; spi_pdata = dev_get_platdata(&pdev->dev); platform_device_unregister(pdev); clk_unregister(spi_pdata->ssp.clk); } static const struct pci_device_id pxa2xx_spi_pci_devices[] = { { PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 }, { PCI_VDEVICE(INTEL, 0x0935), PORT_QUARK_X1000 }, { PCI_VDEVICE(INTEL, 0x0f0e), PORT_BYT }, { PCI_VDEVICE(INTEL, 0x228e), PORT_BSW0 }, { PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 }, { PCI_VDEVICE(INTEL, 0x22ac), PORT_BSW2 }, { }, }; MODULE_DEVICE_TABLE(pci, pxa2xx_spi_pci_devices); static struct pci_driver pxa2xx_spi_pci_driver = { .name = "pxa2xx_spi_pci", .id_table = pxa2xx_spi_pci_devices, .probe = pxa2xx_spi_pci_probe, .remove = pxa2xx_spi_pci_remove, }; module_pci_driver(pxa2xx_spi_pci_driver); MODULE_DESCRIPTION("CE4100/LPSS PCI-SPI glue code for PXA's driver"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>"); |