1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2012 Stephen Warren
9 #include <asm/arch/base.h>
10 #include <asm/arch/mbox.h>
13 #define TIMEOUT 1000 /* ms */
15 int bcm2835_mbox_call_raw(u32 chan, u32 send, u32 *recv)
17 struct bcm2835_mbox_regs *regs =
18 (struct bcm2835_mbox_regs *)BCM2835_MBOX_PHYSADDR;
19 ulong endtime = get_timer(0) + TIMEOUT;
22 debug("time: %lu timeout: %lu\n", get_timer(0), endtime);
24 if (send & BCM2835_CHAN_MASK) {
25 printf("mbox: Illegal mbox data 0x%08x\n", send);
29 /* Drain any stale responses */
32 val = readl(®s->mail0_status);
33 if (val & BCM2835_MBOX_STATUS_RD_EMPTY)
35 if (get_timer(0) >= endtime) {
36 printf("mbox: Timeout draining stale responses\n");
39 val = readl(®s->read);
42 /* Wait for space to send */
45 val = readl(®s->mail1_status);
46 if (!(val & BCM2835_MBOX_STATUS_WR_FULL))
48 if (get_timer(0) >= endtime) {
49 printf("mbox: Timeout waiting for send space\n");
54 /* Send the request */
56 val = BCM2835_MBOX_PACK(chan, send);
57 debug("mbox: TX raw: 0x%08x\n", val);
58 writel(val, ®s->write);
60 /* Wait for the response */
63 val = readl(®s->mail0_status);
64 if (!(val & BCM2835_MBOX_STATUS_RD_EMPTY))
66 if (get_timer(0) >= endtime) {
67 printf("mbox: Timeout waiting for response\n");
72 /* Read the response */
74 val = readl(®s->read);
75 debug("mbox: RX raw: 0x%08x\n", val);
77 /* Validate the response */
79 if (BCM2835_MBOX_UNPACK_CHAN(val) != chan) {
80 printf("mbox: Response channel mismatch\n");
84 *recv = BCM2835_MBOX_UNPACK_DATA(val);
90 void dump_buf(struct bcm2835_mbox_hdr *buffer)
97 words = buffer->buf_size / 4;
98 for (i = 0; i < words; i++)
99 printf(" 0x%04x: 0x%08x\n", i * 4, p[i]);
103 int bcm2835_mbox_call_prop(u32 chan, struct bcm2835_mbox_hdr *buffer)
107 struct bcm2835_mbox_tag_hdr *tag;
111 printf("mbox: TX buffer\n");
115 flush_dcache_range((unsigned long)buffer,
116 (unsigned long)((void *)buffer +
117 roundup(buffer->buf_size, ARCH_DMA_MINALIGN)));
119 ret = bcm2835_mbox_call_raw(chan,
120 phys_to_bus((unsigned long)buffer),
125 invalidate_dcache_range((unsigned long)buffer,
126 (unsigned long)((void *)buffer +
127 roundup(buffer->buf_size, ARCH_DMA_MINALIGN)));
129 if (rbuffer != phys_to_bus((unsigned long)buffer)) {
130 printf("mbox: Response buffer mismatch\n");
135 printf("mbox: RX buffer\n");
139 /* Validate overall response status */
141 if (buffer->code != BCM2835_MBOX_RESP_CODE_SUCCESS) {
142 printf("mbox: Header response code invalid\n");
146 /* Validate each tag's response status */
148 tag = (void *)(buffer + 1);
151 if (!(tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE)) {
152 printf("mbox: Tag %d missing val_len response bit\n",
157 * Clear the reponse bit so clients can just look right at the
158 * length field without extra processing
160 tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE;
161 tag = (void *)(((u8 *)tag) + sizeof(*tag) + tag->val_buf_size);