Loading...
Note: File does not exist in v3.1.
1// SPDX-License-Identifier: GPL-2.0-or-later
2
3#include <linux/acpi.h>
4#include <linux/clk.h>
5#include <linux/device.h>
6#include <linux/err.h>
7#include <linux/init.h>
8#include <linux/mod_devicetable.h>
9#include <linux/platform_device.h>
10#include <linux/pm_runtime.h>
11#include <linux/property.h>
12#include <linux/types.h>
13
14#include "spi-pxa2xx.h"
15
16static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
17{
18 return param == chan->device->dev;
19}
20
21static int
22pxa2xx_spi_init_ssp(struct platform_device *pdev, struct ssp_device *ssp, enum pxa_ssp_type type)
23{
24 struct device *dev = &pdev->dev;
25 struct resource *res;
26 int status;
27 u64 uid;
28
29 ssp->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
30 if (IS_ERR(ssp->mmio_base))
31 return PTR_ERR(ssp->mmio_base);
32
33 ssp->phys_base = res->start;
34
35 ssp->clk = devm_clk_get(dev, NULL);
36 if (IS_ERR(ssp->clk))
37 return PTR_ERR(ssp->clk);
38
39 ssp->irq = platform_get_irq(pdev, 0);
40 if (ssp->irq < 0)
41 return ssp->irq;
42
43 ssp->type = type;
44 ssp->dev = dev;
45
46 status = acpi_dev_uid_to_integer(ACPI_COMPANION(dev), &uid);
47 if (status)
48 ssp->port_id = -1;
49 else
50 ssp->port_id = uid;
51
52 return 0;
53}
54
55static void pxa2xx_spi_ssp_release(void *ssp)
56{
57 pxa_ssp_free(ssp);
58}
59
60static struct ssp_device *pxa2xx_spi_ssp_request(struct platform_device *pdev)
61{
62 struct ssp_device *ssp;
63 int status;
64
65 ssp = pxa_ssp_request(pdev->id, pdev->name);
66 if (!ssp)
67 return NULL;
68
69 status = devm_add_action_or_reset(&pdev->dev, pxa2xx_spi_ssp_release, ssp);
70 if (status)
71 return ERR_PTR(status);
72
73 return ssp;
74}
75
76static struct pxa2xx_spi_controller *
77pxa2xx_spi_init_pdata(struct platform_device *pdev)
78{
79 struct pxa2xx_spi_controller *pdata;
80 struct device *dev = &pdev->dev;
81 struct device *parent = dev->parent;
82 const void *match = device_get_match_data(dev);
83 enum pxa_ssp_type type = SSP_UNDEFINED;
84 struct ssp_device *ssp;
85 bool is_lpss_priv;
86 u32 num_cs = 1;
87 int status;
88
89 ssp = pxa2xx_spi_ssp_request(pdev);
90 if (IS_ERR(ssp))
91 return ERR_CAST(ssp);
92 if (ssp) {
93 type = ssp->type;
94 } else if (match) {
95 type = (enum pxa_ssp_type)(uintptr_t)match;
96 } else {
97 u32 value;
98
99 status = device_property_read_u32(dev, "intel,spi-pxa2xx-type", &value);
100 if (status)
101 return ERR_PTR(status);
102
103 type = (enum pxa_ssp_type)value;
104 }
105
106 /* Validate the SSP type correctness */
107 if (!(type > SSP_UNDEFINED && type < SSP_MAX))
108 return ERR_PTR(-EINVAL);
109
110 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
111 if (!pdata)
112 return ERR_PTR(-ENOMEM);
113
114 /* Platforms with iDMA 64-bit */
115 is_lpss_priv = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpss_priv");
116 if (is_lpss_priv) {
117 pdata->tx_param = parent;
118 pdata->rx_param = parent;
119 pdata->dma_filter = pxa2xx_spi_idma_filter;
120 }
121
122 /* Read number of chip select pins, if provided */
123 device_property_read_u32(dev, "num-cs", &num_cs);
124
125 pdata->num_chipselect = num_cs;
126 pdata->is_target = device_property_read_bool(dev, "spi-slave");
127 pdata->enable_dma = true;
128 pdata->dma_burst_size = 1;
129
130 /* If SSP has been already enumerated, use it */
131 if (ssp)
132 return pdata;
133
134 status = pxa2xx_spi_init_ssp(pdev, &pdata->ssp, type);
135 if (status)
136 return ERR_PTR(status);
137
138 return pdata;
139}
140
141static int pxa2xx_spi_platform_probe(struct platform_device *pdev)
142{
143 struct pxa2xx_spi_controller *platform_info;
144 struct device *dev = &pdev->dev;
145 struct ssp_device *ssp;
146 int ret;
147
148 platform_info = dev_get_platdata(dev);
149 if (!platform_info) {
150 platform_info = pxa2xx_spi_init_pdata(pdev);
151 if (IS_ERR(platform_info))
152 return dev_err_probe(dev, PTR_ERR(platform_info), "missing platform data\n");
153 }
154
155 ssp = pxa2xx_spi_ssp_request(pdev);
156 if (IS_ERR(ssp))
157 return PTR_ERR(ssp);
158 if (!ssp)
159 ssp = &platform_info->ssp;
160
161 pm_runtime_set_autosuspend_delay(dev, 50);
162 pm_runtime_use_autosuspend(dev);
163 pm_runtime_set_active(dev);
164 pm_runtime_enable(dev);
165
166 ret = pxa2xx_spi_probe(dev, ssp, platform_info);
167 if (ret)
168 pm_runtime_disable(dev);
169
170 return ret;
171}
172
173static void pxa2xx_spi_platform_remove(struct platform_device *pdev)
174{
175 struct device *dev = &pdev->dev;
176
177 pm_runtime_get_sync(dev);
178
179 pxa2xx_spi_remove(dev);
180
181 pm_runtime_put_noidle(dev);
182 pm_runtime_disable(dev);
183}
184
185static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
186 { "80860F0E" },
187 { "8086228E" },
188 { "INT33C0" },
189 { "INT33C1" },
190 { "INT3430" },
191 { "INT3431" },
192 {}
193};
194MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
195
196static const struct of_device_id pxa2xx_spi_of_match[] = {
197 { .compatible = "marvell,mmp2-ssp", .data = (void *)MMP2_SSP },
198 {}
199};
200MODULE_DEVICE_TABLE(of, pxa2xx_spi_of_match);
201
202static struct platform_driver driver = {
203 .driver = {
204 .name = "pxa2xx-spi",
205 .pm = pm_ptr(&pxa2xx_spi_pm_ops),
206 .acpi_match_table = pxa2xx_spi_acpi_match,
207 .of_match_table = pxa2xx_spi_of_match,
208 },
209 .probe = pxa2xx_spi_platform_probe,
210 .remove = pxa2xx_spi_platform_remove,
211};
212
213static int __init pxa2xx_spi_init(void)
214{
215 return platform_driver_register(&driver);
216}
217subsys_initcall(pxa2xx_spi_init);
218
219static void __exit pxa2xx_spi_exit(void)
220{
221 platform_driver_unregister(&driver);
222}
223module_exit(pxa2xx_spi_exit);
224
225MODULE_AUTHOR("Stephen Street");
226MODULE_DESCRIPTION("PXA2xx SSP SPI Controller platform driver");
227MODULE_LICENSE("GPL");
228MODULE_IMPORT_NS("SPI_PXA2xx");
229MODULE_ALIAS("platform:pxa2xx-spi");
230MODULE_SOFTDEP("pre: dw_dmac");