hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/spi/spi-altera.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Altera SPI driver
34 *
....@@ -7,16 +8,13 @@
78 * Copyright (c) 2006 Ben Dooks
89 * Copyright (c) 2006 Simtec Electronics
910 * Ben Dooks <ben@simtec.co.uk>
10
- *
11
- * This program is free software; you can redistribute it and/or modify
12
- * it under the terms of the GNU General Public License version 2 as
13
- * published by the Free Software Foundation.
1411 */
1512
1613 #include <linux/interrupt.h>
1714 #include <linux/errno.h>
1815 #include <linux/module.h>
1916 #include <linux/platform_device.h>
17
+#include <linux/spi/altera.h>
2018 #include <linux/spi/spi.h>
2119 #include <linux/io.h>
2220 #include <linux/of.h>
....@@ -43,18 +41,60 @@
4341 #define ALTERA_SPI_CONTROL_IE_MSK 0x100
4442 #define ALTERA_SPI_CONTROL_SSO_MSK 0x400
4543
44
+#define ALTERA_SPI_MAX_CS 32
45
+
46
+enum altera_spi_type {
47
+ ALTERA_SPI_TYPE_UNKNOWN,
48
+ ALTERA_SPI_TYPE_SUBDEV,
49
+};
50
+
4651 struct altera_spi {
47
- void __iomem *base;
4852 int irq;
4953 int len;
5054 int count;
5155 int bytes_per_word;
52
- unsigned long imr;
56
+ u32 imr;
5357
5458 /* data buffers */
5559 const unsigned char *tx;
5660 unsigned char *rx;
61
+
62
+ struct regmap *regmap;
63
+ u32 regoff;
64
+ struct device *dev;
5765 };
66
+
67
+static const struct regmap_config spi_altera_config = {
68
+ .reg_bits = 32,
69
+ .reg_stride = 4,
70
+ .val_bits = 32,
71
+ .fast_io = true,
72
+};
73
+
74
+static int altr_spi_writel(struct altera_spi *hw, unsigned int reg,
75
+ unsigned int val)
76
+{
77
+ int ret;
78
+
79
+ ret = regmap_write(hw->regmap, hw->regoff + reg, val);
80
+ if (ret)
81
+ dev_err(hw->dev, "fail to write reg 0x%x val 0x%x: %d\n",
82
+ reg, val, ret);
83
+
84
+ return ret;
85
+}
86
+
87
+static int altr_spi_readl(struct altera_spi *hw, unsigned int reg,
88
+ unsigned int *val)
89
+{
90
+ int ret;
91
+
92
+ ret = regmap_read(hw->regmap, hw->regoff + reg, val);
93
+ if (ret)
94
+ dev_err(hw->dev, "fail to read reg 0x%x: %d\n", reg, ret);
95
+
96
+ return ret;
97
+}
5898
5999 static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev)
60100 {
....@@ -67,12 +107,13 @@
67107
68108 if (is_high) {
69109 hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
70
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
71
- writel(0, hw->base + ALTERA_SPI_SLAVE_SEL);
110
+ altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
111
+ altr_spi_writel(hw, ALTERA_SPI_SLAVE_SEL, 0);
72112 } else {
73
- writel(BIT(spi->chip_select), hw->base + ALTERA_SPI_SLAVE_SEL);
113
+ altr_spi_writel(hw, ALTERA_SPI_SLAVE_SEL,
114
+ BIT(spi->chip_select));
74115 hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
75
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
116
+ altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
76117 }
77118 }
78119
....@@ -89,17 +130,24 @@
89130 txd = (hw->tx[hw->count * 2]
90131 | (hw->tx[hw->count * 2 + 1] << 8));
91132 break;
133
+ case 4:
134
+ txd = (hw->tx[hw->count * 4]
135
+ | (hw->tx[hw->count * 4 + 1] << 8)
136
+ | (hw->tx[hw->count * 4 + 2] << 16)
137
+ | (hw->tx[hw->count * 4 + 3] << 24));
138
+ break;
139
+
92140 }
93141 }
94142
95
- writel(txd, hw->base + ALTERA_SPI_TXDATA);
143
+ altr_spi_writel(hw, ALTERA_SPI_TXDATA, txd);
96144 }
97145
98146 static void altera_spi_rx_word(struct altera_spi *hw)
99147 {
100148 unsigned int rxd;
101149
102
- rxd = readl(hw->base + ALTERA_SPI_RXDATA);
150
+ altr_spi_readl(hw, ALTERA_SPI_RXDATA, &rxd);
103151 if (hw->rx) {
104152 switch (hw->bytes_per_word) {
105153 case 1:
....@@ -109,6 +157,13 @@
109157 hw->rx[hw->count * 2] = rxd;
110158 hw->rx[hw->count * 2 + 1] = rxd >> 8;
111159 break;
160
+ case 4:
161
+ hw->rx[hw->count * 4] = rxd;
162
+ hw->rx[hw->count * 4 + 1] = rxd >> 8;
163
+ hw->rx[hw->count * 4 + 2] = rxd >> 16;
164
+ hw->rx[hw->count * 4 + 3] = rxd >> 24;
165
+ break;
166
+
112167 }
113168 }
114169
....@@ -119,6 +174,7 @@
119174 struct spi_device *spi, struct spi_transfer *t)
120175 {
121176 struct altera_spi *hw = spi_master_get_devdata(master);
177
+ u32 val;
122178
123179 hw->tx = t->tx_buf;
124180 hw->rx = t->rx_buf;
....@@ -129,24 +185,30 @@
129185 if (hw->irq >= 0) {
130186 /* enable receive interrupt */
131187 hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK;
132
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
188
+ altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
133189
134190 /* send the first byte */
135191 altera_spi_tx_word(hw);
136
- } else {
137
- while (hw->count < hw->len) {
138
- altera_spi_tx_word(hw);
139192
140
- while (!(readl(hw->base + ALTERA_SPI_STATUS) &
141
- ALTERA_SPI_STATUS_RRDY_MSK))
142
- cpu_relax();
143
-
144
- altera_spi_rx_word(hw);
145
- }
146
- spi_finalize_current_transfer(master);
193
+ return 1;
147194 }
148195
149
- return t->len;
196
+ while (hw->count < hw->len) {
197
+ altera_spi_tx_word(hw);
198
+
199
+ for (;;) {
200
+ altr_spi_readl(hw, ALTERA_SPI_STATUS, &val);
201
+ if (val & ALTERA_SPI_STATUS_RRDY_MSK)
202
+ break;
203
+
204
+ cpu_relax();
205
+ }
206
+
207
+ altera_spi_rx_word(hw);
208
+ }
209
+ spi_finalize_current_transfer(master);
210
+
211
+ return 0;
150212 }
151213
152214 static irqreturn_t altera_spi_irq(int irq, void *dev)
....@@ -161,7 +223,7 @@
161223 } else {
162224 /* disable receive interrupt */
163225 hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
164
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
226
+ altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
165227
166228 spi_finalize_current_transfer(master);
167229 }
....@@ -171,10 +233,14 @@
171233
172234 static int altera_spi_probe(struct platform_device *pdev)
173235 {
236
+ const struct platform_device_id *platid = platform_get_device_id(pdev);
237
+ struct altera_spi_platform_data *pdata = dev_get_platdata(&pdev->dev);
238
+ enum altera_spi_type type = ALTERA_SPI_TYPE_UNKNOWN;
174239 struct altera_spi *hw;
175240 struct spi_master *master;
176
- struct resource *res;
177241 int err = -ENODEV;
242
+ u32 val;
243
+ u16 i;
178244
179245 master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi));
180246 if (!master)
....@@ -182,28 +248,73 @@
182248
183249 /* setup the master state. */
184250 master->bus_num = pdev->id;
185
- master->num_chipselect = 16;
186
- master->mode_bits = SPI_CS_HIGH;
187
- master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
251
+
252
+ if (pdata) {
253
+ if (pdata->num_chipselect > ALTERA_SPI_MAX_CS) {
254
+ dev_err(&pdev->dev,
255
+ "Invalid number of chipselect: %hu\n",
256
+ pdata->num_chipselect);
257
+ err = -EINVAL;
258
+ goto exit;
259
+ }
260
+
261
+ master->num_chipselect = pdata->num_chipselect;
262
+ master->mode_bits = pdata->mode_bits;
263
+ master->bits_per_word_mask = pdata->bits_per_word_mask;
264
+ } else {
265
+ master->num_chipselect = 16;
266
+ master->mode_bits = SPI_CS_HIGH;
267
+ master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
268
+ }
269
+
188270 master->dev.of_node = pdev->dev.of_node;
189271 master->transfer_one = altera_spi_txrx;
190272 master->set_cs = altera_spi_set_cs;
191273
192274 hw = spi_master_get_devdata(master);
275
+ hw->dev = &pdev->dev;
276
+
277
+ if (platid)
278
+ type = platid->driver_data;
193279
194280 /* find and map our resources */
195
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
196
- hw->base = devm_ioremap_resource(&pdev->dev, res);
197
- if (IS_ERR(hw->base)) {
198
- err = PTR_ERR(hw->base);
199
- goto exit;
281
+ if (type == ALTERA_SPI_TYPE_SUBDEV) {
282
+ struct resource *regoff;
283
+
284
+ hw->regmap = dev_get_regmap(pdev->dev.parent, NULL);
285
+ if (!hw->regmap) {
286
+ dev_err(&pdev->dev, "get regmap failed\n");
287
+ goto exit;
288
+ }
289
+
290
+ regoff = platform_get_resource(pdev, IORESOURCE_REG, 0);
291
+ if (regoff)
292
+ hw->regoff = regoff->start;
293
+ } else {
294
+ void __iomem *res;
295
+
296
+ res = devm_platform_ioremap_resource(pdev, 0);
297
+ if (IS_ERR(res)) {
298
+ err = PTR_ERR(res);
299
+ goto exit;
300
+ }
301
+
302
+ hw->regmap = devm_regmap_init_mmio(&pdev->dev, res,
303
+ &spi_altera_config);
304
+ if (IS_ERR(hw->regmap)) {
305
+ dev_err(&pdev->dev, "regmap mmio init failed\n");
306
+ err = PTR_ERR(hw->regmap);
307
+ goto exit;
308
+ }
200309 }
310
+
201311 /* program defaults into the registers */
202312 hw->imr = 0; /* disable spi interrupts */
203
- writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
204
- writel(0, hw->base + ALTERA_SPI_STATUS); /* clear status reg */
205
- if (readl(hw->base + ALTERA_SPI_STATUS) & ALTERA_SPI_STATUS_RRDY_MSK)
206
- readl(hw->base + ALTERA_SPI_RXDATA); /* flush rxdata */
313
+ altr_spi_writel(hw, ALTERA_SPI_CONTROL, hw->imr);
314
+ altr_spi_writel(hw, ALTERA_SPI_STATUS, 0); /* clear status reg */
315
+ altr_spi_readl(hw, ALTERA_SPI_STATUS, &val);
316
+ if (val & ALTERA_SPI_STATUS_RRDY_MSK)
317
+ altr_spi_readl(hw, ALTERA_SPI_RXDATA, &val); /* flush rxdata */
207318 /* irq is optional */
208319 hw->irq = platform_get_irq(pdev, 0);
209320 if (hw->irq >= 0) {
....@@ -216,7 +327,17 @@
216327 err = devm_spi_register_master(&pdev->dev, master);
217328 if (err)
218329 goto exit;
219
- dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
330
+
331
+ if (pdata) {
332
+ for (i = 0; i < pdata->num_devices; i++) {
333
+ if (!spi_new_device(master, pdata->devices + i))
334
+ dev_warn(&pdev->dev,
335
+ "unable to create SPI device: %s\n",
336
+ pdata->devices[i].modalias);
337
+ }
338
+ }
339
+
340
+ dev_info(&pdev->dev, "regoff %u, irq %d\n", hw->regoff, hw->irq);
220341
221342 return 0;
222343 exit:
....@@ -233,6 +354,13 @@
233354 MODULE_DEVICE_TABLE(of, altera_spi_match);
234355 #endif /* CONFIG_OF */
235356
357
+static const struct platform_device_id altera_spi_ids[] = {
358
+ { DRV_NAME, ALTERA_SPI_TYPE_UNKNOWN },
359
+ { "subdev_spi_altera", ALTERA_SPI_TYPE_SUBDEV },
360
+ { }
361
+};
362
+MODULE_DEVICE_TABLE(platform, altera_spi_ids);
363
+
236364 static struct platform_driver altera_spi_driver = {
237365 .probe = altera_spi_probe,
238366 .driver = {
....@@ -240,6 +368,7 @@
240368 .pm = NULL,
241369 .of_match_table = of_match_ptr(altera_spi_match),
242370 },
371
+ .id_table = altera_spi_ids,
243372 };
244373 module_platform_driver(altera_spi_driver);
245374