Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) ============================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) The Common Mailbox Framework
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) ============================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) :Author: Jassi Brar <jaswinder.singh@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) This document aims to help developers write client and controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) drivers for the API. But before we start, let us note that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) client (especially) and controller drivers are likely going to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) very platform specific because the remote firmware is likely to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) proprietary and implement non-standard protocol. So even if two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) platforms employ, say, PL320 controller, the client drivers can't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) be shared across them. Even the PL320 driver might need to accommodate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) some platform specific quirks. So the API is meant mainly to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) similar copies of code written for each platform. Having said that,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) nothing prevents the remote f/w to also be Linux based and use the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) same api there. However none of that helps us locally because we only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) ever deal at client's protocol level.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) Some of the choices made during implementation are the result of this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) peculiarity of this "common" framework.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) Controller Driver (See include/linux/mailbox_controller.h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) ==========================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) Allocate mbox_controller and the array of mbox_chan.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) Populate mbox_chan_ops, except peek_data() all are mandatory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) The controller driver might know a message has been consumed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) by the remote by getting an IRQ or polling some hardware flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) or it can never know (the client knows by way of the protocol).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) The method in order of preference is IRQ -> Poll -> None, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) the controller driver should set via 'txdone_irq' or 'txdone_poll'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) or neither.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) Client Driver (See include/linux/mailbox_client.h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) ==================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) The client might want to operate in blocking mode (synchronously
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) send a message through before returning) or non-blocking/async mode (submit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) a message and a callback function to the API and return immediately).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) ::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	struct demo_client {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		struct mbox_client cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		struct mbox_chan *mbox;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		struct completion c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		bool async;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 		/* ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	* This is the handler for data received from remote. The behaviour is purely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	* dependent upon the protocol. This is just an example.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	static void message_from_remote(struct mbox_client *cl, void *mssg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		struct demo_client *dc = container_of(cl, struct demo_client, cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		if (dc->async) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 			if (is_an_ack(mssg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 				/* An ACK to our last sample sent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 				return; /* Or do something else here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 			} else { /* A new message from remote */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 				queue_req(mssg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 			/* Remote f/w sends only ACK packets on this channel */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	static void sample_sent(struct mbox_client *cl, void *mssg, int r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		struct demo_client *dc = container_of(cl, struct demo_client, cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		complete(&dc->c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	static void client_demo(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 		struct demo_client *dc_sync, *dc_async;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		/* The controller already knows async_pkt and sync_pkt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		struct async_pkt ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		struct sync_pkt sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		/* Populate non-blocking mode client */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		dc_async->cl.dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		dc_async->cl.rx_callback = message_from_remote;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		dc_async->cl.tx_done = sample_sent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		dc_async->cl.tx_block = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 		dc_async->cl.tx_tout = 0; /* doesn't matter here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		dc_async->cl.knows_txdone = false; /* depending upon protocol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		dc_async->async = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		init_completion(&dc_async->c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		/* Populate blocking mode client */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 		dc_sync->cl.dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		dc_sync->cl.rx_callback = message_from_remote;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		dc_sync->cl.tx_done = NULL; /* operate in blocking mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		dc_sync->cl.tx_block = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		dc_sync->cl.tx_tout = 500; /* by half a second */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		dc_sync->cl.knows_txdone = false; /* depending upon protocol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		dc_sync->async = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		/* ASync mailbox is listed second in 'mboxes' property */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		dc_async->mbox = mbox_request_channel(&dc_async->cl, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		/* Populate data packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		/* ap.xxx = 123; etc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		/* Send async message to remote */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		mbox_send_message(dc_async->mbox, &ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		/* Sync mailbox is listed first in 'mboxes' property */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 		/* Populate data packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		/* sp.abc = 123; etc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		/* Send message to remote in blocking mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		mbox_send_message(dc_sync->mbox, &sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		/* At this point 'sp' has been sent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		/* Now wait for async chan to be done */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		wait_for_completion(&dc_async->c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	}