2 * (C) Copyright 2012 Stephen Warren
4 * SPDX-License-Identifier: GPL-2.0+
9 #include <asm/arch/mbox.h>
11 #define TIMEOUT (100 * 1000) /* 100mS in uS */
13 int bcm2835_mbox_call_raw(u32 chan
, u32 send
, u32
*recv
)
15 struct bcm2835_mbox_regs
*regs
=
16 (struct bcm2835_mbox_regs
*)BCM2835_MBOX_PHYSADDR
;
17 ulong endtime
= get_timer(0) + TIMEOUT
;
20 debug("time: %lu timeout: %lu\n", get_timer(0), endtime
);
22 if (send
& BCM2835_CHAN_MASK
) {
23 printf("mbox: Illegal mbox data 0x%08x\n", send
);
27 /* Drain any stale responses */
30 val
= readl(®s
->status
);
31 if (val
& BCM2835_MBOX_STATUS_RD_EMPTY
)
33 if (get_timer(0) >= endtime
) {
34 printf("mbox: Timeout draining stale responses\n");
37 val
= readl(®s
->read
);
40 /* Wait for space to send */
43 val
= readl(®s
->status
);
44 if (!(val
& BCM2835_MBOX_STATUS_WR_FULL
))
46 if (get_timer(0) >= endtime
) {
47 printf("mbox: Timeout waiting for send space\n");
52 /* Send the request */
54 val
= BCM2835_MBOX_PACK(chan
, send
);
55 debug("mbox: TX raw: 0x%08x\n", val
);
56 writel(val
, ®s
->write
);
58 /* Wait for the response */
61 val
= readl(®s
->status
);
62 if (!(val
& BCM2835_MBOX_STATUS_RD_EMPTY
))
64 if (get_timer(0) >= endtime
) {
65 printf("mbox: Timeout waiting for response\n");
70 /* Read the response */
72 val
= readl(®s
->read
);
73 debug("mbox: RX raw: 0x%08x\n", val
);
75 /* Validate the response */
77 if (BCM2835_MBOX_UNPACK_CHAN(val
) != chan
) {
78 printf("mbox: Response channel mismatch\n");
82 *recv
= BCM2835_MBOX_UNPACK_DATA(val
);
88 void dump_buf(struct bcm2835_mbox_hdr
*buffer
)
95 words
= buffer
->buf_size
/ 4;
96 for (i
= 0; i
< words
; i
++)
97 printf(" 0x%04x: 0x%08x\n", i
* 4, p
[i
]);
101 int bcm2835_mbox_call_prop(u32 chan
, struct bcm2835_mbox_hdr
*buffer
)
105 struct bcm2835_mbox_tag_hdr
*tag
;
109 printf("mbox: TX buffer\n");
113 ret
= bcm2835_mbox_call_raw(chan
, (u32
)buffer
, &rbuffer
);
116 if (rbuffer
!= (u32
)buffer
) {
117 printf("mbox: Response buffer mismatch\n");
122 printf("mbox: RX buffer\n");
126 /* Validate overall response status */
128 if (buffer
->code
!= BCM2835_MBOX_RESP_CODE_SUCCESS
) {
129 printf("mbox: Header response code invalid\n");
133 /* Validate each tag's response status */
135 tag
= (void *)(buffer
+ 1);
138 if (!(tag
->val_len
& BCM2835_MBOX_TAG_VAL_LEN_RESPONSE
)) {
139 printf("mbox: Tag %d missing val_len response bit\n",
144 * Clear the reponse bit so clients can just look right at the
145 * length field without extra processing
147 tag
->val_len
&= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE
;
148 tag
= (void *)(((u8
*)tag
) + sizeof(*tag
) + tag
->val_buf_size
);