xref: /arm-trusted-firmware/drivers/rpi3/mailbox/rpi3_mbox.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <platform_def.h>
8*91f16700Schasinglulu 
9*91f16700Schasinglulu #include <arch_helpers.h>
10*91f16700Schasinglulu #include <common/debug.h>
11*91f16700Schasinglulu #include <lib/mmio.h>
12*91f16700Schasinglulu 
13*91f16700Schasinglulu #include <rpi_hw.h>
14*91f16700Schasinglulu 
15*91f16700Schasinglulu #include <drivers/rpi3/mailbox/rpi3_mbox.h>
16*91f16700Schasinglulu 
17*91f16700Schasinglulu #define RPI3_MAILBOX_MAX_RETRIES	U(1000000)
18*91f16700Schasinglulu 
19*91f16700Schasinglulu /*******************************************************************************
20*91f16700Schasinglulu  * Routine to send requests to the VideoCore using the mailboxes.
21*91f16700Schasinglulu  ******************************************************************************/
22*91f16700Schasinglulu void rpi3_vc_mailbox_request_send(rpi3_mbox_request_t *req, int req_size)
23*91f16700Schasinglulu {
24*91f16700Schasinglulu 	uint32_t st, data;
25*91f16700Schasinglulu 	uintptr_t resp_addr, addr;
26*91f16700Schasinglulu 	unsigned int retries;
27*91f16700Schasinglulu 
28*91f16700Schasinglulu 	/* This is the location of the request buffer */
29*91f16700Schasinglulu 	addr = (uintptr_t)req;
30*91f16700Schasinglulu 
31*91f16700Schasinglulu 	/* Make sure that the changes are seen by the VideoCore */
32*91f16700Schasinglulu 	flush_dcache_range(addr, req_size);
33*91f16700Schasinglulu 
34*91f16700Schasinglulu 	/* Wait until the outbound mailbox is empty */
35*91f16700Schasinglulu 	retries = 0U;
36*91f16700Schasinglulu 
37*91f16700Schasinglulu 	do {
38*91f16700Schasinglulu 		st = mmio_read_32(RPI3_MBOX_BASE + RPI3_MBOX1_STATUS_OFFSET);
39*91f16700Schasinglulu 
40*91f16700Schasinglulu 		retries++;
41*91f16700Schasinglulu 		if (retries == RPI3_MAILBOX_MAX_RETRIES) {
42*91f16700Schasinglulu 			ERROR("rpi3: mbox: Send request timeout\n");
43*91f16700Schasinglulu 			return;
44*91f16700Schasinglulu 		}
45*91f16700Schasinglulu 
46*91f16700Schasinglulu 	} while ((st & RPI3_MBOX_STATUS_EMPTY_MASK) == 0U);
47*91f16700Schasinglulu 
48*91f16700Schasinglulu 	/* Send base address of this message to start request */
49*91f16700Schasinglulu 	mmio_write_32(RPI3_MBOX_BASE + RPI3_MBOX1_WRITE_OFFSET,
50*91f16700Schasinglulu 		      RPI3_CHANNEL_ARM_TO_VC | (uint32_t) addr);
51*91f16700Schasinglulu 
52*91f16700Schasinglulu 	/* Wait until the inbound mailbox isn't empty */
53*91f16700Schasinglulu 	retries = 0U;
54*91f16700Schasinglulu 
55*91f16700Schasinglulu 	do {
56*91f16700Schasinglulu 		st = mmio_read_32(RPI3_MBOX_BASE + RPI3_MBOX0_STATUS_OFFSET);
57*91f16700Schasinglulu 
58*91f16700Schasinglulu 		retries++;
59*91f16700Schasinglulu 		if (retries == RPI3_MAILBOX_MAX_RETRIES) {
60*91f16700Schasinglulu 			ERROR("rpi3: mbox: Receive response timeout\n");
61*91f16700Schasinglulu 			return;
62*91f16700Schasinglulu 		}
63*91f16700Schasinglulu 
64*91f16700Schasinglulu 	} while ((st & RPI3_MBOX_STATUS_EMPTY_MASK) != 0U);
65*91f16700Schasinglulu 
66*91f16700Schasinglulu 	/* Get location and channel */
67*91f16700Schasinglulu 	data = mmio_read_32(RPI3_MBOX_BASE + RPI3_MBOX0_READ_OFFSET);
68*91f16700Schasinglulu 
69*91f16700Schasinglulu 	if ((data & RPI3_CHANNEL_MASK) != RPI3_CHANNEL_ARM_TO_VC) {
70*91f16700Schasinglulu 		ERROR("rpi3: mbox: Wrong channel: 0x%08x\n", data);
71*91f16700Schasinglulu 		panic();
72*91f16700Schasinglulu 	}
73*91f16700Schasinglulu 
74*91f16700Schasinglulu 	resp_addr = (uintptr_t)(data & ~RPI3_CHANNEL_MASK);
75*91f16700Schasinglulu 	if (addr != resp_addr) {
76*91f16700Schasinglulu 		ERROR("rpi3: mbox: Unexpected address: 0x%08x\n", data);
77*91f16700Schasinglulu 		panic();
78*91f16700Schasinglulu 	}
79*91f16700Schasinglulu 
80*91f16700Schasinglulu 	/* Make sure that the data seen by the CPU is up to date */
81*91f16700Schasinglulu 	inv_dcache_range(addr, req_size);
82*91f16700Schasinglulu }
83