Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

spi: support controllers with multiple data lanes

Add support for SPI controllers with multiple physical SPI data lanes.
(A data lane in this context means lines connected to a serializer, so a
controller with two data lanes would have two serializers in a single
controller).

This is common in the type of controller that can be used with parallel
flash memories, but can be used for general purpose SPI as well.

To indicate support, a controller just needs to set ctlr->num_data_lanes
to something greater than 1. Peripherals indicate which lane they are
connected to via device tree (ACPI support can be added if needed).

The spi-{tx,rx}-bus-width DT properties can now be arrays. The length of
the array indicates the number of data lanes, and each element indicates
the bus width of that lane. For now, we restrict all lanes to have the
same bus width to keep things simple. Support for an optional controller
lane mapping property is also implemented.

Signed-off-by: David Lechner <dlechner@baylibre.com>
Link: https://patch.msgid.link/20260123-spi-add-multi-bus-support-v6-3-12af183c06eb@baylibre.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

David Lechner and committed by
Mark Brown
002d561f 31eab842

+162 -4
+140 -4
drivers/spi/spi.c
··· 2354 2354 static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, 2355 2355 struct device_node *nc) 2356 2356 { 2357 - u32 value, cs[SPI_DEVICE_CS_CNT_MAX]; 2358 - int rc, idx; 2357 + u32 value, cs[SPI_DEVICE_CS_CNT_MAX], map[SPI_DEVICE_DATA_LANE_CNT_MAX]; 2358 + int rc, idx, max_num_data_lanes; 2359 2359 2360 2360 /* Mode (clock phase/polarity/etc.) */ 2361 2361 if (of_property_read_bool(nc, "spi-cpha")) ··· 2370 2370 spi->mode |= SPI_CS_HIGH; 2371 2371 2372 2372 /* Device DUAL/QUAD mode */ 2373 - if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) { 2373 + 2374 + rc = of_property_read_variable_u32_array(nc, "spi-tx-lane-map", map, 1, 2375 + ARRAY_SIZE(map)); 2376 + if (rc >= 0) { 2377 + max_num_data_lanes = rc; 2378 + for (idx = 0; idx < max_num_data_lanes; idx++) 2379 + spi->tx_lane_map[idx] = map[idx]; 2380 + } else if (rc == -EINVAL) { 2381 + /* Default lane map is identity mapping. */ 2382 + max_num_data_lanes = ARRAY_SIZE(spi->tx_lane_map); 2383 + for (idx = 0; idx < max_num_data_lanes; idx++) 2384 + spi->tx_lane_map[idx] = idx; 2385 + } else { 2386 + dev_err(&ctlr->dev, 2387 + "failed to read spi-tx-lane-map property: %d\n", rc); 2388 + return rc; 2389 + } 2390 + 2391 + rc = of_property_count_u32_elems(nc, "spi-tx-bus-width"); 2392 + if (rc < 0 && rc != -EINVAL) { 2393 + dev_err(&ctlr->dev, 2394 + "failed to read spi-tx-bus-width property: %d\n", rc); 2395 + return rc; 2396 + } 2397 + if (rc > max_num_data_lanes) { 2398 + dev_err(&ctlr->dev, 2399 + "spi-tx-bus-width has more elements (%d) than spi-tx-lane-map (%d)\n", 2400 + rc, max_num_data_lanes); 2401 + return -EINVAL; 2402 + } 2403 + 2404 + if (rc == -EINVAL) { 2405 + /* Default when property is not present. */ 2406 + spi->num_tx_lanes = 1; 2407 + } else { 2408 + u32 first_value; 2409 + 2410 + spi->num_tx_lanes = rc; 2411 + 2412 + for (idx = 0; idx < spi->num_tx_lanes; idx++) { 2413 + rc = of_property_read_u32_index(nc, "spi-tx-bus-width", 2414 + idx, &value); 2415 + if (rc) 2416 + return rc; 2417 + 2418 + /* 2419 + * For now, we only support all lanes having the same 2420 + * width so we can keep using the existing mode flags. 2421 + */ 2422 + if (!idx) 2423 + first_value = value; 2424 + else if (first_value != value) { 2425 + dev_err(&ctlr->dev, 2426 + "spi-tx-bus-width has inconsistent values: first %d vs later %d\n", 2427 + first_value, value); 2428 + return -EINVAL; 2429 + } 2430 + } 2431 + 2374 2432 switch (value) { 2375 2433 case 0: 2376 2434 spi->mode |= SPI_NO_TX; ··· 2452 2394 } 2453 2395 } 2454 2396 2455 - if (!of_property_read_u32(nc, "spi-rx-bus-width", &value)) { 2397 + for (idx = 0; idx < spi->num_tx_lanes; idx++) { 2398 + if (spi->tx_lane_map[idx] >= spi->controller->num_data_lanes) { 2399 + dev_err(&ctlr->dev, 2400 + "spi-tx-lane-map has invalid value %d (num_data_lanes=%d)\n", 2401 + spi->tx_lane_map[idx], 2402 + spi->controller->num_data_lanes); 2403 + return -EINVAL; 2404 + } 2405 + } 2406 + 2407 + rc = of_property_read_variable_u32_array(nc, "spi-rx-lane-map", map, 1, 2408 + ARRAY_SIZE(map)); 2409 + if (rc >= 0) { 2410 + max_num_data_lanes = rc; 2411 + for (idx = 0; idx < max_num_data_lanes; idx++) 2412 + spi->rx_lane_map[idx] = map[idx]; 2413 + } else if (rc == -EINVAL) { 2414 + /* Default lane map is identity mapping. */ 2415 + max_num_data_lanes = ARRAY_SIZE(spi->rx_lane_map); 2416 + for (idx = 0; idx < max_num_data_lanes; idx++) 2417 + spi->rx_lane_map[idx] = idx; 2418 + } else { 2419 + dev_err(&ctlr->dev, 2420 + "failed to read spi-rx-lane-map property: %d\n", rc); 2421 + return rc; 2422 + } 2423 + 2424 + rc = of_property_count_u32_elems(nc, "spi-rx-bus-width"); 2425 + if (rc < 0 && rc != -EINVAL) { 2426 + dev_err(&ctlr->dev, 2427 + "failed to read spi-rx-bus-width property: %d\n", rc); 2428 + return rc; 2429 + } 2430 + if (rc > max_num_data_lanes) { 2431 + dev_err(&ctlr->dev, 2432 + "spi-rx-bus-width has more elements (%d) than spi-rx-lane-map (%d)\n", 2433 + rc, max_num_data_lanes); 2434 + return -EINVAL; 2435 + } 2436 + 2437 + if (rc == -EINVAL) { 2438 + /* Default when property is not present. */ 2439 + spi->num_rx_lanes = 1; 2440 + } else { 2441 + u32 first_value; 2442 + 2443 + spi->num_rx_lanes = rc; 2444 + 2445 + for (idx = 0; idx < spi->num_rx_lanes; idx++) { 2446 + rc = of_property_read_u32_index(nc, "spi-rx-bus-width", 2447 + idx, &value); 2448 + if (rc) 2449 + return rc; 2450 + 2451 + /* 2452 + * For now, we only support all lanes having the same 2453 + * width so we can keep using the existing mode flags. 2454 + */ 2455 + if (!idx) 2456 + first_value = value; 2457 + else if (first_value != value) { 2458 + dev_err(&ctlr->dev, 2459 + "spi-rx-bus-width has inconsistent values: first %d vs later %d\n", 2460 + first_value, value); 2461 + return -EINVAL; 2462 + } 2463 + } 2464 + 2456 2465 switch (value) { 2457 2466 case 0: 2458 2467 spi->mode |= SPI_NO_RX; ··· 2540 2415 "spi-rx-bus-width %d not supported\n", 2541 2416 value); 2542 2417 break; 2418 + } 2419 + } 2420 + 2421 + for (idx = 0; idx < spi->num_rx_lanes; idx++) { 2422 + if (spi->rx_lane_map[idx] >= spi->controller->num_data_lanes) { 2423 + dev_err(&ctlr->dev, 2424 + "spi-rx-lane-map has invalid value %d (num_data_lanes=%d)\n", 2425 + spi->rx_lane_map[idx], 2426 + spi->controller->num_data_lanes); 2427 + return -EINVAL; 2543 2428 } 2544 2429 } 2545 2430 ··· 3201 3066 mutex_init(&ctlr->add_lock); 3202 3067 ctlr->bus_num = -1; 3203 3068 ctlr->num_chipselect = 1; 3069 + ctlr->num_data_lanes = 1; 3204 3070 ctlr->target = target; 3205 3071 if (IS_ENABLED(CONFIG_SPI_SLAVE) && target) 3206 3072 ctlr->dev.class = &spi_target_class;
+22
include/linux/spi/spi.h
··· 23 23 /* Max no. of CS supported per spi device */ 24 24 #define SPI_DEVICE_CS_CNT_MAX 4 25 25 26 + /* Max no. of data lanes supported per spi device */ 27 + #define SPI_DEVICE_DATA_LANE_CNT_MAX 8 28 + 26 29 struct dma_chan; 27 30 struct software_node; 28 31 struct ptp_system_timestamp; ··· 177 174 * @cs_index_mask: Bit mask of the active chipselect(s) in the chipselect array 178 175 * @cs_gpiod: Array of GPIO descriptors of the corresponding chipselect lines 179 176 * (optional, NULL when not using a GPIO line) 177 + * @tx_lane_map: Map of peripheral lanes (index) to controller lanes (value). 178 + * @num_tx_lanes: Number of transmit lanes wired up. 179 + * @rx_lane_map: Map of peripheral lanes (index) to controller lanes (value). 180 + * @num_rx_lanes: Number of receive lanes wired up. 180 181 * 181 182 * A @spi_device is used to interchange data between an SPI target device 182 183 * (usually a discrete chip) and CPU memory. ··· 248 241 u32 cs_index_mask : SPI_DEVICE_CS_CNT_MAX; 249 242 250 243 struct gpio_desc *cs_gpiod[SPI_DEVICE_CS_CNT_MAX]; /* Chip select gpio desc */ 244 + 245 + /* Multi-lane SPI controller support. */ 246 + u8 tx_lane_map[SPI_DEVICE_DATA_LANE_CNT_MAX]; 247 + u8 num_tx_lanes; 248 + u8 rx_lane_map[SPI_DEVICE_DATA_LANE_CNT_MAX]; 249 + u8 num_rx_lanes; 251 250 252 251 /* 253 252 * Likely need more hooks for more protocol options affecting how ··· 414 401 * SPI targets, and are numbered from zero to num_chipselects. 415 402 * each target has a chipselect signal, but it's common that not 416 403 * every chipselect is connected to a target. 404 + * @num_data_lanes: Number of data lanes supported by this controller. Default is 1. 417 405 * @dma_alignment: SPI controller constraint on DMA buffers alignment. 418 406 * @mode_bits: flags understood by this controller driver 419 407 * @buswidth_override_bits: flags to override for this controller driver ··· 589 575 * might use board-specific GPIOs. 590 576 */ 591 577 u16 num_chipselect; 578 + 579 + /* 580 + * Some specialized SPI controllers can have more than one physical 581 + * data lane interface per controller (each having it's own serializer). 582 + * This specifies the number of data lanes in that case. Other 583 + * controllers do not need to set this (defaults to 1). 584 + */ 585 + u16 num_data_lanes; 592 586 593 587 /* Some SPI controllers pose alignment requirements on DMAable 594 588 * buffers; let protocol drivers know about these requirements.