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