xref: /rk3399_rockchip-uboot/arch/arm/mach-bcm283x/mbox.c (revision 2b513158946b342a98f14671fd3a84827510a20f)
1ddf6bd48SMasahiro Yamada /*
2ddf6bd48SMasahiro Yamada  * (C) Copyright 2012 Stephen Warren
3ddf6bd48SMasahiro Yamada  *
4ddf6bd48SMasahiro Yamada  * SPDX-License-Identifier:	GPL-2.0+
5ddf6bd48SMasahiro Yamada  */
6ddf6bd48SMasahiro Yamada 
7ddf6bd48SMasahiro Yamada #include <common.h>
8ddf6bd48SMasahiro Yamada #include <asm/io.h>
9ddf6bd48SMasahiro Yamada #include <asm/arch/mbox.h>
10122426d4SStephen Warren #include <phys2bus.h>
11ddf6bd48SMasahiro Yamada 
12ddf6bd48SMasahiro Yamada #define TIMEOUT 1000 /* ms */
13ddf6bd48SMasahiro Yamada 
bcm2835_mbox_call_raw(u32 chan,u32 send,u32 * recv)14ddf6bd48SMasahiro Yamada int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv)
15ddf6bd48SMasahiro Yamada {
16ddf6bd48SMasahiro Yamada 	struct bcm2835_mbox_regs *regs =
17ddf6bd48SMasahiro Yamada 		(struct bcm2835_mbox_regs *)BCM2835_MBOX_PHYSADDR;
18ddf6bd48SMasahiro Yamada 	ulong endtime = get_timer(0) + TIMEOUT;
19ddf6bd48SMasahiro Yamada 	u32 val;
20ddf6bd48SMasahiro Yamada 
21ddf6bd48SMasahiro Yamada 	debug("time: %lu timeout: %lu\n", get_timer(0), endtime);
22ddf6bd48SMasahiro Yamada 
23ddf6bd48SMasahiro Yamada 	if (send & BCM2835_CHAN_MASK) {
24ddf6bd48SMasahiro Yamada 		printf("mbox: Illegal mbox data 0x%08x\n", send);
25ddf6bd48SMasahiro Yamada 		return -1;
26ddf6bd48SMasahiro Yamada 	}
27ddf6bd48SMasahiro Yamada 
28ddf6bd48SMasahiro Yamada 	/* Drain any stale responses */
29ddf6bd48SMasahiro Yamada 
30ddf6bd48SMasahiro Yamada 	for (;;) {
31ddf6bd48SMasahiro Yamada 		val = readl(&regs->status);
32ddf6bd48SMasahiro Yamada 		if (val & BCM2835_MBOX_STATUS_RD_EMPTY)
33ddf6bd48SMasahiro Yamada 			break;
34ddf6bd48SMasahiro Yamada 		if (get_timer(0) >= endtime) {
35ddf6bd48SMasahiro Yamada 			printf("mbox: Timeout draining stale responses\n");
36ddf6bd48SMasahiro Yamada 			return -1;
37ddf6bd48SMasahiro Yamada 		}
38ddf6bd48SMasahiro Yamada 		val = readl(&regs->read);
39ddf6bd48SMasahiro Yamada 	}
40ddf6bd48SMasahiro Yamada 
41ddf6bd48SMasahiro Yamada 	/* Wait for space to send */
42ddf6bd48SMasahiro Yamada 
43ddf6bd48SMasahiro Yamada 	for (;;) {
44ddf6bd48SMasahiro Yamada 		val = readl(&regs->status);
45ddf6bd48SMasahiro Yamada 		if (!(val & BCM2835_MBOX_STATUS_WR_FULL))
46ddf6bd48SMasahiro Yamada 			break;
47ddf6bd48SMasahiro Yamada 		if (get_timer(0) >= endtime) {
48ddf6bd48SMasahiro Yamada 			printf("mbox: Timeout waiting for send space\n");
49ddf6bd48SMasahiro Yamada 			return -1;
50ddf6bd48SMasahiro Yamada 		}
51ddf6bd48SMasahiro Yamada 	}
52ddf6bd48SMasahiro Yamada 
53ddf6bd48SMasahiro Yamada 	/* Send the request */
54ddf6bd48SMasahiro Yamada 
55ddf6bd48SMasahiro Yamada 	val = BCM2835_MBOX_PACK(chan, send);
56ddf6bd48SMasahiro Yamada 	debug("mbox: TX raw: 0x%08x\n", val);
57ddf6bd48SMasahiro Yamada 	writel(val, &regs->write);
58ddf6bd48SMasahiro Yamada 
59ddf6bd48SMasahiro Yamada 	/* Wait for the response */
60ddf6bd48SMasahiro Yamada 
61ddf6bd48SMasahiro Yamada 	for (;;) {
62ddf6bd48SMasahiro Yamada 		val = readl(&regs->status);
63ddf6bd48SMasahiro Yamada 		if (!(val & BCM2835_MBOX_STATUS_RD_EMPTY))
64ddf6bd48SMasahiro Yamada 			break;
65ddf6bd48SMasahiro Yamada 		if (get_timer(0) >= endtime) {
66ddf6bd48SMasahiro Yamada 			printf("mbox: Timeout waiting for response\n");
67ddf6bd48SMasahiro Yamada 			return -1;
68ddf6bd48SMasahiro Yamada 		}
69ddf6bd48SMasahiro Yamada 	}
70ddf6bd48SMasahiro Yamada 
71ddf6bd48SMasahiro Yamada 	/* Read the response */
72ddf6bd48SMasahiro Yamada 
73ddf6bd48SMasahiro Yamada 	val = readl(&regs->read);
74ddf6bd48SMasahiro Yamada 	debug("mbox: RX raw: 0x%08x\n", val);
75ddf6bd48SMasahiro Yamada 
76ddf6bd48SMasahiro Yamada 	/* Validate the response */
77ddf6bd48SMasahiro Yamada 
78ddf6bd48SMasahiro Yamada 	if (BCM2835_MBOX_UNPACK_CHAN(val) != chan) {
79ddf6bd48SMasahiro Yamada 		printf("mbox: Response channel mismatch\n");
80ddf6bd48SMasahiro Yamada 		return -1;
81ddf6bd48SMasahiro Yamada 	}
82ddf6bd48SMasahiro Yamada 
83ddf6bd48SMasahiro Yamada 	*recv = BCM2835_MBOX_UNPACK_DATA(val);
84ddf6bd48SMasahiro Yamada 
85ddf6bd48SMasahiro Yamada 	return 0;
86ddf6bd48SMasahiro Yamada }
87ddf6bd48SMasahiro Yamada 
88ddf6bd48SMasahiro Yamada #ifdef DEBUG
dump_buf(struct bcm2835_mbox_hdr * buffer)89ddf6bd48SMasahiro Yamada void dump_buf(struct bcm2835_mbox_hdr *buffer)
90ddf6bd48SMasahiro Yamada {
91ddf6bd48SMasahiro Yamada 	u32 *p;
92ddf6bd48SMasahiro Yamada 	u32 words;
93ddf6bd48SMasahiro Yamada 	int i;
94ddf6bd48SMasahiro Yamada 
95ddf6bd48SMasahiro Yamada 	p = (u32 *)buffer;
96ddf6bd48SMasahiro Yamada 	words = buffer->buf_size / 4;
97ddf6bd48SMasahiro Yamada 	for (i = 0; i < words; i++)
98ddf6bd48SMasahiro Yamada 		printf("    0x%04x: 0x%08x\n", i * 4, p[i]);
99ddf6bd48SMasahiro Yamada }
100ddf6bd48SMasahiro Yamada #endif
101ddf6bd48SMasahiro Yamada 
bcm2835_mbox_call_prop(u32 chan,struct bcm2835_mbox_hdr * buffer)102ddf6bd48SMasahiro Yamada int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer)
103ddf6bd48SMasahiro Yamada {
104ddf6bd48SMasahiro Yamada 	int ret;
105ddf6bd48SMasahiro Yamada 	u32 rbuffer;
106ddf6bd48SMasahiro Yamada 	struct bcm2835_mbox_tag_hdr *tag;
107ddf6bd48SMasahiro Yamada 	int tag_index;
108ddf6bd48SMasahiro Yamada 
109ddf6bd48SMasahiro Yamada #ifdef DEBUG
110ddf6bd48SMasahiro Yamada 	printf("mbox: TX buffer\n");
111ddf6bd48SMasahiro Yamada 	dump_buf(buffer);
112ddf6bd48SMasahiro Yamada #endif
113ddf6bd48SMasahiro Yamada 
1144342557fSAlexander Stein 	flush_dcache_range((unsigned long)buffer,
1154342557fSAlexander Stein 			   (unsigned long)((void *)buffer +
1164342557fSAlexander Stein 			   roundup(buffer->buf_size, ARCH_DMA_MINALIGN)));
1174342557fSAlexander Stein 
118*2b513158SStephen Warren 	ret = bcm2835_mbox_call_raw(chan,
119*2b513158SStephen Warren 				    phys_to_bus((unsigned long)buffer),
120*2b513158SStephen Warren 				    &rbuffer);
121ddf6bd48SMasahiro Yamada 	if (ret)
122ddf6bd48SMasahiro Yamada 		return ret;
1234342557fSAlexander Stein 
1244342557fSAlexander Stein 	invalidate_dcache_range((unsigned long)buffer,
1254342557fSAlexander Stein 				(unsigned long)((void *)buffer +
1264342557fSAlexander Stein 				roundup(buffer->buf_size, ARCH_DMA_MINALIGN)));
1274342557fSAlexander Stein 
128*2b513158SStephen Warren 	if (rbuffer != phys_to_bus((unsigned long)buffer)) {
129ddf6bd48SMasahiro Yamada 		printf("mbox: Response buffer mismatch\n");
130ddf6bd48SMasahiro Yamada 		return -1;
131ddf6bd48SMasahiro Yamada 	}
132ddf6bd48SMasahiro Yamada 
133ddf6bd48SMasahiro Yamada #ifdef DEBUG
134ddf6bd48SMasahiro Yamada 	printf("mbox: RX buffer\n");
135ddf6bd48SMasahiro Yamada 	dump_buf(buffer);
136ddf6bd48SMasahiro Yamada #endif
137ddf6bd48SMasahiro Yamada 
138ddf6bd48SMasahiro Yamada 	/* Validate overall response status */
139ddf6bd48SMasahiro Yamada 
140ddf6bd48SMasahiro Yamada 	if (buffer->code != BCM2835_MBOX_RESP_CODE_SUCCESS) {
141ddf6bd48SMasahiro Yamada 		printf("mbox: Header response code invalid\n");
142ddf6bd48SMasahiro Yamada 		return -1;
143ddf6bd48SMasahiro Yamada 	}
144ddf6bd48SMasahiro Yamada 
145ddf6bd48SMasahiro Yamada 	/* Validate each tag's response status */
146ddf6bd48SMasahiro Yamada 
147ddf6bd48SMasahiro Yamada 	tag = (void *)(buffer + 1);
148ddf6bd48SMasahiro Yamada 	tag_index = 0;
149ddf6bd48SMasahiro Yamada 	while (tag->tag) {
150ddf6bd48SMasahiro Yamada 		if (!(tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE)) {
151ddf6bd48SMasahiro Yamada 			printf("mbox: Tag %d missing val_len response bit\n",
152ddf6bd48SMasahiro Yamada 				tag_index);
153ddf6bd48SMasahiro Yamada 			return -1;
154ddf6bd48SMasahiro Yamada 		}
155ddf6bd48SMasahiro Yamada 		/*
156ddf6bd48SMasahiro Yamada 		 * Clear the reponse bit so clients can just look right at the
157ddf6bd48SMasahiro Yamada 		 * length field without extra processing
158ddf6bd48SMasahiro Yamada 		 */
159ddf6bd48SMasahiro Yamada 		tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE;
160ddf6bd48SMasahiro Yamada 		tag = (void *)(((u8 *)tag) + sizeof(*tag) + tag->val_buf_size);
161ddf6bd48SMasahiro Yamada 		tag_index++;
162ddf6bd48SMasahiro Yamada 	}
163ddf6bd48SMasahiro Yamada 
164ddf6bd48SMasahiro Yamada 	return 0;
165ddf6bd48SMasahiro Yamada }
166