rpi4-osdev/part12-wgt/lib/mb.c
2021-03-11 22:33:27 +00:00

98 lines
2.6 KiB
C

#include "../include/io.h"
#include "../include/mb.h"
// The buffer must be 16-byte aligned as only the upper 28 bits of the address can be passed via the mailbox
volatile unsigned int __attribute__((aligned(16))) mbox[36];
enum {
VIDEOCORE_MBOX = (PERIPHERAL_BASE + 0x0000B880),
MBOX_READ = (VIDEOCORE_MBOX + 0x0),
MBOX_POLL = (VIDEOCORE_MBOX + 0x10),
MBOX_SENDER = (VIDEOCORE_MBOX + 0x14),
MBOX_STATUS = (VIDEOCORE_MBOX + 0x18),
MBOX_CONFIG = (VIDEOCORE_MBOX + 0x1C),
MBOX_WRITE = (VIDEOCORE_MBOX + 0x20),
MBOX_RESPONSE = 0x80000000,
MBOX_FULL = 0x80000000,
MBOX_EMPTY = 0x40000000
};
unsigned int mbox_call(unsigned char ch)
{
// 28-bit address (MSB) and 4-bit value (LSB)
unsigned int r = ((unsigned int)((long) &mbox) &~ 0xF) | (ch & 0xF);
// Wait until we can write
while (mmio_read(MBOX_STATUS) & MBOX_FULL);
// Write the address of our buffer to the mailbox with the channel appended
mmio_write(MBOX_WRITE, r);
while (1) {
// Is there a reply?
while (mmio_read(MBOX_STATUS) & MBOX_EMPTY);
// Is it a reply to our message?
if (r == mmio_read(MBOX_READ)) return mbox[1]==MBOX_RESPONSE; // Is it successful?
}
return 0;
}
int get_max_clock()
{
mbox[0] = 8*4; // Length of message in bytes
mbox[1] = MBOX_REQUEST;
mbox[2] = MBOX_TAG_GETCLKMAXM; // Tag identifier
mbox[3] = 8; // Value size in bytes
mbox[4] = 0; // Value size in bytes
mbox[5] = 0x3; // Value
mbox[6] = 0; // Rate
mbox[7] = MBOX_TAG_LAST;
if (mbox_call(MBOX_CH_PROP)) {
if (mbox[5] == 0x3) {
return mbox[6];
}
}
return 0;
}
int get_clock_rate()
{
mbox[0] = 8*4; // Length of message in bytes
mbox[1] = MBOX_REQUEST;
mbox[2] = MBOX_TAG_GETCLKRATE; // Tag identifier
mbox[3] = 8; // Value size in bytes
mbox[4] = 0; // Value size in bytes
mbox[5] = 0x3; // Value
mbox[6] = 0; // Rate
mbox[7] = MBOX_TAG_LAST;
if (mbox_call(MBOX_CH_PROP)) {
if (mbox[5] == 0x3) {
return mbox[6];
}
}
return 0;
}
int set_clock_rate(unsigned int rate)
{
mbox[0] = 9*4; // Length of message in bytes
mbox[1] = MBOX_REQUEST;
mbox[2] = MBOX_TAG_SETCLKRATE; // Tag identifier
mbox[3] = 12; // Value size in bytes
mbox[4] = 0; // Value size in bytes
mbox[5] = 0x3; // Value
mbox[6] = rate; // Rate
mbox[7] = 0; // Rate
mbox[8] = MBOX_TAG_LAST;
if (mbox_call(MBOX_CH_PROP)) {
if (mbox[5] == 0x3 && mbox[6] == rate) {
return 1;
}
}
return 0;
}