2323#include <linux/spi/spi.h>
2424#include <trace/events/spi.h>
2525
26+ #define SPI_ENGINE_REG_DATA_WIDTH 0x0C
27+ #define SPI_ENGINE_REG_DATA_WIDTH_NUM_OF_SDIO_MASK GENMASK(23, 16)
28+ #define SPI_ENGINE_REG_DATA_WIDTH_MASK GENMASK(15, 0)
2629#define SPI_ENGINE_REG_OFFLOAD_MEM_ADDR_WIDTH 0x10
2730#define SPI_ENGINE_REG_RESET 0x40
2831
7578#define SPI_ENGINE_CMD_REG_CLK_DIV 0x0
7679#define SPI_ENGINE_CMD_REG_CONFIG 0x1
7780#define SPI_ENGINE_CMD_REG_XFER_BITS 0x2
81+ #define SPI_ENGINE_CMD_REG_SDI_MASK 0x3
82+ #define SPI_ENGINE_CMD_REG_SDO_MASK 0x4
7883
7984#define SPI_ENGINE_MISC_SYNC 0x0
8085#define SPI_ENGINE_MISC_SLEEP 0x1
105110#define SPI_ENGINE_OFFLOAD_CMD_FIFO_SIZE 16
106111#define SPI_ENGINE_OFFLOAD_SDO_FIFO_SIZE 16
107112
113+ /* Extending SPI_MULTI_LANE_MODE values for optimizing messages. */
114+ #define SPI_ENGINE_MULTI_BUS_MODE_UNKNOWN -1
115+ #define SPI_ENGINE_MULTI_BUS_MODE_CONFLICTING -2
116+
108117struct spi_engine_program {
109118 unsigned int length ;
110119 uint16_t instructions [] __counted_by (length );
@@ -142,6 +151,11 @@ struct spi_engine_offload {
142151 unsigned long flags ;
143152 unsigned int offload_num ;
144153 unsigned int spi_mode_config ;
154+ unsigned int multi_lane_mode ;
155+ u8 rx_primary_lane_mask ;
156+ u8 tx_primary_lane_mask ;
157+ u8 rx_all_lanes_mask ;
158+ u8 tx_all_lanes_mask ;
145159 u8 bits_per_word ;
146160};
147161
@@ -165,6 +179,25 @@ struct spi_engine {
165179 bool offload_requires_sync ;
166180};
167181
182+ static void spi_engine_primary_lane_flag (struct spi_device * spi ,
183+ u8 * rx_lane_flags , u8 * tx_lane_flags )
184+ {
185+ * rx_lane_flags = BIT (spi -> rx_lane_map [0 ]);
186+ * tx_lane_flags = BIT (spi -> tx_lane_map [0 ]);
187+ }
188+
189+ static void spi_engine_all_lanes_flags (struct spi_device * spi ,
190+ u8 * rx_lane_flags , u8 * tx_lane_flags )
191+ {
192+ int i ;
193+
194+ for (i = 0 ; i < spi -> num_rx_lanes ; i ++ )
195+ * rx_lane_flags |= BIT (spi -> rx_lane_map [i ]);
196+
197+ for (i = 0 ; i < spi -> num_tx_lanes ; i ++ )
198+ * tx_lane_flags |= BIT (spi -> tx_lane_map [i ]);
199+ }
200+
168201static void spi_engine_program_add_cmd (struct spi_engine_program * p ,
169202 bool dry , uint16_t cmd )
170203{
@@ -193,7 +226,7 @@ static unsigned int spi_engine_get_config(struct spi_device *spi)
193226}
194227
195228static void spi_engine_gen_xfer (struct spi_engine_program * p , bool dry ,
196- struct spi_transfer * xfer )
229+ struct spi_transfer * xfer , u32 num_lanes )
197230{
198231 unsigned int len ;
199232
@@ -204,6 +237,9 @@ static void spi_engine_gen_xfer(struct spi_engine_program *p, bool dry,
204237 else
205238 len = xfer -> len / 4 ;
206239
240+ if (xfer -> multi_lane_mode == SPI_MULTI_LANE_MODE_STRIPE )
241+ len /= num_lanes ;
242+
207243 while (len ) {
208244 unsigned int n = min (len , 256U );
209245 unsigned int flags = 0 ;
@@ -269,6 +305,7 @@ static int spi_engine_precompile_message(struct spi_message *msg)
269305{
270306 unsigned int clk_div , max_hz = msg -> spi -> controller -> max_speed_hz ;
271307 struct spi_transfer * xfer ;
308+ int multi_lane_mode = SPI_ENGINE_MULTI_BUS_MODE_UNKNOWN ;
272309 u8 min_bits_per_word = U8_MAX ;
273310 u8 max_bits_per_word = 0 ;
274311
@@ -284,6 +321,24 @@ static int spi_engine_precompile_message(struct spi_message *msg)
284321 min_bits_per_word = min (min_bits_per_word , xfer -> bits_per_word );
285322 max_bits_per_word = max (max_bits_per_word , xfer -> bits_per_word );
286323 }
324+
325+ if (xfer -> rx_buf || xfer -> offload_flags & SPI_OFFLOAD_XFER_RX_STREAM ||
326+ xfer -> tx_buf || xfer -> offload_flags & SPI_OFFLOAD_XFER_TX_STREAM ) {
327+ switch (xfer -> multi_lane_mode ) {
328+ case SPI_MULTI_LANE_MODE_SINGLE :
329+ case SPI_MULTI_LANE_MODE_STRIPE :
330+ break ;
331+ default :
332+ /* Other modes, like mirror not supported */
333+ return - EINVAL ;
334+ }
335+
336+ /* If all xfers have the same multi-lane mode, we can optimize. */
337+ if (multi_lane_mode == SPI_ENGINE_MULTI_BUS_MODE_UNKNOWN )
338+ multi_lane_mode = xfer -> multi_lane_mode ;
339+ else if (multi_lane_mode != xfer -> multi_lane_mode )
340+ multi_lane_mode = SPI_ENGINE_MULTI_BUS_MODE_CONFLICTING ;
341+ }
287342 }
288343
289344 /*
@@ -297,6 +352,14 @@ static int spi_engine_precompile_message(struct spi_message *msg)
297352 priv -> bits_per_word = min_bits_per_word ;
298353 else
299354 priv -> bits_per_word = 0 ;
355+
356+ priv -> multi_lane_mode = multi_lane_mode ;
357+ spi_engine_primary_lane_flag (msg -> spi ,
358+ & priv -> rx_primary_lane_mask ,
359+ & priv -> tx_primary_lane_mask );
360+ spi_engine_all_lanes_flags (msg -> spi ,
361+ & priv -> rx_all_lanes_mask ,
362+ & priv -> tx_all_lanes_mask );
300363 }
301364
302365 return 0 ;
@@ -310,6 +373,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
310373 struct spi_engine_offload * priv ;
311374 struct spi_transfer * xfer ;
312375 int clk_div , new_clk_div , inst_ns ;
376+ int prev_multi_lane_mode = SPI_MULTI_LANE_MODE_SINGLE ;
313377 bool keep_cs = false;
314378 u8 bits_per_word = 0 ;
315379
@@ -334,6 +398,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
334398 * in the same way.
335399 */
336400 bits_per_word = priv -> bits_per_word ;
401+ prev_multi_lane_mode = priv -> multi_lane_mode ;
337402 } else {
338403 spi_engine_program_add_cmd (p , dry ,
339404 SPI_ENGINE_CMD_WRITE (SPI_ENGINE_CMD_REG_CONFIG ,
@@ -344,6 +409,28 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
344409 spi_engine_gen_cs (p , dry , spi , !xfer -> cs_off );
345410
346411 list_for_each_entry (xfer , & msg -> transfers , transfer_list ) {
412+ if (xfer -> rx_buf || xfer -> offload_flags & SPI_OFFLOAD_XFER_RX_STREAM ||
413+ xfer -> tx_buf || xfer -> offload_flags & SPI_OFFLOAD_XFER_TX_STREAM ) {
414+ if (xfer -> multi_lane_mode != prev_multi_lane_mode ) {
415+ u8 tx_lane_flags , rx_lane_flags ;
416+
417+ if (xfer -> multi_lane_mode == SPI_MULTI_LANE_MODE_STRIPE )
418+ spi_engine_all_lanes_flags (spi , & rx_lane_flags ,
419+ & tx_lane_flags );
420+ else
421+ spi_engine_primary_lane_flag (spi , & rx_lane_flags ,
422+ & tx_lane_flags );
423+
424+ spi_engine_program_add_cmd (p , dry ,
425+ SPI_ENGINE_CMD_WRITE (SPI_ENGINE_CMD_REG_SDI_MASK ,
426+ rx_lane_flags ));
427+ spi_engine_program_add_cmd (p , dry ,
428+ SPI_ENGINE_CMD_WRITE (SPI_ENGINE_CMD_REG_SDO_MASK ,
429+ tx_lane_flags ));
430+ }
431+ prev_multi_lane_mode = xfer -> multi_lane_mode ;
432+ }
433+
347434 new_clk_div = host -> max_speed_hz / xfer -> effective_speed_hz ;
348435 if (new_clk_div != clk_div ) {
349436 clk_div = new_clk_div ;
@@ -360,7 +447,7 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
360447 bits_per_word ));
361448 }
362449
363- spi_engine_gen_xfer (p , dry , xfer );
450+ spi_engine_gen_xfer (p , dry , xfer , spi -> num_rx_lanes );
364451 spi_engine_gen_sleep (p , dry , spi_delay_to_ns (& xfer -> delay , xfer ),
365452 inst_ns , xfer -> effective_speed_hz );
366453
@@ -394,6 +481,19 @@ static void spi_engine_compile_message(struct spi_message *msg, bool dry,
394481 if (clk_div != 1 )
395482 spi_engine_program_add_cmd (p , dry ,
396483 SPI_ENGINE_CMD_WRITE (SPI_ENGINE_CMD_REG_CLK_DIV , 0 ));
484+
485+ /* Restore single lane mode unless offload disable will restore it later. */
486+ if (prev_multi_lane_mode == SPI_MULTI_LANE_MODE_STRIPE &&
487+ (!msg -> offload || priv -> multi_lane_mode != SPI_MULTI_LANE_MODE_STRIPE )) {
488+ u8 rx_lane_flags , tx_lane_flags ;
489+
490+ spi_engine_primary_lane_flag (spi , & rx_lane_flags , & tx_lane_flags );
491+
492+ spi_engine_program_add_cmd (p , dry ,
493+ SPI_ENGINE_CMD_WRITE (SPI_ENGINE_CMD_REG_SDI_MASK , rx_lane_flags ));
494+ spi_engine_program_add_cmd (p , dry ,
495+ SPI_ENGINE_CMD_WRITE (SPI_ENGINE_CMD_REG_SDO_MASK , tx_lane_flags ));
496+ }
397497}
398498
399499static void spi_engine_xfer_next (struct spi_message * msg ,
@@ -799,6 +899,19 @@ static int spi_engine_setup(struct spi_device *device)
799899 writel_relaxed (SPI_ENGINE_CMD_CS_INV (spi_engine -> cs_inv ),
800900 spi_engine -> base + SPI_ENGINE_REG_CMD_FIFO );
801901
902+ if (host -> num_data_lanes > 1 ) {
903+ u8 rx_lane_flags , tx_lane_flags ;
904+
905+ spi_engine_primary_lane_flag (device , & rx_lane_flags , & tx_lane_flags );
906+
907+ writel_relaxed (SPI_ENGINE_CMD_WRITE (SPI_ENGINE_CMD_REG_SDI_MASK ,
908+ rx_lane_flags ),
909+ spi_engine -> base + SPI_ENGINE_REG_CMD_FIFO );
910+ writel_relaxed (SPI_ENGINE_CMD_WRITE (SPI_ENGINE_CMD_REG_SDO_MASK ,
911+ tx_lane_flags ),
912+ spi_engine -> base + SPI_ENGINE_REG_CMD_FIFO );
913+ }
914+
802915 /*
803916 * In addition to setting the flags, we have to do a CS assert command
804917 * to make the new setting actually take effect.
@@ -902,6 +1015,15 @@ static int spi_engine_trigger_enable(struct spi_offload *offload)
9021015 priv -> bits_per_word ),
9031016 spi_engine -> base + SPI_ENGINE_REG_CMD_FIFO );
9041017
1018+ if (priv -> multi_lane_mode == SPI_MULTI_LANE_MODE_STRIPE ) {
1019+ writel_relaxed (SPI_ENGINE_CMD_WRITE (SPI_ENGINE_CMD_REG_SDI_MASK ,
1020+ priv -> rx_all_lanes_mask ),
1021+ spi_engine -> base + SPI_ENGINE_REG_CMD_FIFO );
1022+ writel_relaxed (SPI_ENGINE_CMD_WRITE (SPI_ENGINE_CMD_REG_SDO_MASK ,
1023+ priv -> tx_all_lanes_mask ),
1024+ spi_engine -> base + SPI_ENGINE_REG_CMD_FIFO );
1025+ }
1026+
9051027 writel_relaxed (SPI_ENGINE_CMD_SYNC (1 ),
9061028 spi_engine -> base + SPI_ENGINE_REG_CMD_FIFO );
9071029
@@ -929,6 +1051,16 @@ static void spi_engine_trigger_disable(struct spi_offload *offload)
9291051 reg &= ~SPI_ENGINE_OFFLOAD_CTRL_ENABLE ;
9301052 writel_relaxed (reg , spi_engine -> base +
9311053 SPI_ENGINE_REG_OFFLOAD_CTRL (priv -> offload_num ));
1054+
1055+ /* Restore single-lane mode. */
1056+ if (priv -> multi_lane_mode == SPI_MULTI_LANE_MODE_STRIPE ) {
1057+ writel_relaxed (SPI_ENGINE_CMD_WRITE (SPI_ENGINE_CMD_REG_SDI_MASK ,
1058+ priv -> rx_primary_lane_mask ),
1059+ spi_engine -> base + SPI_ENGINE_REG_CMD_FIFO );
1060+ writel_relaxed (SPI_ENGINE_CMD_WRITE (SPI_ENGINE_CMD_REG_SDO_MASK ,
1061+ priv -> tx_primary_lane_mask ),
1062+ spi_engine -> base + SPI_ENGINE_REG_CMD_FIFO );
1063+ }
9321064}
9331065
9341066static struct dma_chan
@@ -973,7 +1105,7 @@ static int spi_engine_probe(struct platform_device *pdev)
9731105{
9741106 struct spi_engine * spi_engine ;
9751107 struct spi_controller * host ;
976- unsigned int version ;
1108+ unsigned int version , data_width_reg_val ;
9771109 int irq , ret ;
9781110
9791111 irq = platform_get_irq (pdev , 0 );
@@ -1042,14 +1174,16 @@ static int spi_engine_probe(struct platform_device *pdev)
10421174 return PTR_ERR (spi_engine -> base );
10431175
10441176 version = readl (spi_engine -> base + ADI_AXI_REG_VERSION );
1045- if (ADI_AXI_PCORE_VER_MAJOR (version ) != 1 ) {
1177+ if (ADI_AXI_PCORE_VER_MAJOR (version ) > 2 ) {
10461178 dev_err (& pdev -> dev , "Unsupported peripheral version %u.%u.%u\n" ,
10471179 ADI_AXI_PCORE_VER_MAJOR (version ),
10481180 ADI_AXI_PCORE_VER_MINOR (version ),
10491181 ADI_AXI_PCORE_VER_PATCH (version ));
10501182 return - ENODEV ;
10511183 }
10521184
1185+ data_width_reg_val = readl (spi_engine -> base + SPI_ENGINE_REG_DATA_WIDTH );
1186+
10531187 if (adi_axi_pcore_ver_gteq (version , 1 , 1 )) {
10541188 unsigned int sizes = readl (spi_engine -> base +
10551189 SPI_ENGINE_REG_OFFLOAD_MEM_ADDR_WIDTH );
@@ -1097,6 +1231,9 @@ static int spi_engine_probe(struct platform_device *pdev)
10971231 }
10981232 if (adi_axi_pcore_ver_gteq (version , 1 , 3 ))
10991233 host -> mode_bits |= SPI_MOSI_IDLE_LOW | SPI_MOSI_IDLE_HIGH ;
1234+ if (adi_axi_pcore_ver_gteq (version , 2 , 0 ))
1235+ host -> num_data_lanes = FIELD_GET (SPI_ENGINE_REG_DATA_WIDTH_NUM_OF_SDIO_MASK ,
1236+ data_width_reg_val );
11001237
11011238 if (host -> max_speed_hz == 0 )
11021239 return dev_err_probe (& pdev -> dev , - EINVAL , "spi_clk rate is 0" );
0 commit comments