hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/spi/spi-bcm2835aux.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Driver for Broadcom BCM2835 auxiliary SPI Controllers
34 *
....@@ -7,20 +8,11 @@
78 * Based on: spi-bcm2835.c
89 *
910 * Copyright (C) 2015 Martin Sperl
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 as published by
13
- * the Free Software Foundation; either version 2 of the License, or
14
- * (at your option) any later version.
15
- *
16
- * This program is distributed in the hope that it will be useful,
17
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
- * GNU General Public License for more details.
2011 */
2112
2213 #include <linux/clk.h>
2314 #include <linux/completion.h>
15
+#include <linux/debugfs.h>
2416 #include <linux/delay.h>
2517 #include <linux/err.h>
2618 #include <linux/interrupt.h>
....@@ -35,6 +27,12 @@
3527 #include <linux/regmap.h>
3628 #include <linux/spi/spi.h>
3729 #include <linux/spinlock.h>
30
+
31
+/* define polling limits */
32
+static unsigned int polling_limit_us = 30;
33
+module_param(polling_limit_us, uint, 0664);
34
+MODULE_PARM_DESC(polling_limit_us,
35
+ "time in us to run a transfer in polling mode - if zero no polling is used\n");
3836
3937 /*
4038 * spi register defines
....@@ -88,10 +86,6 @@
8886 #define BCM2835_AUX_SPI_STAT_BUSY 0x00000040
8987 #define BCM2835_AUX_SPI_STAT_BITCOUNT 0x0000003F
9088
91
-/* timeout values */
92
-#define BCM2835_AUX_SPI_POLLING_LIMIT_US 30
93
-#define BCM2835_AUX_SPI_POLLING_JIFFIES 2
94
-
9589 struct bcm2835aux_spi {
9690 void __iomem *regs;
9791 struct clk *clk;
....@@ -102,7 +96,52 @@
10296 int tx_len;
10397 int rx_len;
10498 int pending;
99
+
100
+ u64 count_transfer_polling;
101
+ u64 count_transfer_irq;
102
+ u64 count_transfer_irq_after_poll;
103
+
104
+ struct dentry *debugfs_dir;
105105 };
106
+
107
+#if defined(CONFIG_DEBUG_FS)
108
+static void bcm2835aux_debugfs_create(struct bcm2835aux_spi *bs,
109
+ const char *dname)
110
+{
111
+ char name[64];
112
+ struct dentry *dir;
113
+
114
+ /* get full name */
115
+ snprintf(name, sizeof(name), "spi-bcm2835aux-%s", dname);
116
+
117
+ /* the base directory */
118
+ dir = debugfs_create_dir(name, NULL);
119
+ bs->debugfs_dir = dir;
120
+
121
+ /* the counters */
122
+ debugfs_create_u64("count_transfer_polling", 0444, dir,
123
+ &bs->count_transfer_polling);
124
+ debugfs_create_u64("count_transfer_irq", 0444, dir,
125
+ &bs->count_transfer_irq);
126
+ debugfs_create_u64("count_transfer_irq_after_poll", 0444, dir,
127
+ &bs->count_transfer_irq_after_poll);
128
+}
129
+
130
+static void bcm2835aux_debugfs_remove(struct bcm2835aux_spi *bs)
131
+{
132
+ debugfs_remove_recursive(bs->debugfs_dir);
133
+ bs->debugfs_dir = NULL;
134
+}
135
+#else
136
+static void bcm2835aux_debugfs_create(struct bcm2835aux_spi *bs,
137
+ const char *dname)
138
+{
139
+}
140
+
141
+static void bcm2835aux_debugfs_remove(struct bcm2835aux_spi *bs)
142
+{
143
+}
144
+#endif /* CONFIG_DEBUG_FS */
106145
107146 static inline u32 bcm2835aux_rd(struct bcm2835aux_spi *bs, unsigned reg)
108147 {
....@@ -123,15 +162,12 @@
123162 data = bcm2835aux_rd(bs, BCM2835_AUX_SPI_IO);
124163 if (bs->rx_buf) {
125164 switch (count) {
126
- case 4:
127
- *bs->rx_buf++ = (data >> 24) & 0xff;
128
- /* fallthrough */
129165 case 3:
130166 *bs->rx_buf++ = (data >> 16) & 0xff;
131
- /* fallthrough */
167
+ fallthrough;
132168 case 2:
133169 *bs->rx_buf++ = (data >> 8) & 0xff;
134
- /* fallthrough */
170
+ fallthrough;
135171 case 1:
136172 *bs->rx_buf++ = (data >> 0) & 0xff;
137173 /* fallthrough - no default */
....@@ -245,6 +281,9 @@
245281 {
246282 struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
247283
284
+ /* update statistics */
285
+ bs->count_transfer_irq++;
286
+
248287 /* fill in registers and fifos before enabling interrupts */
249288 bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
250289 bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
....@@ -268,12 +307,15 @@
268307 struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
269308 unsigned long timeout;
270309
310
+ /* update statistics */
311
+ bs->count_transfer_polling++;
312
+
271313 /* configure spi */
272314 bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]);
273315 bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL0, bs->cntl[0]);
274316
275
- /* set the timeout */
276
- timeout = jiffies + BCM2835_AUX_SPI_POLLING_JIFFIES;
317
+ /* set the timeout to at least 2 jiffies */
318
+ timeout = jiffies + 2 + HZ * polling_limit_us / 1000000;
277319
278320 /* loop until finished the transfer */
279321 while (bs->rx_len) {
....@@ -288,6 +330,7 @@
288330 jiffies - timeout,
289331 bs->tx_len, bs->rx_len);
290332 /* forward to interrupt handler */
333
+ bs->count_transfer_irq_after_poll++;
291334 return __bcm2835aux_spi_transfer_one_irq(master,
292335 spi, tfr);
293336 }
....@@ -303,7 +346,7 @@
303346 {
304347 struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
305348 unsigned long spi_hz, clk_hz, speed;
306
- unsigned long spi_used_hz;
349
+ unsigned long hz_per_byte, byte_limit;
307350
308351 /* calculate the registers to handle
309352 *
....@@ -331,7 +374,7 @@
331374 /* set the new speed */
332375 bs->cntl[0] |= speed << BCM2835_AUX_SPI_CNTL0_SPEED_SHIFT;
333376
334
- spi_used_hz = clk_hz / (2 * (speed + 1));
377
+ tfr->effective_speed_hz = clk_hz / (2 * (speed + 1));
335378
336379 /* set transmit buffers and length */
337380 bs->tx_buf = tfr->tx_buf;
....@@ -347,14 +390,15 @@
347390 * of Hz per byte per polling limit. E.g., we can transfer 1 byte in
348391 * 30 µs per 300,000 Hz of bus clock.
349392 */
350
-#define HZ_PER_BYTE ((9 * 1000000) / BCM2835_AUX_SPI_POLLING_LIMIT_US)
393
+ hz_per_byte = polling_limit_us ? (9 * 1000000) / polling_limit_us : 0;
394
+ byte_limit = hz_per_byte ? tfr->effective_speed_hz / hz_per_byte : 1;
395
+
351396 /* run in polling mode for short transfers */
352
- if (tfr->len < spi_used_hz / HZ_PER_BYTE)
397
+ if (tfr->len < byte_limit)
353398 return bcm2835aux_spi_transfer_one_poll(master, spi, tfr);
354399
355400 /* run in interrupt mode for all others */
356401 return bcm2835aux_spi_transfer_one_irq(master, spi, tfr);
357
-#undef HZ_PER_BYTE
358402 }
359403
360404 static int bcm2835aux_spi_prepare_message(struct spi_master *master,
....@@ -399,19 +443,60 @@
399443 bcm2835aux_spi_reset_hw(bs);
400444 }
401445
446
+static int bcm2835aux_spi_setup(struct spi_device *spi)
447
+{
448
+ int ret;
449
+
450
+ /* sanity check for native cs */
451
+ if (spi->mode & SPI_NO_CS)
452
+ return 0;
453
+ if (gpio_is_valid(spi->cs_gpio)) {
454
+ /* with gpio-cs set the GPIO to the correct level
455
+ * and as output (in case the dt has the gpio not configured
456
+ * as output but native cs)
457
+ */
458
+ ret = gpio_direction_output(spi->cs_gpio,
459
+ (spi->mode & SPI_CS_HIGH) ? 0 : 1);
460
+ if (ret)
461
+ dev_err(&spi->dev,
462
+ "could not set gpio %i as output: %i\n",
463
+ spi->cs_gpio, ret);
464
+
465
+ return ret;
466
+ }
467
+
468
+ /* for dt-backwards compatibility: only support native on CS0
469
+ * known things not supported with broken native CS:
470
+ * * multiple chip-selects: cs0-cs2 are all
471
+ * simultaniously asserted whenever there is a transfer
472
+ * this even includes SPI_NO_CS
473
+ * * SPI_CS_HIGH: cs are always asserted low
474
+ * * cs_change: cs is deasserted after each spi_transfer
475
+ * * cs_delay_usec: cs is always deasserted one SCK cycle
476
+ * after the last transfer
477
+ * probably more...
478
+ */
479
+ dev_warn(&spi->dev,
480
+ "Native CS is not supported - please configure cs-gpio in device-tree\n");
481
+
482
+ if (spi->chip_select == 0)
483
+ return 0;
484
+
485
+ dev_warn(&spi->dev, "Native CS is not working for cs > 0\n");
486
+
487
+ return -EINVAL;
488
+}
489
+
402490 static int bcm2835aux_spi_probe(struct platform_device *pdev)
403491 {
404492 struct spi_master *master;
405493 struct bcm2835aux_spi *bs;
406
- struct resource *res;
407494 unsigned long clk_hz;
408495 int err;
409496
410497 master = devm_spi_alloc_master(&pdev->dev, sizeof(*bs));
411
- if (!master) {
412
- dev_err(&pdev->dev, "spi_alloc_master() failed\n");
498
+ if (!master)
413499 return -ENOMEM;
414
- }
415500
416501 platform_set_drvdata(pdev, master);
417502 master->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS);
....@@ -428,6 +513,7 @@
428513 * a spi_transfer
429514 */
430515 master->num_chipselect = 1;
516
+ master->setup = bcm2835aux_spi_setup;
431517 master->transfer_one = bcm2835aux_spi_transfer_one;
432518 master->handle_err = bcm2835aux_spi_handle_err;
433519 master->prepare_message = bcm2835aux_spi_prepare_message;
....@@ -437,23 +523,20 @@
437523 bs = spi_master_get_devdata(master);
438524
439525 /* the main area */
440
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
441
- bs->regs = devm_ioremap_resource(&pdev->dev, res);
526
+ bs->regs = devm_platform_ioremap_resource(pdev, 0);
442527 if (IS_ERR(bs->regs))
443528 return PTR_ERR(bs->regs);
444529
445530 bs->clk = devm_clk_get(&pdev->dev, NULL);
446
- if ((!bs->clk) || (IS_ERR(bs->clk))) {
531
+ if (IS_ERR(bs->clk)) {
447532 err = PTR_ERR(bs->clk);
448533 dev_err(&pdev->dev, "could not get clk: %d\n", err);
449534 return err;
450535 }
451536
452537 bs->irq = platform_get_irq(pdev, 0);
453
- if (bs->irq <= 0) {
454
- dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq);
538
+ if (bs->irq <= 0)
455539 return bs->irq ? bs->irq : -ENODEV;
456
- }
457540
458541 /* this also enables the HW block */
459542 err = clk_prepare_enable(bs->clk);
....@@ -488,6 +571,8 @@
488571 goto out_clk_disable;
489572 }
490573
574
+ bcm2835aux_debugfs_create(bs, dev_name(&pdev->dev));
575
+
491576 return 0;
492577
493578 out_clk_disable:
....@@ -499,6 +584,8 @@
499584 {
500585 struct spi_master *master = platform_get_drvdata(pdev);
501586 struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
587
+
588
+ bcm2835aux_debugfs_remove(bs);
502589
503590 spi_unregister_master(master);
504591
....@@ -528,4 +615,4 @@
528615
529616 MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2835 aux");
530617 MODULE_AUTHOR("Martin Sperl <kernel@martin.sperl.org>");
531
-MODULE_LICENSE("GPL v2");
618
+MODULE_LICENSE("GPL");