embox
1/**
2* @file
3* @brief Mailbox Communication mechanism for Raspberry Pi
4*
5* @date 16.07.15
6* @author Michele Di Giorgio
7*/
8
9#include <errno.h>10#include <stdint.h>11
12#include <drivers/mailbox/bcm2835_mailbox.h>13#include <hal/reg.h>14#include <hal/mem_barriers.h>15
16static struct bcm2835_mailbox_regs volatile *const mailbox_regs =17(struct bcm2835_mailbox_regs volatile *) BCM2835_MAILBOX_BASE;18
19/**
20* Read from memory mapped IO registers with a memory barrier around.
21* @param addr - pointer to register address
22*
23* @return data read (returns a memory location)
24*/
25static uint32_t read_mmio(uint32_t volatile *addr) {26uint32_t n;27n = REG_LOAD(addr);28data_mem_barrier();29return n;30}
31
32/**
33* Write to memory mapped IO register with a memory barrier around.
34* @param addr - pointer to register address
35* @param val - data to be stored (a pointer to a memory location)
36*/
37static void write_mmio(uint32_t volatile *addr, uint32_t val) {38data_mem_barrier();39REG_STORE(addr, val);40}
41
42int bcm2835_mailbox_write(uint32_t data, uint32_t channel) {43/* validate channel number */44if (channel > 15) {45return -EINVAL;46}47/* lowest 4 bits of data must be 0 and combine data and the channel */48uint32_t to_write = (data & BCM2835_MAILBOX_DATA_MASK) | channel;49/* read the status field and wait until ready */50while (read_mmio((uint32_t volatile *)&mailbox_regs->Status) & BCM2835_MAILBOX_FULL);51write_mmio((uint32_t volatile *)&mailbox_regs->Write, to_write);52return 0;53}
54
55uint32_t bcm2835_mailbox_read(uint32_t channel) {56uint32_t data;57
58if (channel > 15) {59return -EINVAL;60}61
62/* repeat reading if the channel was wrong */63do {64while (read_mmio((uint32_t volatile *)&mailbox_regs->Status) & BCM2835_MAILBOX_EMPTY);65data = read_mmio((uint32_t volatile *)&mailbox_regs->Read);66} while ((data & BCM2835_MAILBOX_CHANNEL_MASK) != channel);67/* return the message only (top 28 bits of the read data) */68return data & BCM2835_MAILBOX_DATA_MASK;69}
70