Skip to content

Commit 099f942

Browse files
KanjiMonsterbroonie
authored andcommitted
spi: keep track of number of chipselects in spi_device
There are several places where we need to iterate over a device's chipselect. To be able to do it efficiently, store the number of chipselects in spi_device, like we do for controllers. Since we now use a device supplied value, add a check to make sure it isn't more than we can support. Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com> Link: https://patch.msgid.link/20250915183725.219473-3-jonas.gorski@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 188f632 commit 099f942

2 files changed

Lines changed: 24 additions & 9 deletions

File tree

drivers/spi/spi.c

Lines changed: 21 additions & 8 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;
@@ -635,7 +636,7 @@ static inline int spi_dev_check_cs(struct device *dev,
635636
u8 idx_new;
636637

637638
cs = spi_get_chipselect(spi, idx);
638-
for (idx_new = new_idx; idx_new < SPI_CS_CNT_MAX; idx_new++) {
639+
for (idx_new = new_idx; idx_new < new_spi->num_chipselect; idx_new++) {
639640
cs_new = spi_get_chipselect(new_spi, idx_new);
640641
if (is_valid_cs(cs) && is_valid_cs(cs_new) && cs == cs_new) {
641642
dev_err(dev, "chipselect %u already in use\n", cs_new);
@@ -652,7 +653,7 @@ static int spi_dev_check(struct device *dev, void *data)
652653
int status, idx;
653654

654655
if (spi->controller == new_spi->controller) {
655-
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
656+
for (idx = 0; idx < spi->num_chipselect; idx++) {
656657
status = spi_dev_check_cs(dev, spi, idx, new_spi, 0);
657658
if (status)
658659
return status;
@@ -674,7 +675,13 @@ static int __spi_add_device(struct spi_device *spi)
674675
int status, idx;
675676
u8 cs;
676677

677-
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
678+
if (spi->num_chipselect > SPI_CS_CNT_MAX) {
679+
dev_err(dev, "num_cs %d > max %d\n", spi->num_chipselect,
680+
SPI_CS_CNT_MAX);
681+
return -EOVERFLOW;
682+
}
683+
684+
for (idx = 0; idx < spi->num_chipselect; idx++) {
678685
/* Chipselects are numbered 0..max; validate. */
679686
cs = spi_get_chipselect(spi, idx);
680687
if (is_valid_cs(cs) && cs >= ctlr->num_chipselect) {
@@ -689,7 +696,7 @@ static int __spi_add_device(struct spi_device *spi)
689696
* For example, spi->chip_select[0] != spi->chip_select[1] and so on.
690697
*/
691698
if (!spi_controller_is_target(ctlr)) {
692-
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
699+
for (idx = 0; idx < spi->num_chipselect; idx++) {
693700
status = spi_dev_check_cs(dev, spi, idx, spi, idx + 1);
694701
if (status)
695702
return status;
@@ -717,7 +724,7 @@ static int __spi_add_device(struct spi_device *spi)
717724
if (ctlr->cs_gpiods) {
718725
u8 cs;
719726

720-
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
727+
for (idx = 0; idx < spi->num_chipselect; idx++) {
721728
cs = spi_get_chipselect(spi, idx);
722729
if (is_valid_cs(cs))
723730
spi_set_csgpiod(spi, idx, ctlr->cs_gpiods[cs]);
@@ -1024,7 +1031,7 @@ static void spi_res_release(struct spi_controller *ctlr, struct spi_message *mes
10241031

10251032
/*-------------------------------------------------------------------------*/
10261033
#define spi_for_each_valid_cs(spi, idx) \
1027-
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) \
1034+
for (idx = 0; idx < spi->num_chipselect; idx++) \
10281035
if (!(spi->cs_index_mask & BIT(idx))) {} else
10291036

10301037
static inline bool spi_is_last_cs(struct spi_device *spi)
@@ -1080,8 +1087,12 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
10801087
trace_spi_set_cs(spi, activate);
10811088

10821089
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;
1090+
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
1091+
if (enable && idx < spi->num_chipselect)
1092+
spi->controller->last_cs[idx] = spi_get_chipselect(spi, 0);
1093+
else
1094+
spi->controller->last_cs[idx] = SPI_INVALID_CS;
1095+
}
10851096

10861097
spi->controller->last_cs_mode_high = spi->mode & SPI_CS_HIGH;
10871098
if (spi->controller->last_cs_mode_high)
@@ -2452,6 +2463,8 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
24522463
dev_err(&ctlr->dev, "SPI controller doesn't support multi CS\n");
24532464
return -EINVAL;
24542465
}
2466+
2467+
spi->num_chipselect = rc;
24552468
for (idx = 0; idx < rc; idx++)
24562469
spi_set_chipselect(spi, idx, cs[idx]);
24572470

include/linux/spi/spi.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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)
@@ -229,6 +230,7 @@ struct spi_device {
229230
struct spi_delay cs_inactive;
230231

231232
u8 chip_select[SPI_CS_CNT_MAX];
233+
u8 num_chipselect;
232234

233235
/*
234236
* Bit mask of the chipselect(s) that the driver need to use from
@@ -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
}

0 commit comments

Comments
 (0)