Skip to content

Commit 7ea79f5

Browse files
committed
spi: multi CS cleanup and controller CS limit
Merge series from Jonas Gorski <[email protected]>: This series aims at cleaning up the current multi CS parts and removing the CS limit per controller that was introduced with the multi CS support. To do this, store the assigned chip selects per device in spi_device::num_chipselects, which allows us to use that instead of SPI_CS_CNT_MAX for most loops, as well as remove the check for SPI_INVALID_CS for any chip select. This should hopefully make it obvious that SPI_CS_CNT_MAX only limits accesses to arrays indexed by the number of chip selects of a device, not the controller, and we can remove the check for spi_controller::num_chipselects being less than SPI_CS_CNT_MAX in device registration (which was the wrong place to do that anyway). After having done that, we can reduce SPI_CS_CNT_MAX again to 4 without breaking devices on higher CS lines. Finally, rename SPI_CS_CNT_MAX to SPI_DEVICE_CNT_MAX to make it more clear that this limit only applies to devices, not controllers. There are still more issues left, but these can be addressed in future submissions: * The code allows multi-cs devices for any controller, as long as the device does not set parallel-memories. * No current spi controller driver handles logical chip selects other than the first one, and always use it, regardless what cs_index_mask says. * While most spi controllers should be able to handle devices that have multiple cs that just get enabled selectively, but not at the same time, there is no way to tell that to the core (ties into the above). * There is no parallel memories/multi cs flag for devices, so any implementing driver needs to check the device tree node, making it impossible to register these kind of devices via platform code.
2 parents 8787027 + e336ab5 commit 7ea79f5

3 files changed

Lines changed: 42 additions & 51 deletions

File tree

drivers/spi/spi-cadence-quadspi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
#define CQSPI_NAME "cadence-qspi"
3434
#define CQSPI_MAX_CHIPSELECT 4
3535

36-
static_assert(CQSPI_MAX_CHIPSELECT <= SPI_CS_CNT_MAX);
36+
static_assert(CQSPI_MAX_CHIPSELECT <= SPI_DEVICE_CS_CNT_MAX);
3737

3838
/* Quirks */
3939
#define CQSPI_NEEDS_WR_DELAY BIT(0)

drivers/spi/spi.c

Lines changed: 32 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,7 @@ struct spi_device *spi_alloc_device(struct spi_controller *ctlr)
586586
spi->dev.bus = &spi_bus_type;
587587
spi->dev.release = spidev_release;
588588
spi->mode = ctlr->buswidth_override_bits;
589+
spi->num_chipselect = 1;
589590

590591
device_initialize(&spi->dev);
591592
return spi;
@@ -622,11 +623,6 @@ static void spi_dev_set_name(struct spi_device *spi)
622623
*/
623624
#define SPI_INVALID_CS ((s8)-1)
624625

625-
static inline bool is_valid_cs(s8 chip_select)
626-
{
627-
return chip_select != SPI_INVALID_CS;
628-
}
629-
630626
static inline int spi_dev_check_cs(struct device *dev,
631627
struct spi_device *spi, u8 idx,
632628
struct spi_device *new_spi, u8 new_idx)
@@ -635,9 +631,9 @@ static inline int spi_dev_check_cs(struct device *dev,
635631
u8 idx_new;
636632

637633
cs = spi_get_chipselect(spi, idx);
638-
for (idx_new = new_idx; idx_new < SPI_CS_CNT_MAX; idx_new++) {
634+
for (idx_new = new_idx; idx_new < new_spi->num_chipselect; idx_new++) {
639635
cs_new = spi_get_chipselect(new_spi, idx_new);
640-
if (is_valid_cs(cs) && is_valid_cs(cs_new) && cs == cs_new) {
636+
if (cs == cs_new) {
641637
dev_err(dev, "chipselect %u already in use\n", cs_new);
642638
return -EBUSY;
643639
}
@@ -652,7 +648,7 @@ static int spi_dev_check(struct device *dev, void *data)
652648
int status, idx;
653649

654650
if (spi->controller == new_spi->controller) {
655-
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
651+
for (idx = 0; idx < spi->num_chipselect; idx++) {
656652
status = spi_dev_check_cs(dev, spi, idx, new_spi, 0);
657653
if (status)
658654
return status;
@@ -674,10 +670,16 @@ static int __spi_add_device(struct spi_device *spi)
674670
int status, idx;
675671
u8 cs;
676672

677-
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
673+
if (spi->num_chipselect > SPI_DEVICE_CS_CNT_MAX) {
674+
dev_err(dev, "num_cs %d > max %d\n", spi->num_chipselect,
675+
SPI_DEVICE_CS_CNT_MAX);
676+
return -EOVERFLOW;
677+
}
678+
679+
for (idx = 0; idx < spi->num_chipselect; idx++) {
678680
/* Chipselects are numbered 0..max; validate. */
679681
cs = spi_get_chipselect(spi, idx);
680-
if (is_valid_cs(cs) && cs >= ctlr->num_chipselect) {
682+
if (cs >= ctlr->num_chipselect) {
681683
dev_err(dev, "cs%d >= max %d\n", spi_get_chipselect(spi, idx),
682684
ctlr->num_chipselect);
683685
return -EINVAL;
@@ -689,13 +691,17 @@ static int __spi_add_device(struct spi_device *spi)
689691
* For example, spi->chip_select[0] != spi->chip_select[1] and so on.
690692
*/
691693
if (!spi_controller_is_target(ctlr)) {
692-
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
694+
for (idx = 0; idx < spi->num_chipselect; idx++) {
693695
status = spi_dev_check_cs(dev, spi, idx, spi, idx + 1);
694696
if (status)
695697
return status;
696698
}
697699
}
698700

701+
/* Initialize unused logical CS as invalid */
702+
for (idx = spi->num_chipselect; idx < SPI_DEVICE_CS_CNT_MAX; idx++)
703+
spi_set_chipselect(spi, idx, SPI_INVALID_CS);
704+
699705
/* Set the bus ID string */
700706
spi_dev_set_name(spi);
701707

@@ -717,10 +723,9 @@ static int __spi_add_device(struct spi_device *spi)
717723
if (ctlr->cs_gpiods) {
718724
u8 cs;
719725

720-
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
726+
for (idx = 0; idx < spi->num_chipselect; idx++) {
721727
cs = spi_get_chipselect(spi, idx);
722-
if (is_valid_cs(cs))
723-
spi_set_csgpiod(spi, idx, ctlr->cs_gpiods[cs]);
728+
spi_set_csgpiod(spi, idx, ctlr->cs_gpiods[cs]);
724729
}
725730
}
726731

@@ -773,14 +778,6 @@ int spi_add_device(struct spi_device *spi)
773778
}
774779
EXPORT_SYMBOL_GPL(spi_add_device);
775780

776-
static void spi_set_all_cs_unused(struct spi_device *spi)
777-
{
778-
u8 idx;
779-
780-
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++)
781-
spi_set_chipselect(spi, idx, SPI_INVALID_CS);
782-
}
783-
784781
/**
785782
* spi_new_device - instantiate one new SPI device
786783
* @ctlr: Controller to which device is connected
@@ -816,7 +813,6 @@ struct spi_device *spi_new_device(struct spi_controller *ctlr,
816813
WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
817814

818815
/* Use provided chip-select for proxy device */
819-
spi_set_all_cs_unused(proxy);
820816
spi_set_chipselect(proxy, 0, chip->chip_select);
821817

822818
proxy->max_speed_hz = chip->max_speed_hz;
@@ -1024,7 +1020,7 @@ static void spi_res_release(struct spi_controller *ctlr, struct spi_message *mes
10241020

10251021
/*-------------------------------------------------------------------------*/
10261022
#define spi_for_each_valid_cs(spi, idx) \
1027-
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) \
1023+
for (idx = 0; idx < spi->num_chipselect; idx++) \
10281024
if (!(spi->cs_index_mask & BIT(idx))) {} else
10291025

10301026
static inline bool spi_is_last_cs(struct spi_device *spi)
@@ -1080,8 +1076,12 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
10801076
trace_spi_set_cs(spi, activate);
10811077

10821078
spi->controller->last_cs_index_mask = spi->cs_index_mask;
1083-
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++)
1084-
spi->controller->last_cs[idx] = enable ? spi_get_chipselect(spi, 0) : SPI_INVALID_CS;
1079+
for (idx = 0; idx < SPI_DEVICE_CS_CNT_MAX; idx++) {
1080+
if (enable && idx < spi->num_chipselect)
1081+
spi->controller->last_cs[idx] = spi_get_chipselect(spi, 0);
1082+
else
1083+
spi->controller->last_cs[idx] = SPI_INVALID_CS;
1084+
}
10851085

10861086
spi->controller->last_cs_mode_high = spi->mode & SPI_CS_HIGH;
10871087
if (spi->controller->last_cs_mode_high)
@@ -2354,7 +2354,7 @@ static void of_spi_parse_dt_cs_delay(struct device_node *nc,
23542354
static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
23552355
struct device_node *nc)
23562356
{
2357-
u32 value, cs[SPI_CS_CNT_MAX];
2357+
u32 value, cs[SPI_DEVICE_CS_CNT_MAX];
23582358
int rc, idx;
23592359

23602360
/* Mode (clock phase/polarity/etc.) */
@@ -2427,31 +2427,22 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
24272427
return 0;
24282428
}
24292429

2430-
if (ctlr->num_chipselect > SPI_CS_CNT_MAX) {
2431-
dev_err(&ctlr->dev, "No. of CS is more than max. no. of supported CS\n");
2432-
return -EINVAL;
2433-
}
2434-
2435-
spi_set_all_cs_unused(spi);
2436-
24372430
/* Device address */
24382431
rc = of_property_read_variable_u32_array(nc, "reg", &cs[0], 1,
2439-
SPI_CS_CNT_MAX);
2432+
SPI_DEVICE_CS_CNT_MAX);
24402433
if (rc < 0) {
24412434
dev_err(&ctlr->dev, "%pOF has no valid 'reg' property (%d)\n",
24422435
nc, rc);
24432436
return rc;
24442437
}
2445-
if (rc > ctlr->num_chipselect) {
2446-
dev_err(&ctlr->dev, "%pOF has number of CS > ctlr->num_chipselect (%d)\n",
2447-
nc, rc);
2448-
return rc;
2449-
}
2438+
24502439
if ((of_property_present(nc, "parallel-memories")) &&
24512440
(!(ctlr->flags & SPI_CONTROLLER_MULTI_CS))) {
24522441
dev_err(&ctlr->dev, "SPI controller doesn't support multi CS\n");
24532442
return -EINVAL;
24542443
}
2444+
2445+
spi->num_chipselect = rc;
24552446
for (idx = 0; idx < rc; idx++)
24562447
spi_set_chipselect(spi, idx, cs[idx]);
24572448

@@ -2576,7 +2567,6 @@ struct spi_device *spi_new_ancillary_device(struct spi_device *spi,
25762567
strscpy(ancillary->modalias, "dummy", sizeof(ancillary->modalias));
25772568

25782569
/* Use provided chip-select for ancillary device */
2579-
spi_set_all_cs_unused(ancillary);
25802570
spi_set_chipselect(ancillary, 0, chip_select);
25812571

25822572
/* Take over SPI mode/speed from SPI main device */
@@ -2824,7 +2814,6 @@ struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr,
28242814
return ERR_PTR(-ENOMEM);
28252815
}
28262816

2827-
spi_set_all_cs_unused(spi);
28282817
spi_set_chipselect(spi, 0, lookup.chip_select);
28292818

28302819
ACPI_COMPANION_SET(&spi->dev, adev);
@@ -3324,7 +3313,7 @@ int spi_register_controller(struct spi_controller *ctlr)
33243313
}
33253314

33263315
/* Setting last_cs to SPI_INVALID_CS means no chip selected */
3327-
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++)
3316+
for (idx = 0; idx < SPI_DEVICE_CS_CNT_MAX; idx++)
33283317
ctlr->last_cs[idx] = SPI_INVALID_CS;
33293318

33303319
status = device_add(&ctlr->dev);

include/linux/spi/spi.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#include <uapi/linux/spi/spi.h>
2222

2323
/* Max no. of CS supported per spi device */
24-
#define SPI_CS_CNT_MAX 24
24+
#define SPI_DEVICE_CS_CNT_MAX 4
2525

2626
struct dma_chan;
2727
struct software_node;
@@ -170,6 +170,7 @@ extern void spi_transfer_cs_change_delay_exec(struct spi_message *msg,
170170
* two delays will be added up.
171171
* @chip_select: Array of physical chipselect, spi->chipselect[i] gives
172172
* the corresponding physical CS for logical CS i.
173+
* @num_chipselect: Number of physical chipselects used.
173174
* @cs_index_mask: Bit mask of the active chipselect(s) in the chipselect array
174175
* @cs_gpiod: Array of GPIO descriptors of the corresponding chipselect lines
175176
* (optional, NULL when not using a GPIO line)
@@ -228,17 +229,18 @@ struct spi_device {
228229
struct spi_delay cs_hold;
229230
struct spi_delay cs_inactive;
230231

231-
u8 chip_select[SPI_CS_CNT_MAX];
232+
u8 chip_select[SPI_DEVICE_CS_CNT_MAX];
233+
u8 num_chipselect;
232234

233235
/*
234236
* Bit mask of the chipselect(s) that the driver need to use from
235237
* the chipselect array. When the controller is capable to handle
236238
* multiple chip selects & memories are connected in parallel
237239
* then more than one bit need to be set in cs_index_mask.
238240
*/
239-
u32 cs_index_mask : SPI_CS_CNT_MAX;
241+
u32 cs_index_mask : SPI_DEVICE_CS_CNT_MAX;
240242

241-
struct gpio_desc *cs_gpiod[SPI_CS_CNT_MAX]; /* Chip select gpio desc */
243+
struct gpio_desc *cs_gpiod[SPI_DEVICE_CS_CNT_MAX]; /* Chip select gpio desc */
242244

243245
/*
244246
* Likely need more hooks for more protocol options affecting how
@@ -315,7 +317,7 @@ static inline bool spi_is_csgpiod(struct spi_device *spi)
315317
{
316318
u8 idx;
317319

318-
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
320+
for (idx = 0; idx < spi->num_chipselect; idx++) {
319321
if (spi_get_csgpiod(spi, idx))
320322
return true;
321323
}
@@ -719,8 +721,8 @@ struct spi_controller {
719721
bool auto_runtime_pm;
720722
bool fallback;
721723
bool last_cs_mode_high;
722-
s8 last_cs[SPI_CS_CNT_MAX];
723-
u32 last_cs_index_mask : SPI_CS_CNT_MAX;
724+
s8 last_cs[SPI_DEVICE_CS_CNT_MAX];
725+
u32 last_cs_index_mask : SPI_DEVICE_CS_CNT_MAX;
724726
struct completion xfer_completion;
725727
size_t max_dma_len;
726728

0 commit comments

Comments
 (0)