1
0
Fork 0
aedrix-kernel/drivers/bcm2835_mailbox.c

70 lines
2.4 KiB
C

/*
Copyright (C) 2012, Aaron Lindsay <aaron@aclindsay.com>
This file is part of Aedrix.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <types.h>
/* Mailbox Memory-Mapped Registers */
#define VC_MMU_IO_OFFSET(addr) (addr - 0x7E000000 + 0x20000000)
#define MBOX0_READ VC_MMU_IO_OFFSET(0x7E00B880)
/* MBOX0_READ layout:
31-4 data The 28 bits of data sent to the CPU
3-0 channel The mailbox channel number from which the data originated */
#define MBOX0_PEEK VC_MMU_IO_OFFSET(0x7E00B890) //Read from the mailbox without removing data from it.
#define MBOX0_SENDER VC_MMU_IO_OFFSET(0x7E00B894) //Sender ID (bottom 2 bits only)
#define MBOX0_STATUS VC_MMU_IO_OFFSET(0x7E00B898)
/* MBOX0_STATUS layout:
31 full Set if the mailbox is full, and thus no more data can be written to it.
30 empty Set if the mailbox is empty, and thus no more data is available to be read from it.
29-0 unused? */
#define MBOX0_CONFIG VC_MMU_IO_OFFSET(0x7E00B89C)
#define MBOX0_WRITE VC_MMU_IO_OFFSET(0x7E00B8A0) //also MBOX1_READ?
/* MBOX0_WRITE layout:
31-4 data The 28 bits of data to be sent
3-0 channel The mailbox channel to send data to */
#define MBOX0_STATUS_FULL 0x80000000
#define MBOX0_STATUS_EMPTY 0x40000000
uint32 mailbox_read(uint32 channel) {
uint32 mbox_msg;
while (1) {
int i;
for (i = 0; *(volatile uint32 *)MBOX0_STATUS & MBOX0_STATUS_EMPTY; i++) {
if (i >= 1<<20)
return 0xFFFFFFFF;
}
mbox_msg = *(volatile uint32 *)MBOX0_READ;
if ((mbox_msg & 0xf) == channel)
return mbox_msg & ~0xf;
}
}
void mailbox_write(uint32 channel, uint32 data) {
channel &= 0xf;
data &= ~0xf;
while (*(volatile uint32 *)MBOX0_STATUS & MBOX0_STATUS_FULL);
*(volatile uint32 *)MBOX0_WRITE = channel | data;
}