Commit | Line | Data |
---|---|---|
09c434b8 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
d6ea3df0 | 2 | /* |
8083d6b8 AS |
3 | * PCI glue driver for SPI PXA2xx compatible controllers. |
4 | * CE4100's SPI device is more or less the same one as found on PXA. | |
d6ea3df0 | 5 | * |
8083d6b8 | 6 | * Copyright (C) 2016, 2021 Intel Corporation |
d6ea3df0 | 7 | */ |
e379d2cd AS |
8 | #include <linux/clk-provider.h> |
9 | #include <linux/module.h> | |
d6ea3df0 SAS |
10 | #include <linux/pci.h> |
11 | #include <linux/platform_device.h> | |
0e476871 | 12 | |
d6ea3df0 SAS |
13 | #include <linux/spi/pxa2xx_spi.h> |
14 | ||
b729bf34 MW |
15 | #include <linux/dmaengine.h> |
16 | #include <linux/platform_data/dma-dw.h> | |
17 | ||
7e425c3c AS |
18 | #define PCI_DEVICE_ID_INTEL_QUARK_X1000 0x0935 |
19 | #define PCI_DEVICE_ID_INTEL_BYT 0x0f0e | |
20 | #define PCI_DEVICE_ID_INTEL_MRFLD 0x1194 | |
21 | #define PCI_DEVICE_ID_INTEL_BSW0 0x228e | |
22 | #define PCI_DEVICE_ID_INTEL_BSW1 0x2290 | |
23 | #define PCI_DEVICE_ID_INTEL_BSW2 0x22ac | |
24 | #define PCI_DEVICE_ID_INTEL_CE4100 0x2e6a | |
25 | #define PCI_DEVICE_ID_INTEL_LPT0_0 0x9c65 | |
26 | #define PCI_DEVICE_ID_INTEL_LPT0_1 0x9c66 | |
27 | #define PCI_DEVICE_ID_INTEL_LPT1_0 0x9ce5 | |
28 | #define PCI_DEVICE_ID_INTEL_LPT1_1 0x9ce6 | |
d6ba32d5 CCE |
29 | |
30 | struct pxa_spi_info { | |
ba8d1353 | 31 | int (*setup)(struct pci_dev *pdev, struct pxa2xx_spi_controller *c); |
d6ba32d5 CCE |
32 | }; |
33 | ||
b729bf34 MW |
34 | static struct dw_dma_slave byt_tx_param = { .dst_id = 0 }; |
35 | static struct dw_dma_slave byt_rx_param = { .src_id = 1 }; | |
36 | ||
25014521 AS |
37 | static struct dw_dma_slave mrfld3_tx_param = { .dst_id = 15 }; |
38 | static struct dw_dma_slave mrfld3_rx_param = { .src_id = 14 }; | |
39 | static struct dw_dma_slave mrfld5_tx_param = { .dst_id = 13 }; | |
40 | static struct dw_dma_slave mrfld5_rx_param = { .src_id = 12 }; | |
41 | static struct dw_dma_slave mrfld6_tx_param = { .dst_id = 11 }; | |
42 | static struct dw_dma_slave mrfld6_rx_param = { .src_id = 10 }; | |
43 | ||
39d36536 MW |
44 | static struct dw_dma_slave bsw0_tx_param = { .dst_id = 0 }; |
45 | static struct dw_dma_slave bsw0_rx_param = { .src_id = 1 }; | |
46 | static struct dw_dma_slave bsw1_tx_param = { .dst_id = 6 }; | |
47 | static struct dw_dma_slave bsw1_rx_param = { .src_id = 7 }; | |
48 | static struct dw_dma_slave bsw2_tx_param = { .dst_id = 8 }; | |
49 | static struct dw_dma_slave bsw2_rx_param = { .src_id = 9 }; | |
50 | ||
54c5d3bf AS |
51 | static struct dw_dma_slave lpt1_tx_param = { .dst_id = 0 }; |
52 | static struct dw_dma_slave lpt1_rx_param = { .src_id = 1 }; | |
53 | static struct dw_dma_slave lpt0_tx_param = { .dst_id = 2 }; | |
54 | static struct dw_dma_slave lpt0_rx_param = { .src_id = 3 }; | |
caba248d | 55 | |
c3f4fc09 AS |
56 | static void pxa2xx_spi_pci_clk_unregister(void *clk) |
57 | { | |
58 | clk_unregister(clk); | |
59 | } | |
60 | ||
61 | static int pxa2xx_spi_pci_clk_register(struct pci_dev *dev, struct ssp_device *ssp, | |
62 | unsigned long rate) | |
63 | { | |
64 | char buf[40]; | |
65 | ||
66 | snprintf(buf, sizeof(buf), "pxa2xx-spi.%d", ssp->port_id); | |
67 | ssp->clk = clk_register_fixed_rate(&dev->dev, buf, NULL, 0, rate); | |
68 | if (IS_ERR(ssp->clk)) | |
69 | return PTR_ERR(ssp->clk); | |
70 | ||
71 | return devm_add_action_or_reset(&dev->dev, pxa2xx_spi_pci_clk_unregister, ssp->clk); | |
72 | } | |
73 | ||
b729bf34 MW |
74 | static bool lpss_dma_filter(struct dma_chan *chan, void *param) |
75 | { | |
76 | struct dw_dma_slave *dws = param; | |
77 | ||
78 | if (dws->dma_dev != chan->device->dev) | |
79 | return false; | |
80 | ||
81 | chan->private = dws; | |
82 | return true; | |
83 | } | |
84 | ||
609d7ffd AS |
85 | static void lpss_dma_put_device(void *dma_dev) |
86 | { | |
87 | pci_dev_put(dma_dev); | |
88 | } | |
89 | ||
ba8d1353 | 90 | static int lpss_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c) |
743485ea | 91 | { |
ba8d1353 | 92 | struct ssp_device *ssp = &c->ssp; |
cb50f3f3 | 93 | struct dw_dma_slave *tx, *rx; |
743485ea | 94 | struct pci_dev *dma_dev; |
609d7ffd | 95 | int ret; |
743485ea | 96 | |
7e425c3c AS |
97 | switch (dev->device) { |
98 | case PCI_DEVICE_ID_INTEL_BYT: | |
ba8d1353 AS |
99 | ssp->type = LPSS_BYT_SSP; |
100 | ssp->port_id = 0; | |
7e425c3c AS |
101 | c->tx_param = &byt_tx_param; |
102 | c->rx_param = &byt_rx_param; | |
103 | break; | |
104 | case PCI_DEVICE_ID_INTEL_BSW0: | |
ba8d1353 AS |
105 | ssp->type = LPSS_BSW_SSP; |
106 | ssp->port_id = 0; | |
7e425c3c AS |
107 | c->tx_param = &bsw0_tx_param; |
108 | c->rx_param = &bsw0_rx_param; | |
109 | break; | |
110 | case PCI_DEVICE_ID_INTEL_BSW1: | |
ba8d1353 AS |
111 | ssp->type = LPSS_BSW_SSP; |
112 | ssp->port_id = 1; | |
7e425c3c AS |
113 | c->tx_param = &bsw1_tx_param; |
114 | c->rx_param = &bsw1_rx_param; | |
115 | break; | |
116 | case PCI_DEVICE_ID_INTEL_BSW2: | |
ba8d1353 AS |
117 | ssp->type = LPSS_BSW_SSP; |
118 | ssp->port_id = 2; | |
7e425c3c AS |
119 | c->tx_param = &bsw2_tx_param; |
120 | c->rx_param = &bsw2_rx_param; | |
121 | break; | |
122 | case PCI_DEVICE_ID_INTEL_LPT0_0: | |
123 | case PCI_DEVICE_ID_INTEL_LPT1_0: | |
ba8d1353 AS |
124 | ssp->type = LPSS_LPT_SSP; |
125 | ssp->port_id = 0; | |
7e425c3c AS |
126 | c->tx_param = &lpt0_tx_param; |
127 | c->rx_param = &lpt0_rx_param; | |
128 | break; | |
129 | case PCI_DEVICE_ID_INTEL_LPT0_1: | |
130 | case PCI_DEVICE_ID_INTEL_LPT1_1: | |
ba8d1353 AS |
131 | ssp->type = LPSS_LPT_SSP; |
132 | ssp->port_id = 1; | |
7e425c3c AS |
133 | c->tx_param = &lpt1_tx_param; |
134 | c->rx_param = &lpt1_rx_param; | |
135 | break; | |
136 | default: | |
137 | return -ENODEV; | |
138 | } | |
139 | ||
743485ea | 140 | c->num_chipselect = 1; |
ba8d1353 AS |
141 | |
142 | ret = pxa2xx_spi_pci_clk_register(dev, ssp, 50000000); | |
143 | if (ret) | |
144 | return ret; | |
743485ea AS |
145 | |
146 | dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); | |
609d7ffd AS |
147 | ret = devm_add_action_or_reset(&dev->dev, lpss_dma_put_device, dma_dev); |
148 | if (ret) | |
149 | return ret; | |
743485ea | 150 | |
cb50f3f3 AS |
151 | tx = c->tx_param; |
152 | tx->dma_dev = &dma_dev->dev; | |
153 | tx->m_master = 0; | |
154 | tx->p_master = 1; | |
743485ea | 155 | |
cb50f3f3 AS |
156 | rx = c->rx_param; |
157 | rx->dma_dev = &dma_dev->dev; | |
158 | rx->m_master = 0; | |
159 | rx->p_master = 1; | |
743485ea AS |
160 | |
161 | c->dma_filter = lpss_dma_filter; | |
bd2e24de | 162 | c->dma_burst_size = 1; |
ba8d1353 | 163 | c->enable_dma = 1; |
743485ea AS |
164 | return 0; |
165 | } | |
166 | ||
fcaaf76e | 167 | static const struct pxa_spi_info lpss_info_config = { |
7e425c3c AS |
168 | .setup = lpss_spi_setup, |
169 | }; | |
170 | ||
ba8d1353 | 171 | static int ce4100_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c) |
78e27f97 | 172 | { |
ba8d1353 AS |
173 | struct ssp_device *ssp = &c->ssp; |
174 | ||
175 | ssp->type = PXA25x_SSP; | |
176 | ssp->port_id = dev->devfn; | |
78e27f97 | 177 | c->num_chipselect = dev->devfn; |
78e27f97 | 178 | |
ba8d1353 | 179 | return pxa2xx_spi_pci_clk_register(dev, ssp, 3686400); |
78e27f97 AS |
180 | } |
181 | ||
fcaaf76e | 182 | static const struct pxa_spi_info ce4100_info_config = { |
7e425c3c AS |
183 | .setup = ce4100_spi_setup, |
184 | }; | |
185 | ||
ba8d1353 | 186 | static int mrfld_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c) |
4f470910 | 187 | { |
ba8d1353 | 188 | struct ssp_device *ssp = &c->ssp; |
25014521 | 189 | struct dw_dma_slave *tx, *rx; |
609d7ffd AS |
190 | struct pci_dev *dma_dev; |
191 | int ret; | |
25014521 | 192 | |
ba8d1353 AS |
193 | ssp->type = MRFLD_SSP; |
194 | ||
4f470910 AS |
195 | switch (PCI_FUNC(dev->devfn)) { |
196 | case 0: | |
ba8d1353 | 197 | ssp->port_id = 3; |
4f470910 | 198 | c->num_chipselect = 1; |
25014521 AS |
199 | c->tx_param = &mrfld3_tx_param; |
200 | c->rx_param = &mrfld3_rx_param; | |
4f470910 AS |
201 | break; |
202 | case 1: | |
ba8d1353 | 203 | ssp->port_id = 5; |
4f470910 | 204 | c->num_chipselect = 4; |
25014521 AS |
205 | c->tx_param = &mrfld5_tx_param; |
206 | c->rx_param = &mrfld5_rx_param; | |
4f470910 AS |
207 | break; |
208 | case 2: | |
ba8d1353 | 209 | ssp->port_id = 6; |
4f470910 | 210 | c->num_chipselect = 1; |
25014521 AS |
211 | c->tx_param = &mrfld6_tx_param; |
212 | c->rx_param = &mrfld6_rx_param; | |
4f470910 AS |
213 | break; |
214 | default: | |
215 | return -ENODEV; | |
216 | } | |
25014521 | 217 | |
ba8d1353 AS |
218 | ret = pxa2xx_spi_pci_clk_register(dev, ssp, 25000000); |
219 | if (ret) | |
220 | return ret; | |
03f8e04e | 221 | |
609d7ffd AS |
222 | dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(21, 0)); |
223 | ret = devm_add_action_or_reset(&dev->dev, lpss_dma_put_device, dma_dev); | |
224 | if (ret) | |
225 | return ret; | |
226 | ||
25014521 AS |
227 | tx = c->tx_param; |
228 | tx->dma_dev = &dma_dev->dev; | |
229 | ||
230 | rx = c->rx_param; | |
231 | rx->dma_dev = &dma_dev->dev; | |
232 | ||
233 | c->dma_filter = lpss_dma_filter; | |
37821a82 | 234 | c->dma_burst_size = 8; |
ba8d1353 | 235 | c->enable_dma = 1; |
4f470910 AS |
236 | return 0; |
237 | } | |
238 | ||
fcaaf76e | 239 | static const struct pxa_spi_info mrfld_info_config = { |
7e425c3c AS |
240 | .setup = mrfld_spi_setup, |
241 | }; | |
242 | ||
ba8d1353 | 243 | static int qrk_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c) |
71ea0e3a | 244 | { |
ba8d1353 AS |
245 | struct ssp_device *ssp = &c->ssp; |
246 | ||
247 | ssp->type = QUARK_X1000_SSP; | |
248 | ssp->port_id = dev->devfn; | |
71ea0e3a | 249 | c->num_chipselect = 1; |
71ea0e3a | 250 | |
ba8d1353 | 251 | return pxa2xx_spi_pci_clk_register(dev, ssp, 50000000); |
71ea0e3a AS |
252 | } |
253 | ||
fcaaf76e | 254 | static const struct pxa_spi_info qrk_info_config = { |
7e425c3c | 255 | .setup = qrk_spi_setup, |
d6ba32d5 CCE |
256 | }; |
257 | ||
258 | static int pxa2xx_spi_pci_probe(struct pci_dev *dev, | |
d6ea3df0 SAS |
259 | const struct pci_device_id *ent) |
260 | { | |
fcaaf76e | 261 | const struct pxa_spi_info *info; |
0202775b | 262 | struct platform_device_info pi; |
d6ea3df0 | 263 | int ret; |
d6ea3df0 | 264 | struct platform_device *pdev; |
51eea52d | 265 | struct pxa2xx_spi_controller spi_pdata; |
d6ea3df0 SAS |
266 | struct ssp_device *ssp; |
267 | ||
0202775b | 268 | ret = pcim_enable_device(dev); |
d6ea3df0 SAS |
269 | if (ret) |
270 | return ret; | |
271 | ||
0202775b | 272 | ret = pcim_iomap_regions(dev, 1 << 0, "PXA2xx SPI"); |
c1346340 | 273 | if (ret) |
d6ea3df0 | 274 | return ret; |
d6ea3df0 | 275 | |
743485ea | 276 | memset(&spi_pdata, 0, sizeof(spi_pdata)); |
d6ea3df0 | 277 | |
851bacf5 | 278 | ssp = &spi_pdata.ssp; |
c3dce24c | 279 | ssp->dev = &dev->dev; |
d6ea3df0 | 280 | ssp->phys_base = pci_resource_start(dev, 0); |
0202775b | 281 | ssp->mmio_base = pcim_iomap_table(dev)[0]; |
ba8d1353 AS |
282 | |
283 | info = (struct pxa_spi_info *)ent->driver_data; | |
284 | ret = info->setup(dev, &spi_pdata); | |
285 | if (ret) | |
286 | return ret; | |
d6ea3df0 | 287 | |
64e02cb0 JK |
288 | pci_set_master(dev); |
289 | ||
290 | ret = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_ALL_TYPES); | |
291 | if (ret < 0) | |
292 | return ret; | |
293 | ssp->irq = pci_irq_vector(dev, 0); | |
294 | ||
0202775b | 295 | memset(&pi, 0, sizeof(pi)); |
a586f944 | 296 | pi.fwnode = dev_fwnode(&dev->dev); |
0202775b MW |
297 | pi.parent = &dev->dev; |
298 | pi.name = "pxa2xx-spi"; | |
299 | pi.id = ssp->port_id; | |
300 | pi.data = &spi_pdata; | |
301 | pi.size_data = sizeof(spi_pdata); | |
d6ea3df0 | 302 | |
0202775b | 303 | pdev = platform_device_register_full(&pi); |
c3f4fc09 | 304 | if (IS_ERR(pdev)) |
d77b5382 | 305 | return PTR_ERR(pdev); |
d6ea3df0 | 306 | |
851bacf5 | 307 | pci_set_drvdata(dev, pdev); |
d6ea3df0 | 308 | |
0202775b | 309 | return 0; |
d6ea3df0 SAS |
310 | } |
311 | ||
d6ba32d5 | 312 | static void pxa2xx_spi_pci_remove(struct pci_dev *dev) |
d6ea3df0 | 313 | { |
851bacf5 | 314 | struct platform_device *pdev = pci_get_drvdata(dev); |
d6ea3df0 | 315 | |
851bacf5 | 316 | platform_device_unregister(pdev); |
d6ea3df0 SAS |
317 | } |
318 | ||
d6ba32d5 | 319 | static const struct pci_device_id pxa2xx_spi_pci_devices[] = { |
7e425c3c AS |
320 | { PCI_DEVICE_DATA(INTEL, QUARK_X1000, &qrk_info_config) }, |
321 | { PCI_DEVICE_DATA(INTEL, BYT, &lpss_info_config) }, | |
322 | { PCI_DEVICE_DATA(INTEL, MRFLD, &mrfld_info_config) }, | |
323 | { PCI_DEVICE_DATA(INTEL, BSW0, &lpss_info_config) }, | |
324 | { PCI_DEVICE_DATA(INTEL, BSW1, &lpss_info_config) }, | |
325 | { PCI_DEVICE_DATA(INTEL, BSW2, &lpss_info_config) }, | |
326 | { PCI_DEVICE_DATA(INTEL, CE4100, &ce4100_info_config) }, | |
327 | { PCI_DEVICE_DATA(INTEL, LPT0_0, &lpss_info_config) }, | |
328 | { PCI_DEVICE_DATA(INTEL, LPT0_1, &lpss_info_config) }, | |
329 | { PCI_DEVICE_DATA(INTEL, LPT1_0, &lpss_info_config) }, | |
330 | { PCI_DEVICE_DATA(INTEL, LPT1_1, &lpss_info_config) }, | |
54c5d3bf | 331 | { } |
d6ea3df0 | 332 | }; |
d6ba32d5 | 333 | MODULE_DEVICE_TABLE(pci, pxa2xx_spi_pci_devices); |
d6ea3df0 | 334 | |
d6ba32d5 CCE |
335 | static struct pci_driver pxa2xx_spi_pci_driver = { |
336 | .name = "pxa2xx_spi_pci", | |
337 | .id_table = pxa2xx_spi_pci_devices, | |
338 | .probe = pxa2xx_spi_pci_probe, | |
339 | .remove = pxa2xx_spi_pci_remove, | |
d6ea3df0 SAS |
340 | }; |
341 | ||
d6ba32d5 | 342 | module_pci_driver(pxa2xx_spi_pci_driver); |
d6ea3df0 | 343 | |
d6ba32d5 | 344 | MODULE_DESCRIPTION("CE4100/LPSS PCI-SPI glue code for PXA's driver"); |
d6ea3df0 SAS |
345 | MODULE_LICENSE("GPL v2"); |
346 | MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>"); |