99#include <linux/interrupt.h>
1010#include <linux/io.h>
1111#include <linux/iopoll.h>
12+ #include <linux/jiffies.h>
1213#include <linux/kernel.h>
1314#include <linux/mailbox_controller.h>
1415#include <linux/module.h>
2425#define IMX_MU_S4_CHANS 2
2526#define IMX_MU_CHAN_NAME_SIZE 20
2627
28+ #define IMX_MU_SECO_TX_TOUT (msecs_to_jiffies(3000))
29+ #define IMX_MU_SECO_RX_TOUT (msecs_to_jiffies(3000))
30+
2731enum imx_mu_chan_type {
2832 IMX_MU_TYPE_TX , /* Tx */
2933 IMX_MU_TYPE_RX , /* Rx */
@@ -48,7 +52,7 @@ enum imx_mu_xsr {
4852
4953struct imx_sc_rpc_msg_max {
5054 struct imx_sc_rpc_msg hdr ;
51- u32 data [7 ];
55+ u32 data [30 ];
5256};
5357
5458struct imx_s4_rpc_msg_max {
@@ -131,6 +135,55 @@ static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
131135 return ioread32 (priv -> base + offs );
132136}
133137
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+
134187static u32 imx_mu_xcr_rmw (struct imx_mu_priv * priv , enum imx_mu_xcr type , u32 set , u32 clr )
135188{
136189 unsigned long flags ;
@@ -289,6 +342,125 @@ static int imx_mu_specific_rx(struct imx_mu_priv *priv, struct imx_mu_con_priv *
289342 return 0 ;
290343}
291344
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+
292464static void imx_mu_txdb_tasklet (unsigned long data )
293465{
294466 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,
494666 return & mbox -> chans [chan ];
495667}
496668
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+
497690static void imx_mu_init_generic (struct imx_mu_priv * priv )
498691{
499692 unsigned int i ;
@@ -544,6 +737,12 @@ static void imx_mu_init_specific(struct imx_mu_priv *priv)
544737 imx_mu_write (priv , 0 , priv -> dcfg -> xCR [i ]);
545738}
546739
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+
547746static int imx_mu_probe (struct platform_device * pdev )
548747{
549748 struct device * dev = & pdev -> dev ;
@@ -702,12 +901,24 @@ static const struct imx_mu_dcfg imx_mu_cfg_imx8_scu = {
702901 .xCR = {0x24 , 0x24 , 0x24 , 0x24 },
703902};
704903
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+
705915static const struct of_device_id imx_mu_dt_ids [] = {
706916 { .compatible = "fsl,imx7ulp-mu" , .data = & imx_mu_cfg_imx7ulp },
707917 { .compatible = "fsl,imx6sx-mu" , .data = & imx_mu_cfg_imx6sx },
708918 { .compatible = "fsl,imx8ulp-mu" , .data = & imx_mu_cfg_imx8ulp },
709919 { .compatible = "fsl,imx8ulp-mu-s4" , .data = & imx_mu_cfg_imx8ulp_s4 },
710920 { .compatible = "fsl,imx8-mu-scu" , .data = & imx_mu_cfg_imx8_scu },
921+ { .compatible = "fsl,imx8-mu-seco" , .data = & imx_mu_cfg_imx8_seco },
711922 { },
712923};
713924MODULE_DEVICE_TABLE (of , imx_mu_dt_ids );
0 commit comments