xref: /dpdk/drivers/common/cnxk/roc_mbox.c (revision 9bd368ca311a1ede6c17bb9e39d0e30f6a9abb2d)
103cc9bd9SJerin Jacob /* SPDX-License-Identifier: BSD-3-Clause
203cc9bd9SJerin Jacob  * Copyright(C) 2021 Marvell.
303cc9bd9SJerin Jacob  */
403cc9bd9SJerin Jacob 
503cc9bd9SJerin Jacob #include <errno.h>
603cc9bd9SJerin Jacob #include <stdio.h>
703cc9bd9SJerin Jacob #include <stdlib.h>
803cc9bd9SJerin Jacob #include <string.h>
903cc9bd9SJerin Jacob 
1003cc9bd9SJerin Jacob #include "roc_api.h"
1103cc9bd9SJerin Jacob #include "roc_priv.h"
1203cc9bd9SJerin Jacob 
1303cc9bd9SJerin Jacob /* RCLK, SCLK in MHz */
1403cc9bd9SJerin Jacob uint16_t dev_rclk_freq;
1503cc9bd9SJerin Jacob uint16_t dev_sclk_freq;
1603cc9bd9SJerin Jacob 
1703cc9bd9SJerin Jacob static inline uint16_t
1803cc9bd9SJerin Jacob msgs_offset(void)
1903cc9bd9SJerin Jacob {
2003cc9bd9SJerin Jacob 	return PLT_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
2103cc9bd9SJerin Jacob }
2203cc9bd9SJerin Jacob 
2303cc9bd9SJerin Jacob void
2403cc9bd9SJerin Jacob mbox_fini(struct mbox *mbox)
2503cc9bd9SJerin Jacob {
2603cc9bd9SJerin Jacob 	mbox->reg_base = 0;
2703cc9bd9SJerin Jacob 	mbox->hwbase = 0;
2803cc9bd9SJerin Jacob 	plt_free(mbox->dev);
2903cc9bd9SJerin Jacob 	mbox->dev = NULL;
3003cc9bd9SJerin Jacob }
3103cc9bd9SJerin Jacob 
3203cc9bd9SJerin Jacob void
3303cc9bd9SJerin Jacob mbox_reset(struct mbox *mbox, int devid)
3403cc9bd9SJerin Jacob {
3503cc9bd9SJerin Jacob 	struct mbox_dev *mdev = &mbox->dev[devid];
3603cc9bd9SJerin Jacob 	struct mbox_hdr *tx_hdr =
3703cc9bd9SJerin Jacob 		(struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->tx_start);
3803cc9bd9SJerin Jacob 	struct mbox_hdr *rx_hdr =
3903cc9bd9SJerin Jacob 		(struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
4003cc9bd9SJerin Jacob 
4103cc9bd9SJerin Jacob 	mdev->msg_size = 0;
4203cc9bd9SJerin Jacob 	mdev->rsp_size = 0;
4303cc9bd9SJerin Jacob 	tx_hdr->msg_size = 0;
4403cc9bd9SJerin Jacob 	tx_hdr->num_msgs = 0;
4503cc9bd9SJerin Jacob 	rx_hdr->msg_size = 0;
4603cc9bd9SJerin Jacob 	rx_hdr->num_msgs = 0;
4703cc9bd9SJerin Jacob }
4803cc9bd9SJerin Jacob 
4961deac72SHarman Kalra static int
5061deac72SHarman Kalra cn20k_mbox_setup(struct mbox *mbox, int direction)
5103cc9bd9SJerin Jacob {
5261deac72SHarman Kalra 	switch (direction) {
5361deac72SHarman Kalra 	case MBOX_DIR_AFPF:
5461deac72SHarman Kalra 		mbox->trigger = RVU_MBOX_AF_AFPFX_TRIGX(1);
5561deac72SHarman Kalra 		mbox->tr_shift = 4;
5661deac72SHarman Kalra 		break;
5761deac72SHarman Kalra 	case MBOX_DIR_AFPF_UP:
5861deac72SHarman Kalra 		mbox->trigger = RVU_MBOX_AF_AFPFX_TRIGX(0);
5961deac72SHarman Kalra 		mbox->tr_shift = 4;
6061deac72SHarman Kalra 		break;
6161deac72SHarman Kalra 	case MBOX_DIR_PFAF:
6261deac72SHarman Kalra 		mbox->trigger = RVU_MBOX_PF_PFAF_TRIGX(0);
6361deac72SHarman Kalra 		mbox->tr_shift = 0;
6461deac72SHarman Kalra 		break;
6561deac72SHarman Kalra 	case MBOX_DIR_PFAF_UP:
6661deac72SHarman Kalra 		mbox->trigger = RVU_MBOX_PF_PFAF_TRIGX(1);
6761deac72SHarman Kalra 		mbox->tr_shift = 0;
6861deac72SHarman Kalra 		break;
69*9bd368caSHarman Kalra 	case MBOX_DIR_PFVF:
70*9bd368caSHarman Kalra 		mbox->trigger = RVU_MBOX_PF_VFX_PFVF_TRIGX(1);
71*9bd368caSHarman Kalra 		mbox->tr_shift = 4;
72*9bd368caSHarman Kalra 		break;
73*9bd368caSHarman Kalra 	case MBOX_DIR_PFVF_UP:
74*9bd368caSHarman Kalra 		mbox->trigger = RVU_MBOX_PF_VFX_PFVF_TRIGX(0);
75*9bd368caSHarman Kalra 		mbox->tr_shift = 4;
76*9bd368caSHarman Kalra 		break;
77*9bd368caSHarman Kalra 	case MBOX_DIR_VFPF:
78*9bd368caSHarman Kalra 		mbox->trigger = RVU_MBOX_VF_VFPF_TRIGX(0);
79*9bd368caSHarman Kalra 		mbox->tr_shift = 0;
80*9bd368caSHarman Kalra 		break;
81*9bd368caSHarman Kalra 	case MBOX_DIR_VFPF_UP:
82*9bd368caSHarman Kalra 		mbox->trigger = RVU_MBOX_VF_VFPF_TRIGX(1);
83*9bd368caSHarman Kalra 		mbox->tr_shift = 0;
84*9bd368caSHarman Kalra 		break;
8561deac72SHarman Kalra 	default:
8661deac72SHarman Kalra 		return -ENODEV;
8761deac72SHarman Kalra 	}
8803cc9bd9SJerin Jacob 
8961deac72SHarman Kalra 	return 0;
9061deac72SHarman Kalra }
9103cc9bd9SJerin Jacob 
9261deac72SHarman Kalra static int
9361deac72SHarman Kalra mbox_setup(struct mbox *mbox, uintptr_t reg_base, int direction, int ndevs, uint64_t intr_offset)
9461deac72SHarman Kalra {
9503cc9bd9SJerin Jacob 	switch (direction) {
9603cc9bd9SJerin Jacob 	case MBOX_DIR_AFPF:
9703cc9bd9SJerin Jacob 	case MBOX_DIR_PFVF:
9803cc9bd9SJerin Jacob 		mbox->tx_start = MBOX_DOWN_TX_START;
9903cc9bd9SJerin Jacob 		mbox->rx_start = MBOX_DOWN_RX_START;
10003cc9bd9SJerin Jacob 		mbox->tx_size = MBOX_DOWN_TX_SIZE;
10103cc9bd9SJerin Jacob 		mbox->rx_size = MBOX_DOWN_RX_SIZE;
10203cc9bd9SJerin Jacob 		break;
10303cc9bd9SJerin Jacob 	case MBOX_DIR_PFAF:
10403cc9bd9SJerin Jacob 	case MBOX_DIR_VFPF:
10503cc9bd9SJerin Jacob 		mbox->tx_start = MBOX_DOWN_RX_START;
10603cc9bd9SJerin Jacob 		mbox->rx_start = MBOX_DOWN_TX_START;
10703cc9bd9SJerin Jacob 		mbox->tx_size = MBOX_DOWN_RX_SIZE;
10803cc9bd9SJerin Jacob 		mbox->rx_size = MBOX_DOWN_TX_SIZE;
10903cc9bd9SJerin Jacob 		break;
11003cc9bd9SJerin Jacob 	case MBOX_DIR_AFPF_UP:
11103cc9bd9SJerin Jacob 	case MBOX_DIR_PFVF_UP:
11203cc9bd9SJerin Jacob 		mbox->tx_start = MBOX_UP_TX_START;
11303cc9bd9SJerin Jacob 		mbox->rx_start = MBOX_UP_RX_START;
11403cc9bd9SJerin Jacob 		mbox->tx_size = MBOX_UP_TX_SIZE;
11503cc9bd9SJerin Jacob 		mbox->rx_size = MBOX_UP_RX_SIZE;
11603cc9bd9SJerin Jacob 		break;
11703cc9bd9SJerin Jacob 	case MBOX_DIR_PFAF_UP:
11803cc9bd9SJerin Jacob 	case MBOX_DIR_VFPF_UP:
11903cc9bd9SJerin Jacob 		mbox->tx_start = MBOX_UP_RX_START;
12003cc9bd9SJerin Jacob 		mbox->rx_start = MBOX_UP_TX_START;
12103cc9bd9SJerin Jacob 		mbox->tx_size = MBOX_UP_RX_SIZE;
12203cc9bd9SJerin Jacob 		mbox->rx_size = MBOX_UP_TX_SIZE;
12303cc9bd9SJerin Jacob 		break;
12403cc9bd9SJerin Jacob 	default:
12503cc9bd9SJerin Jacob 		return -ENODEV;
12603cc9bd9SJerin Jacob 	}
12703cc9bd9SJerin Jacob 
12861deac72SHarman Kalra 	mbox->intr_offset = intr_offset;
12961deac72SHarman Kalra 	mbox->dev = plt_zmalloc(ndevs * sizeof(struct mbox_dev), ROC_ALIGN);
13061deac72SHarman Kalra 	if (!mbox->dev) {
13161deac72SHarman Kalra 		mbox_fini(mbox);
13261deac72SHarman Kalra 		return -ENOMEM;
13361deac72SHarman Kalra 	}
13461deac72SHarman Kalra 	mbox->ndevs = ndevs;
13561deac72SHarman Kalra 
13661deac72SHarman Kalra 	mbox->reg_base = reg_base;
13761deac72SHarman Kalra 	if (roc_model_is_cn20k())
13861deac72SHarman Kalra 		return cn20k_mbox_setup(mbox, direction);
13961deac72SHarman Kalra 
14003cc9bd9SJerin Jacob 	switch (direction) {
14103cc9bd9SJerin Jacob 	case MBOX_DIR_AFPF:
14203cc9bd9SJerin Jacob 	case MBOX_DIR_AFPF_UP:
14303cc9bd9SJerin Jacob 		mbox->trigger = RVU_AF_AFPF_MBOX0;
14403cc9bd9SJerin Jacob 		mbox->tr_shift = 4;
14503cc9bd9SJerin Jacob 		break;
14603cc9bd9SJerin Jacob 	case MBOX_DIR_PFAF:
14703cc9bd9SJerin Jacob 	case MBOX_DIR_PFAF_UP:
14803cc9bd9SJerin Jacob 		mbox->trigger = RVU_PF_PFAF_MBOX1;
14903cc9bd9SJerin Jacob 		mbox->tr_shift = 0;
15003cc9bd9SJerin Jacob 		break;
15103cc9bd9SJerin Jacob 	case MBOX_DIR_PFVF:
15203cc9bd9SJerin Jacob 	case MBOX_DIR_PFVF_UP:
15303cc9bd9SJerin Jacob 		mbox->trigger = RVU_PF_VFX_PFVF_MBOX0;
15403cc9bd9SJerin Jacob 		mbox->tr_shift = 12;
15503cc9bd9SJerin Jacob 		break;
15603cc9bd9SJerin Jacob 	case MBOX_DIR_VFPF:
15703cc9bd9SJerin Jacob 	case MBOX_DIR_VFPF_UP:
15803cc9bd9SJerin Jacob 		mbox->trigger = RVU_VF_VFPF_MBOX1;
15903cc9bd9SJerin Jacob 		mbox->tr_shift = 0;
16003cc9bd9SJerin Jacob 		break;
16103cc9bd9SJerin Jacob 	default:
16203cc9bd9SJerin Jacob 		return -ENODEV;
16303cc9bd9SJerin Jacob 	}
16403cc9bd9SJerin Jacob 
16561deac72SHarman Kalra 	return 0;
16603cc9bd9SJerin Jacob }
16761deac72SHarman Kalra 
16861deac72SHarman Kalra int
16961deac72SHarman Kalra mbox_init(struct mbox *mbox, uintptr_t hwbase, uintptr_t reg_base, int direction, int ndevs,
17061deac72SHarman Kalra 	  uint64_t intr_offset)
17161deac72SHarman Kalra {
17261deac72SHarman Kalra 	struct mbox_dev *mdev;
17361deac72SHarman Kalra 	char *var, *var_to;
17461deac72SHarman Kalra 	int devid, rc;
17561deac72SHarman Kalra 
17661deac72SHarman Kalra 	rc = mbox_setup(mbox, reg_base, direction, ndevs, intr_offset);
17761deac72SHarman Kalra 	if (rc) {
17861deac72SHarman Kalra 		plt_err("Failed to setup the mailbox");
17961deac72SHarman Kalra 		return rc;
18061deac72SHarman Kalra 	}
18161deac72SHarman Kalra 
18261deac72SHarman Kalra 	mbox->hwbase = hwbase;
18303cc9bd9SJerin Jacob 	for (devid = 0; devid < ndevs; devid++) {
18403cc9bd9SJerin Jacob 		mdev = &mbox->dev[devid];
18503cc9bd9SJerin Jacob 		mdev->mbase = (void *)(mbox->hwbase + (devid * MBOX_SIZE));
18603cc9bd9SJerin Jacob 		plt_spinlock_init(&mdev->mbox_lock);
18703cc9bd9SJerin Jacob 		/* Init header to reset value */
18803cc9bd9SJerin Jacob 		mbox_reset(mbox, devid);
18903cc9bd9SJerin Jacob 	}
19003cc9bd9SJerin Jacob 
19103cc9bd9SJerin Jacob 	var = getenv("ROC_CN10K_MBOX_TIMEOUT");
19203cc9bd9SJerin Jacob 	var_to = getenv("ROC_MBOX_TIMEOUT");
19303cc9bd9SJerin Jacob 
19403cc9bd9SJerin Jacob 	if (var)
19503cc9bd9SJerin Jacob 		mbox->rsp_tmo = atoi(var);
19603cc9bd9SJerin Jacob 	else if (var_to)
19703cc9bd9SJerin Jacob 		mbox->rsp_tmo = atoi(var_to);
19803cc9bd9SJerin Jacob 	else
19903cc9bd9SJerin Jacob 		mbox->rsp_tmo = MBOX_RSP_TIMEOUT;
20003cc9bd9SJerin Jacob 
20103cc9bd9SJerin Jacob 	return 0;
20203cc9bd9SJerin Jacob }
20303cc9bd9SJerin Jacob 
20403cc9bd9SJerin Jacob /**
20503cc9bd9SJerin Jacob  * @internal
20603cc9bd9SJerin Jacob  * Allocate a message response
20703cc9bd9SJerin Jacob  */
20803cc9bd9SJerin Jacob struct mbox_msghdr *
20903cc9bd9SJerin Jacob mbox_alloc_msg_rsp(struct mbox *mbox, int devid, int size, int size_rsp)
21003cc9bd9SJerin Jacob {
21103cc9bd9SJerin Jacob 	struct mbox_dev *mdev = &mbox->dev[devid];
21203cc9bd9SJerin Jacob 	struct mbox_msghdr *msghdr = NULL;
21303cc9bd9SJerin Jacob 
21403cc9bd9SJerin Jacob 	size = PLT_ALIGN(size, MBOX_MSG_ALIGN);
21503cc9bd9SJerin Jacob 	size_rsp = PLT_ALIGN(size_rsp, MBOX_MSG_ALIGN);
21603cc9bd9SJerin Jacob 	/* Check if there is space in mailbox */
21703cc9bd9SJerin Jacob 	if ((mdev->msg_size + size) > mbox->tx_size - msgs_offset())
21803cc9bd9SJerin Jacob 		goto exit;
21903cc9bd9SJerin Jacob 	if ((mdev->rsp_size + size_rsp) > mbox->rx_size - msgs_offset())
22003cc9bd9SJerin Jacob 		goto exit;
22103cc9bd9SJerin Jacob 	if (mdev->msg_size == 0)
22203cc9bd9SJerin Jacob 		mdev->num_msgs = 0;
22303cc9bd9SJerin Jacob 	mdev->num_msgs++;
22403cc9bd9SJerin Jacob 
22503cc9bd9SJerin Jacob 	msghdr = (struct mbox_msghdr *)(((uintptr_t)mdev->mbase +
22603cc9bd9SJerin Jacob 					 mbox->tx_start + msgs_offset() +
22703cc9bd9SJerin Jacob 					 mdev->msg_size));
22803cc9bd9SJerin Jacob 
22903cc9bd9SJerin Jacob 	/* Clear the whole msg region */
23003cc9bd9SJerin Jacob 	mbox_memset(msghdr, 0, sizeof(*msghdr) + size);
23103cc9bd9SJerin Jacob 	/* Init message header with reset values */
23203cc9bd9SJerin Jacob 	msghdr->ver = MBOX_VERSION;
23303cc9bd9SJerin Jacob 	mdev->msg_size += size;
23403cc9bd9SJerin Jacob 	mdev->rsp_size += size_rsp;
23503cc9bd9SJerin Jacob 	msghdr->next_msgoff = mdev->msg_size + msgs_offset();
23603cc9bd9SJerin Jacob exit:
23703cc9bd9SJerin Jacob 
23803cc9bd9SJerin Jacob 	return msghdr;
23903cc9bd9SJerin Jacob }
24003cc9bd9SJerin Jacob 
24103cc9bd9SJerin Jacob /**
24203cc9bd9SJerin Jacob  * @internal
243fa4ee2d4SHarman Kalra  * Synchronization between UP and DOWN messages
24403cc9bd9SJerin Jacob  */
245fa4ee2d4SHarman Kalra bool
246fa4ee2d4SHarman Kalra mbox_wait_for_zero(struct mbox *mbox, int devid)
247fa4ee2d4SHarman Kalra {
248fa4ee2d4SHarman Kalra 	uint64_t data;
249fa4ee2d4SHarman Kalra 
250fa4ee2d4SHarman Kalra 	data = plt_read64((volatile void *)(mbox->reg_base +
251fa4ee2d4SHarman Kalra 				(mbox->trigger | (devid << mbox->tr_shift))));
252fa4ee2d4SHarman Kalra 
253fa4ee2d4SHarman Kalra 	/* If data is non-zero wait for ~1ms and return to caller
254fa4ee2d4SHarman Kalra 	 * whether data has changed to zero or not after the wait.
255fa4ee2d4SHarman Kalra 	 */
256fa4ee2d4SHarman Kalra 	if (data)
257fa4ee2d4SHarman Kalra 		usleep(1000);
258fa4ee2d4SHarman Kalra 	else
259fa4ee2d4SHarman Kalra 		return true;
260fa4ee2d4SHarman Kalra 
261fa4ee2d4SHarman Kalra 	data = plt_read64((volatile void *)(mbox->reg_base +
262fa4ee2d4SHarman Kalra 				(mbox->trigger | (devid << mbox->tr_shift))));
263fa4ee2d4SHarman Kalra 	return data == 0;
264fa4ee2d4SHarman Kalra }
265fa4ee2d4SHarman Kalra 
266fa4ee2d4SHarman Kalra static void
267fa4ee2d4SHarman Kalra mbox_msg_send_data(struct mbox *mbox, int devid, uint8_t data)
26803cc9bd9SJerin Jacob {
26903cc9bd9SJerin Jacob 	struct mbox_dev *mdev = &mbox->dev[devid];
2705d8ff275SHarman Kalra 	struct mbox_hdr *tx_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->tx_start);
2715d8ff275SHarman Kalra 	struct mbox_hdr *rx_hdr = (struct mbox_hdr *)((uintptr_t)mdev->mbase + mbox->rx_start);
2725d8ff275SHarman Kalra 	uint64_t intr_val;
27303cc9bd9SJerin Jacob 
27403cc9bd9SJerin Jacob 	/* Reset header for next messages */
27503cc9bd9SJerin Jacob 	tx_hdr->msg_size = mdev->msg_size;
27603cc9bd9SJerin Jacob 	mdev->msg_size = 0;
27703cc9bd9SJerin Jacob 	mdev->rsp_size = 0;
27803cc9bd9SJerin Jacob 	mdev->msgs_acked = 0;
27903cc9bd9SJerin Jacob 
28003cc9bd9SJerin Jacob 	/* num_msgs != 0 signals to the peer that the buffer has a number of
28103cc9bd9SJerin Jacob 	 * messages. So this should be written after copying txmem
28203cc9bd9SJerin Jacob 	 */
28303cc9bd9SJerin Jacob 	tx_hdr->num_msgs = mdev->num_msgs;
28403cc9bd9SJerin Jacob 	rx_hdr->num_msgs = 0;
28503cc9bd9SJerin Jacob 
28603cc9bd9SJerin Jacob 	/* Sync mbox data into memory */
28703cc9bd9SJerin Jacob 	plt_wmb();
28803cc9bd9SJerin Jacob 
2895d8ff275SHarman Kalra 	/* Check for any pending interrupt */
2905d8ff275SHarman Kalra 	intr_val = plt_read64(
2915d8ff275SHarman Kalra 		(volatile void *)(mbox->reg_base + (mbox->trigger | (devid << mbox->tr_shift))));
2925d8ff275SHarman Kalra 
2935d8ff275SHarman Kalra 	intr_val |= (uint64_t)data;
29403cc9bd9SJerin Jacob 	/* The interrupt should be fired after num_msgs is written
29503cc9bd9SJerin Jacob 	 * to the shared memory
29603cc9bd9SJerin Jacob 	 */
2975d8ff275SHarman Kalra 	plt_write64(intr_val, (volatile void *)(mbox->reg_base +
298fa4ee2d4SHarman Kalra 						(mbox->trigger | (devid << mbox->tr_shift))));
299fa4ee2d4SHarman Kalra }
300fa4ee2d4SHarman Kalra 
301fa4ee2d4SHarman Kalra /**
302fa4ee2d4SHarman Kalra  * @internal
303fa4ee2d4SHarman Kalra  * Send a mailbox message
304fa4ee2d4SHarman Kalra  */
305fa4ee2d4SHarman Kalra void
306fa4ee2d4SHarman Kalra mbox_msg_send(struct mbox *mbox, int devid)
307fa4ee2d4SHarman Kalra {
308fa4ee2d4SHarman Kalra 	mbox_msg_send_data(mbox, devid, MBOX_DOWN_MSG);
309fa4ee2d4SHarman Kalra }
310fa4ee2d4SHarman Kalra 
311fa4ee2d4SHarman Kalra /**
312fa4ee2d4SHarman Kalra  * @internal
313fa4ee2d4SHarman Kalra  * Send an UP mailbox message
314fa4ee2d4SHarman Kalra  */
315fa4ee2d4SHarman Kalra void
316fa4ee2d4SHarman Kalra mbox_msg_send_up(struct mbox *mbox, int devid)
317fa4ee2d4SHarman Kalra {
318fa4ee2d4SHarman Kalra 	mbox_msg_send_data(mbox, devid, MBOX_UP_MSG);
31903cc9bd9SJerin Jacob }
32003cc9bd9SJerin Jacob 
32103cc9bd9SJerin Jacob /**
32203cc9bd9SJerin Jacob  * @internal
32303cc9bd9SJerin Jacob  * Wait and get mailbox response
32403cc9bd9SJerin Jacob  */
32503cc9bd9SJerin Jacob int
32603cc9bd9SJerin Jacob mbox_get_rsp(struct mbox *mbox, int devid, void **msg)
32703cc9bd9SJerin Jacob {
32803cc9bd9SJerin Jacob 	struct mbox_dev *mdev = &mbox->dev[devid];
32903cc9bd9SJerin Jacob 	struct mbox_msghdr *msghdr;
33003cc9bd9SJerin Jacob 	uint64_t offset;
33103cc9bd9SJerin Jacob 	int rc;
33203cc9bd9SJerin Jacob 
33303cc9bd9SJerin Jacob 	rc = mbox_wait_for_rsp(mbox, devid);
33403cc9bd9SJerin Jacob 	if (rc < 0)
33503cc9bd9SJerin Jacob 		return -EIO;
33603cc9bd9SJerin Jacob 
33703cc9bd9SJerin Jacob 	plt_rmb();
33803cc9bd9SJerin Jacob 
33903cc9bd9SJerin Jacob 	offset = mbox->rx_start +
34003cc9bd9SJerin Jacob 		 PLT_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
34103cc9bd9SJerin Jacob 	msghdr = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);
34203cc9bd9SJerin Jacob 	if (msg != NULL)
34303cc9bd9SJerin Jacob 		*msg = msghdr;
34403cc9bd9SJerin Jacob 
34503cc9bd9SJerin Jacob 	return msghdr->rc;
34603cc9bd9SJerin Jacob }
34703cc9bd9SJerin Jacob 
34803cc9bd9SJerin Jacob /**
34903cc9bd9SJerin Jacob  * Polling for given wait time to get mailbox response
35003cc9bd9SJerin Jacob  */
35103cc9bd9SJerin Jacob static int
35203cc9bd9SJerin Jacob mbox_poll(struct mbox *mbox, uint32_t wait)
35303cc9bd9SJerin Jacob {
35403cc9bd9SJerin Jacob 	uint32_t timeout = 0, sleep = 1;
35503cc9bd9SJerin Jacob 	uint32_t wait_us = wait * 1000;
35603cc9bd9SJerin Jacob 	uint64_t rsp_reg = 0;
35703cc9bd9SJerin Jacob 	uintptr_t reg_addr;
35803cc9bd9SJerin Jacob 
35903cc9bd9SJerin Jacob 	reg_addr = mbox->reg_base + mbox->intr_offset;
36003cc9bd9SJerin Jacob 	do {
36103cc9bd9SJerin Jacob 		rsp_reg = plt_read64(reg_addr);
36203cc9bd9SJerin Jacob 
36303cc9bd9SJerin Jacob 		if (timeout >= wait_us)
36403cc9bd9SJerin Jacob 			return -ETIMEDOUT;
36503cc9bd9SJerin Jacob 
36603cc9bd9SJerin Jacob 		plt_delay_us(sleep);
36703cc9bd9SJerin Jacob 		timeout += sleep;
36803cc9bd9SJerin Jacob 	} while (!rsp_reg);
36903cc9bd9SJerin Jacob 
37003cc9bd9SJerin Jacob 	plt_rmb();
37103cc9bd9SJerin Jacob 
37203cc9bd9SJerin Jacob 	/* Clear interrupt */
37303cc9bd9SJerin Jacob 	plt_write64(rsp_reg, reg_addr);
37403cc9bd9SJerin Jacob 
37503cc9bd9SJerin Jacob 	/* Reset mbox */
37603cc9bd9SJerin Jacob 	mbox_reset(mbox, 0);
37703cc9bd9SJerin Jacob 
37803cc9bd9SJerin Jacob 	return 0;
37903cc9bd9SJerin Jacob }
38003cc9bd9SJerin Jacob 
38103cc9bd9SJerin Jacob /**
38203cc9bd9SJerin Jacob  * @internal
38303cc9bd9SJerin Jacob  * Wait and get mailbox response with timeout
38403cc9bd9SJerin Jacob  */
38503cc9bd9SJerin Jacob int
38603cc9bd9SJerin Jacob mbox_get_rsp_tmo(struct mbox *mbox, int devid, void **msg, uint32_t tmo)
38703cc9bd9SJerin Jacob {
38803cc9bd9SJerin Jacob 	struct mbox_dev *mdev = &mbox->dev[devid];
38903cc9bd9SJerin Jacob 	struct mbox_msghdr *msghdr;
39003cc9bd9SJerin Jacob 	uint64_t offset;
39103cc9bd9SJerin Jacob 	int rc;
39203cc9bd9SJerin Jacob 
39303cc9bd9SJerin Jacob 	rc = mbox_wait_for_rsp_tmo(mbox, devid, tmo);
39403cc9bd9SJerin Jacob 	if (rc != 1)
39503cc9bd9SJerin Jacob 		return -EIO;
39603cc9bd9SJerin Jacob 
39703cc9bd9SJerin Jacob 	plt_rmb();
39803cc9bd9SJerin Jacob 
39903cc9bd9SJerin Jacob 	offset = mbox->rx_start +
40003cc9bd9SJerin Jacob 		 PLT_ALIGN(sizeof(struct mbox_hdr), MBOX_MSG_ALIGN);
40103cc9bd9SJerin Jacob 	msghdr = (struct mbox_msghdr *)((uintptr_t)mdev->mbase + offset);
40203cc9bd9SJerin Jacob 	if (msg != NULL)
40303cc9bd9SJerin Jacob 		*msg = msghdr;
40403cc9bd9SJerin Jacob 
40503cc9bd9SJerin Jacob 	return msghdr->rc;
40603cc9bd9SJerin Jacob }
40703cc9bd9SJerin Jacob 
40803cc9bd9SJerin Jacob static int
40903cc9bd9SJerin Jacob mbox_wait(struct mbox *mbox, int devid, uint32_t rst_timo)
41003cc9bd9SJerin Jacob {
41103cc9bd9SJerin Jacob 	volatile struct mbox_dev *mdev = &mbox->dev[devid];
41203cc9bd9SJerin Jacob 	uint32_t timeout = 0, sleep = 1;
41303cc9bd9SJerin Jacob 
41403cc9bd9SJerin Jacob 	rst_timo = rst_timo * 1000; /* Milli seconds to micro seconds */
415dfb5a7a7SHarman Kalra 
416dfb5a7a7SHarman Kalra 	/* Waiting for mdev->msgs_acked tp become equal to mdev->num_msgs,
417dfb5a7a7SHarman Kalra 	 * mdev->msgs_acked are incremented at process_msgs() in interrupt
418dfb5a7a7SHarman Kalra 	 * thread context.
419dfb5a7a7SHarman Kalra 	 */
42003cc9bd9SJerin Jacob 	while (mdev->num_msgs > mdev->msgs_acked) {
42103cc9bd9SJerin Jacob 		plt_delay_us(sleep);
42203cc9bd9SJerin Jacob 		timeout += sleep;
42303cc9bd9SJerin Jacob 		if (timeout >= rst_timo) {
42403cc9bd9SJerin Jacob 			struct mbox_hdr *tx_hdr =
42503cc9bd9SJerin Jacob 				(struct mbox_hdr *)((uintptr_t)mdev->mbase +
42603cc9bd9SJerin Jacob 						    mbox->tx_start);
42703cc9bd9SJerin Jacob 			struct mbox_hdr *rx_hdr =
42803cc9bd9SJerin Jacob 				(struct mbox_hdr *)((uintptr_t)mdev->mbase +
42903cc9bd9SJerin Jacob 						    mbox->rx_start);
43003cc9bd9SJerin Jacob 
43103cc9bd9SJerin Jacob 			plt_err("MBOX[devid: %d] message wait timeout %d, "
43203cc9bd9SJerin Jacob 				"num_msgs: %d, msgs_acked: %d "
43303cc9bd9SJerin Jacob 				"(tx/rx num_msgs: %d/%d), msg_size: %d, "
43403cc9bd9SJerin Jacob 				"rsp_size: %d",
43503cc9bd9SJerin Jacob 				devid, timeout, mdev->num_msgs,
43603cc9bd9SJerin Jacob 				mdev->msgs_acked, tx_hdr->num_msgs,
43703cc9bd9SJerin Jacob 				rx_hdr->num_msgs, mdev->msg_size,
43803cc9bd9SJerin Jacob 				mdev->rsp_size);
43903cc9bd9SJerin Jacob 
44003cc9bd9SJerin Jacob 			return -EIO;
44103cc9bd9SJerin Jacob 		}
44203cc9bd9SJerin Jacob 		plt_rmb();
44303cc9bd9SJerin Jacob 	}
44403cc9bd9SJerin Jacob 	return 0;
44503cc9bd9SJerin Jacob }
44603cc9bd9SJerin Jacob 
44703cc9bd9SJerin Jacob int
44803cc9bd9SJerin Jacob mbox_wait_for_rsp_tmo(struct mbox *mbox, int devid, uint32_t tmo)
44903cc9bd9SJerin Jacob {
45003cc9bd9SJerin Jacob 	struct mbox_dev *mdev = &mbox->dev[devid];
45103cc9bd9SJerin Jacob 	int rc = 0;
45203cc9bd9SJerin Jacob 
45303cc9bd9SJerin Jacob 	/* Sync with mbox region */
45403cc9bd9SJerin Jacob 	plt_rmb();
45503cc9bd9SJerin Jacob 
45603cc9bd9SJerin Jacob 	if (mbox->trigger == RVU_PF_VFX_PFVF_MBOX1 ||
45703cc9bd9SJerin Jacob 	    mbox->trigger == RVU_PF_VFX_PFVF_MBOX0) {
45803cc9bd9SJerin Jacob 		/* In case of VF, Wait a bit more to account round trip delay */
45903cc9bd9SJerin Jacob 		tmo = tmo * 2;
46003cc9bd9SJerin Jacob 	}
46103cc9bd9SJerin Jacob 
46203cc9bd9SJerin Jacob 	/* Wait message */
46303cc9bd9SJerin Jacob 	if (plt_thread_is_intr())
46403cc9bd9SJerin Jacob 		rc = mbox_poll(mbox, tmo);
46503cc9bd9SJerin Jacob 	else
46603cc9bd9SJerin Jacob 		rc = mbox_wait(mbox, devid, tmo);
46703cc9bd9SJerin Jacob 
46803cc9bd9SJerin Jacob 	if (!rc)
46903cc9bd9SJerin Jacob 		rc = mdev->num_msgs;
47003cc9bd9SJerin Jacob 
47103cc9bd9SJerin Jacob 	return rc;
47203cc9bd9SJerin Jacob }
47303cc9bd9SJerin Jacob 
47403cc9bd9SJerin Jacob /**
47503cc9bd9SJerin Jacob  * @internal
47603cc9bd9SJerin Jacob  * Wait for the mailbox response
47703cc9bd9SJerin Jacob  */
47803cc9bd9SJerin Jacob int
47903cc9bd9SJerin Jacob mbox_wait_for_rsp(struct mbox *mbox, int devid)
48003cc9bd9SJerin Jacob {
48103cc9bd9SJerin Jacob 	return mbox_wait_for_rsp_tmo(mbox, devid, mbox->rsp_tmo);
48203cc9bd9SJerin Jacob }
48303cc9bd9SJerin Jacob 
48403cc9bd9SJerin Jacob int
48503cc9bd9SJerin Jacob mbox_get_availmem(struct mbox *mbox, int devid)
48603cc9bd9SJerin Jacob {
48703cc9bd9SJerin Jacob 	struct mbox_dev *mdev = &mbox->dev[devid];
48803cc9bd9SJerin Jacob 	int avail;
48903cc9bd9SJerin Jacob 
49003cc9bd9SJerin Jacob 	plt_spinlock_lock(&mdev->mbox_lock);
49103cc9bd9SJerin Jacob 	avail = mbox->tx_size - mdev->msg_size - msgs_offset();
49203cc9bd9SJerin Jacob 	plt_spinlock_unlock(&mdev->mbox_lock);
49303cc9bd9SJerin Jacob 
49403cc9bd9SJerin Jacob 	return avail;
49503cc9bd9SJerin Jacob }
49603cc9bd9SJerin Jacob 
49703cc9bd9SJerin Jacob int
49803cc9bd9SJerin Jacob send_ready_msg(struct mbox *mbox, uint16_t *pcifunc)
49903cc9bd9SJerin Jacob {
50003cc9bd9SJerin Jacob 	struct ready_msg_rsp *rsp;
50103cc9bd9SJerin Jacob 	int rc;
50203cc9bd9SJerin Jacob 
50344a9307cSRakesh Kudurumalla 	mbox_alloc_msg_ready(mbox_get(mbox));
50403cc9bd9SJerin Jacob 
50503cc9bd9SJerin Jacob 	rc = mbox_process_msg(mbox, (void *)&rsp);
50644a9307cSRakesh Kudurumalla 	if (rc) {
50744a9307cSRakesh Kudurumalla 		mbox_put(mbox);
50803cc9bd9SJerin Jacob 		return rc;
50944a9307cSRakesh Kudurumalla 	}
51044a9307cSRakesh Kudurumalla 	mbox_put(mbox);
51103cc9bd9SJerin Jacob 
51203cc9bd9SJerin Jacob 	if (rsp->hdr.ver != MBOX_VERSION) {
51303cc9bd9SJerin Jacob 		plt_err("Incompatible MBox versions(AF: 0x%04x Client: 0x%04x)",
51403cc9bd9SJerin Jacob 			rsp->hdr.ver, MBOX_VERSION);
51503cc9bd9SJerin Jacob 		return -EPIPE;
51603cc9bd9SJerin Jacob 	}
51703cc9bd9SJerin Jacob 
51803cc9bd9SJerin Jacob 	if (pcifunc)
51903cc9bd9SJerin Jacob 		*pcifunc = rsp->hdr.pcifunc;
52003cc9bd9SJerin Jacob 
52103cc9bd9SJerin Jacob 	/* Save rclk & sclk freq */
52203cc9bd9SJerin Jacob 	if (!dev_rclk_freq || !dev_sclk_freq) {
52303cc9bd9SJerin Jacob 		dev_rclk_freq = rsp->rclk_freq;
52403cc9bd9SJerin Jacob 		dev_sclk_freq = rsp->sclk_freq;
52503cc9bd9SJerin Jacob 	}
52603cc9bd9SJerin Jacob 	return 0;
52703cc9bd9SJerin Jacob }
52803cc9bd9SJerin Jacob 
52903cc9bd9SJerin Jacob int
53003cc9bd9SJerin Jacob reply_invalid_msg(struct mbox *mbox, int devid, uint16_t pcifunc, uint16_t id)
53103cc9bd9SJerin Jacob {
53203cc9bd9SJerin Jacob 	struct msg_rsp *rsp;
53303cc9bd9SJerin Jacob 
53403cc9bd9SJerin Jacob 	rsp = (struct msg_rsp *)mbox_alloc_msg(mbox, devid, sizeof(*rsp));
53503cc9bd9SJerin Jacob 	if (!rsp)
53603cc9bd9SJerin Jacob 		return -ENOMEM;
53703cc9bd9SJerin Jacob 	rsp->hdr.id = id;
53803cc9bd9SJerin Jacob 	rsp->hdr.sig = MBOX_RSP_SIG;
53903cc9bd9SJerin Jacob 	rsp->hdr.rc = MBOX_MSG_INVALID;
54003cc9bd9SJerin Jacob 	rsp->hdr.pcifunc = pcifunc;
54103cc9bd9SJerin Jacob 
54203cc9bd9SJerin Jacob 	return 0;
54303cc9bd9SJerin Jacob }
54403cc9bd9SJerin Jacob 
54503cc9bd9SJerin Jacob /**
54603cc9bd9SJerin Jacob  * @internal
54703cc9bd9SJerin Jacob  * Convert mail box ID to name
54803cc9bd9SJerin Jacob  */
54903cc9bd9SJerin Jacob const char *
55003cc9bd9SJerin Jacob mbox_id2name(uint16_t id)
55103cc9bd9SJerin Jacob {
55203cc9bd9SJerin Jacob 	switch (id) {
55303cc9bd9SJerin Jacob 	default:
55403cc9bd9SJerin Jacob 		return "INVALID ID";
55503cc9bd9SJerin Jacob #define M(_name, _id, _1, _2, _3)                                              \
55603cc9bd9SJerin Jacob 	case _id:                                                              \
55703cc9bd9SJerin Jacob 		return #_name;
55803cc9bd9SJerin Jacob 		MBOX_MESSAGES
55903cc9bd9SJerin Jacob 		MBOX_UP_CGX_MESSAGES
560d85c80b4SHarman Kalra 		MBOX_UP_REP_MESSAGES
56103cc9bd9SJerin Jacob #undef M
56203cc9bd9SJerin Jacob 	}
56303cc9bd9SJerin Jacob }
56403cc9bd9SJerin Jacob 
56503cc9bd9SJerin Jacob int
56603cc9bd9SJerin Jacob mbox_id2size(uint16_t id)
56703cc9bd9SJerin Jacob {
56803cc9bd9SJerin Jacob 	switch (id) {
56903cc9bd9SJerin Jacob 	default:
57003cc9bd9SJerin Jacob 		return 0;
57103cc9bd9SJerin Jacob #define M(_1, _id, _2, _req_type, _3)                                          \
57203cc9bd9SJerin Jacob 	case _id:                                                              \
57303cc9bd9SJerin Jacob 		return sizeof(struct _req_type);
57403cc9bd9SJerin Jacob 		MBOX_MESSAGES
57503cc9bd9SJerin Jacob 		MBOX_UP_CGX_MESSAGES
576d85c80b4SHarman Kalra 		MBOX_UP_REP_MESSAGES
57703cc9bd9SJerin Jacob #undef M
57803cc9bd9SJerin Jacob 	}
57903cc9bd9SJerin Jacob }
580