9
9
#include <linux/interrupt.h>
10
10
#include <linux/io.h>
11
11
#include <linux/iopoll.h>
12
+ #include <linux/jiffies.h>
12
13
#include <linux/kernel.h>
13
14
#include <linux/mailbox_controller.h>
14
15
#include <linux/module.h>
24
25
#define IMX_MU_S4_CHANS 2
25
26
#define IMX_MU_CHAN_NAME_SIZE 20
26
27
28
+ #define IMX_MU_SECO_TX_TOUT (msecs_to_jiffies(3000))
29
+ #define IMX_MU_SECO_RX_TOUT (msecs_to_jiffies(3000))
30
+
27
31
enum imx_mu_chan_type {
28
32
IMX_MU_TYPE_TX , /* Tx */
29
33
IMX_MU_TYPE_RX , /* Rx */
@@ -48,7 +52,7 @@ enum imx_mu_xsr {
48
52
49
53
struct imx_sc_rpc_msg_max {
50
54
struct imx_sc_rpc_msg hdr ;
51
- u32 data [7 ];
55
+ u32 data [30 ];
52
56
};
53
57
54
58
struct imx_s4_rpc_msg_max {
@@ -131,6 +135,55 @@ static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
131
135
return ioread32 (priv -> base + offs );
132
136
}
133
137
138
+ static int imx_mu_tx_waiting_write (struct imx_mu_priv * priv , u32 val , u32 idx )
139
+ {
140
+ u64 timeout_time = get_jiffies_64 () + IMX_MU_SECO_TX_TOUT ;
141
+ u32 status ;
142
+ u32 can_write ;
143
+
144
+ dev_dbg (priv -> dev , "Trying to write %.8x to idx %d\n" , val , idx );
145
+
146
+ do {
147
+ status = imx_mu_read (priv , priv -> dcfg -> xSR [IMX_MU_TSR ]);
148
+ can_write = status & IMX_MU_xSR_TEn (priv -> dcfg -> type , idx % 4 );
149
+ } while (!can_write && time_is_after_jiffies64 (timeout_time ));
150
+
151
+ if (!can_write ) {
152
+ dev_err (priv -> dev , "timeout trying to write %.8x at %d(%.8x)\n" ,
153
+ val , idx , status );
154
+ return - ETIME ;
155
+ }
156
+
157
+ imx_mu_write (priv , val , priv -> dcfg -> xTR + (idx % 4 ) * 4 );
158
+
159
+ return 0 ;
160
+ }
161
+
162
+ static int imx_mu_rx_waiting_read (struct imx_mu_priv * priv , u32 * val , u32 idx )
163
+ {
164
+ u64 timeout_time = get_jiffies_64 () + IMX_MU_SECO_RX_TOUT ;
165
+ u32 status ;
166
+ u32 can_read ;
167
+
168
+ dev_dbg (priv -> dev , "Trying to read from idx %d\n" , idx );
169
+
170
+ do {
171
+ status = imx_mu_read (priv , priv -> dcfg -> xSR [IMX_MU_RSR ]);
172
+ can_read = status & IMX_MU_xSR_RFn (priv -> dcfg -> type , idx % 4 );
173
+ } while (!can_read && time_is_after_jiffies64 (timeout_time ));
174
+
175
+ if (!can_read ) {
176
+ dev_err (priv -> dev , "timeout trying to read idx %d (%.8x)\n" ,
177
+ idx , status );
178
+ return - ETIME ;
179
+ }
180
+
181
+ * val = imx_mu_read (priv , priv -> dcfg -> xRR + (idx % 4 ) * 4 );
182
+ dev_dbg (priv -> dev , "Read %.8x\n" , * val );
183
+
184
+ return 0 ;
185
+ }
186
+
134
187
static u32 imx_mu_xcr_rmw (struct imx_mu_priv * priv , enum imx_mu_xcr type , u32 set , u32 clr )
135
188
{
136
189
unsigned long flags ;
@@ -289,6 +342,125 @@ static int imx_mu_specific_rx(struct imx_mu_priv *priv, struct imx_mu_con_priv *
289
342
return 0 ;
290
343
}
291
344
345
+ static int imx_mu_seco_tx (struct imx_mu_priv * priv , struct imx_mu_con_priv * cp ,
346
+ void * data )
347
+ {
348
+ struct imx_sc_rpc_msg_max * msg = data ;
349
+ u32 * arg = data ;
350
+ u32 byte_size ;
351
+ int err ;
352
+ int i ;
353
+
354
+ dev_dbg (priv -> dev , "Sending message\n" );
355
+
356
+ switch (cp -> type ) {
357
+ case IMX_MU_TYPE_TXDB :
358
+ byte_size = msg -> hdr .size * sizeof (u32 );
359
+ if (byte_size > sizeof (* msg )) {
360
+ /*
361
+ * The real message size can be different to
362
+ * struct imx_sc_rpc_msg_max size
363
+ */
364
+ dev_err (priv -> dev ,
365
+ "Exceed max msg size (%zu) on TX, got: %i\n" ,
366
+ sizeof (* msg ), byte_size );
367
+ return - EINVAL ;
368
+ }
369
+
370
+ print_hex_dump_debug ("from client " , DUMP_PREFIX_OFFSET , 4 , 4 ,
371
+ data , byte_size , false);
372
+
373
+ /* Send first word */
374
+ dev_dbg (priv -> dev , "Sending header\n" );
375
+ imx_mu_write (priv , * arg ++ , priv -> dcfg -> xTR );
376
+
377
+ /* Send signaling */
378
+ dev_dbg (priv -> dev , "Sending signaling\n" );
379
+ imx_mu_xcr_rmw (priv , IMX_MU_GCR ,
380
+ IMX_MU_xCR_GIRn (priv -> dcfg -> type , cp -> idx ), 0 );
381
+
382
+ /* Send words to fill the mailbox */
383
+ for (i = 1 ; i < 4 && i < msg -> hdr .size ; i ++ ) {
384
+ dev_dbg (priv -> dev , "Sending word %d\n" , i );
385
+ imx_mu_write (priv , * arg ++ ,
386
+ priv -> dcfg -> xTR + (i % 4 ) * 4 );
387
+ }
388
+
389
+ /* Send rest of message waiting for remote read */
390
+ for (; i < msg -> hdr .size ; i ++ ) {
391
+ dev_dbg (priv -> dev , "Sending word %d\n" , i );
392
+ err = imx_mu_tx_waiting_write (priv , * arg ++ , i );
393
+ if (err ) {
394
+ dev_err (priv -> dev , "Timeout tx %d\n" , i );
395
+ return err ;
396
+ }
397
+ }
398
+
399
+ /* Simulate hack for mbox framework */
400
+ tasklet_schedule (& cp -> txdb_tasklet );
401
+
402
+ break ;
403
+ default :
404
+ dev_warn_ratelimited (priv -> dev ,
405
+ "Send data on wrong channel type: %d\n" ,
406
+ cp -> type );
407
+ return - EINVAL ;
408
+ }
409
+
410
+ return 0 ;
411
+ }
412
+
413
+ static int imx_mu_seco_rxdb (struct imx_mu_priv * priv , struct imx_mu_con_priv * cp )
414
+ {
415
+ struct imx_sc_rpc_msg_max msg ;
416
+ u32 * data = (u32 * )& msg ;
417
+ u32 byte_size ;
418
+ int err = 0 ;
419
+ int i ;
420
+
421
+ dev_dbg (priv -> dev , "Receiving message\n" );
422
+
423
+ /* Read header */
424
+ dev_dbg (priv -> dev , "Receiving header\n" );
425
+ * data ++ = imx_mu_read (priv , priv -> dcfg -> xRR );
426
+ byte_size = msg .hdr .size * sizeof (u32 );
427
+ if (byte_size > sizeof (msg )) {
428
+ dev_err (priv -> dev , "Exceed max msg size (%zu) on RX, got: %i\n" ,
429
+ sizeof (msg ), byte_size );
430
+ err = - EINVAL ;
431
+ goto error ;
432
+ }
433
+
434
+ /* Read message waiting they are written */
435
+ for (i = 1 ; i < msg .hdr .size ; i ++ ) {
436
+ dev_dbg (priv -> dev , "Receiving word %d\n" , i );
437
+ err = imx_mu_rx_waiting_read (priv , data ++ , i );
438
+ if (err ) {
439
+ dev_err (priv -> dev , "Timeout rx %d\n" , i );
440
+ goto error ;
441
+ }
442
+ }
443
+
444
+ /* Clear GIP */
445
+ imx_mu_write (priv , IMX_MU_xSR_GIPn (priv -> dcfg -> type , cp -> idx ),
446
+ priv -> dcfg -> xSR [IMX_MU_GSR ]);
447
+
448
+ print_hex_dump_debug ("to client " , DUMP_PREFIX_OFFSET , 4 , 4 ,
449
+ & msg , byte_size , false);
450
+
451
+ /* send data to client */
452
+ dev_dbg (priv -> dev , "Sending message to client\n" );
453
+ mbox_chan_received_data (cp -> chan , (void * )& msg );
454
+
455
+ goto exit ;
456
+
457
+ error :
458
+ mbox_chan_received_data (cp -> chan , ERR_PTR (err ));
459
+
460
+ exit :
461
+ return err ;
462
+ }
463
+
292
464
static void imx_mu_txdb_tasklet (unsigned long data )
293
465
{
294
466
struct imx_mu_con_priv * cp = (struct imx_mu_con_priv * )data ;
@@ -494,6 +666,27 @@ static struct mbox_chan * imx_mu_xlate(struct mbox_controller *mbox,
494
666
return & mbox -> chans [chan ];
495
667
}
496
668
669
+ static struct mbox_chan * imx_mu_seco_xlate (struct mbox_controller * mbox ,
670
+ const struct of_phandle_args * sp )
671
+ {
672
+ u32 type ;
673
+
674
+ if (sp -> args_count < 1 ) {
675
+ dev_err (mbox -> dev , "Invalid argument count %d\n" , sp -> args_count );
676
+ return ERR_PTR (- EINVAL );
677
+ }
678
+
679
+ type = sp -> args [0 ]; /* channel type */
680
+
681
+ /* Only supports TXDB and RXDB */
682
+ if (type == IMX_MU_TYPE_TX || type == IMX_MU_TYPE_RX ) {
683
+ dev_err (mbox -> dev , "Invalid type: %d\n" , type );
684
+ return ERR_PTR (- EINVAL );
685
+ }
686
+
687
+ return imx_mu_xlate (mbox , sp );
688
+ }
689
+
497
690
static void imx_mu_init_generic (struct imx_mu_priv * priv )
498
691
{
499
692
unsigned int i ;
@@ -544,6 +737,12 @@ static void imx_mu_init_specific(struct imx_mu_priv *priv)
544
737
imx_mu_write (priv , 0 , priv -> dcfg -> xCR [i ]);
545
738
}
546
739
740
+ static void imx_mu_init_seco (struct imx_mu_priv * priv )
741
+ {
742
+ imx_mu_init_generic (priv );
743
+ priv -> mbox .of_xlate = imx_mu_seco_xlate ;
744
+ }
745
+
547
746
static int imx_mu_probe (struct platform_device * pdev )
548
747
{
549
748
struct device * dev = & pdev -> dev ;
@@ -702,12 +901,24 @@ static const struct imx_mu_dcfg imx_mu_cfg_imx8_scu = {
702
901
.xCR = {0x24 , 0x24 , 0x24 , 0x24 },
703
902
};
704
903
904
+ static const struct imx_mu_dcfg imx_mu_cfg_imx8_seco = {
905
+ .tx = imx_mu_seco_tx ,
906
+ .rx = imx_mu_generic_rx ,
907
+ .rxdb = imx_mu_seco_rxdb ,
908
+ .init = imx_mu_init_seco ,
909
+ .xTR = 0x0 ,
910
+ .xRR = 0x10 ,
911
+ .xSR = {0x20 , 0x20 , 0x20 , 0x20 },
912
+ .xCR = {0x24 , 0x24 , 0x24 , 0x24 },
913
+ };
914
+
705
915
static const struct of_device_id imx_mu_dt_ids [] = {
706
916
{ .compatible = "fsl,imx7ulp-mu" , .data = & imx_mu_cfg_imx7ulp },
707
917
{ .compatible = "fsl,imx6sx-mu" , .data = & imx_mu_cfg_imx6sx },
708
918
{ .compatible = "fsl,imx8ulp-mu" , .data = & imx_mu_cfg_imx8ulp },
709
919
{ .compatible = "fsl,imx8ulp-mu-s4" , .data = & imx_mu_cfg_imx8ulp_s4 },
710
920
{ .compatible = "fsl,imx8-mu-scu" , .data = & imx_mu_cfg_imx8_scu },
921
+ { .compatible = "fsl,imx8-mu-seco" , .data = & imx_mu_cfg_imx8_seco },
711
922
{ },
712
923
};
713
924
MODULE_DEVICE_TABLE (of , imx_mu_dt_ids );
0 commit comments