[MAJOR] The first version of mailbox driver
DON'T USE THIS VESRION. Basic functional of mailbox realized.
This commit is contained in:
@@ -16,12 +16,12 @@
|
||||
./etc/system.conf.d/usbd minix-base
|
||||
./service/bmp085 minix-base
|
||||
./service/cat24c256 minix-base
|
||||
./service/omap_emmc minix-base
|
||||
./service/rpi_emmc minix-base
|
||||
./service/fb minix-base
|
||||
./service/gpio minix-base
|
||||
./service/i2c minix-base
|
||||
./service/lan8710a minix-base
|
||||
./service/mailbox minix-base
|
||||
./service/omap_emmc minix-base
|
||||
./service/omap_mmc minix-base
|
||||
./service/rpi_mmc minix-base
|
||||
./service/random minix-base
|
||||
|
||||
@@ -539,18 +539,6 @@ service edfictl
|
||||
ipc ALL;
|
||||
};
|
||||
|
||||
service rpi_emmc
|
||||
{
|
||||
system
|
||||
PRIVCTL
|
||||
IRQCTL
|
||||
PADCONF
|
||||
;
|
||||
irq
|
||||
52 # MMCSD1INT
|
||||
;
|
||||
};
|
||||
|
||||
service omap_emmc
|
||||
{
|
||||
system
|
||||
|
||||
@@ -98,6 +98,8 @@ PROGRAMS+= rpi_mmc
|
||||
dir.rpi_mmc:= minix/drivers/storage/mmc/rpi
|
||||
PROGRAMS+= omap_mmc
|
||||
dir.omap_mmc:= minix/drivers/storage/mmc/omap
|
||||
PROGRAMS+= mailbox
|
||||
dir.mailbox:= minix/drivers/system/mailbox
|
||||
.endif # ${MACHINE_ARCH} == "earm"
|
||||
|
||||
.if ${LDSTATIC} == "-dynamic"
|
||||
|
||||
@@ -31,6 +31,7 @@ d--755 0 0
|
||||
#ifdef __arm__
|
||||
rpi_mmc ---755 0 0 rpi_mmc
|
||||
omap_mmc ---755 0 0 omap_mmc
|
||||
mailbox ---755 0 0 mailbox
|
||||
#endif
|
||||
mfs ---755 0 0 mfs
|
||||
procfs ---755 0 0 procfs
|
||||
|
||||
@@ -6,5 +6,6 @@ SUBDIR+= gpio
|
||||
|
||||
SUBDIR+= log
|
||||
SUBDIR+= random
|
||||
SUBDIR+= mailbox
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
||||
15
minix/drivers/system/mailbox/Makefile
Normal file
15
minix/drivers/system/mailbox/Makefile
Normal file
@@ -0,0 +1,15 @@
|
||||
# Makefile for the mailbox driver.
|
||||
PROG= mailbox
|
||||
SRCS= mbox.c main.c
|
||||
|
||||
FILES=${PROG}.conf
|
||||
FILESNAME=${PROG}
|
||||
FILESDIR= /service
|
||||
|
||||
DPADD+= ${LIBCHARDRIVER} ${LIBSYS}
|
||||
LDADD+= -lchardriver -lsys
|
||||
|
||||
# This is a system driver.
|
||||
CPPFLAGS+= -D_SYSTEM=1
|
||||
|
||||
.include <minix.service.mk>
|
||||
11
minix/drivers/system/mailbox/mailbox.conf
Normal file
11
minix/drivers/system/mailbox/mailbox.conf
Normal file
@@ -0,0 +1,11 @@
|
||||
service gpio
|
||||
{
|
||||
system
|
||||
PRIVCTL # 4
|
||||
IRQCTL # 19
|
||||
;
|
||||
irq
|
||||
33
|
||||
;
|
||||
|
||||
};
|
||||
111
minix/drivers/system/mailbox/main.c
Normal file
111
minix/drivers/system/mailbox/main.c
Normal file
@@ -0,0 +1,111 @@
|
||||
#include <minix/drivers.h>
|
||||
#include <minix/chardriver.h>
|
||||
#include <minix/type.h>
|
||||
|
||||
#include "mbox.h"
|
||||
|
||||
#define NR_DEVS 1 /* number of minor devices */
|
||||
#define MAILBOX_DEV 0 /* minor device for /dev/mailbox */
|
||||
|
||||
/* SEF functions and variables. */
|
||||
static void sef_local_startup(void);
|
||||
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
|
||||
|
||||
static ssize_t m_read(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
static ssize_t m_write(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
|
||||
static int m_open(devminor_t minor, int access, endpoint_t user_endpt);
|
||||
static int m_select(devminor_t, unsigned int, endpoint_t);
|
||||
|
||||
/* Entry points to this driver. */
|
||||
static struct chardriver m_dtab = {
|
||||
.cdr_open = m_open, /* open device */
|
||||
.cdr_read = m_read, /* read from device */
|
||||
.cdr_write = m_write, /* write to device (seeding it) */
|
||||
.cdr_select = m_select, /* select hook */
|
||||
};
|
||||
|
||||
/*===========================================================================*
|
||||
* main *
|
||||
*===========================================================================*/
|
||||
int main(void)
|
||||
{
|
||||
/* SEF local startup. */
|
||||
sef_local_startup();
|
||||
|
||||
/* Call the generic receive loop. */
|
||||
chardriver_task(&m_dtab);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_local_startup *
|
||||
*===========================================================================*/
|
||||
static void sef_local_startup()
|
||||
{
|
||||
/* Register init callbacks. */
|
||||
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||||
sef_setcb_init_restart(sef_cb_init_fresh);
|
||||
|
||||
/* Let SEF perform startup. */
|
||||
sef_startup();
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_cb_init_fresh *
|
||||
*===========================================================================*/
|
||||
static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||||
{
|
||||
/* Initialize the random driver. */
|
||||
static struct k_randomness krandom;
|
||||
int i, s;
|
||||
|
||||
mailbox_init();
|
||||
|
||||
/* Announce we are up! */
|
||||
chardriver_announce();
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
static ssize_t m_read(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id)
|
||||
{
|
||||
/* Read from one of the driver's minor devices. */
|
||||
size_t offset, chunk;
|
||||
int r;
|
||||
|
||||
if (minor != MAILBOX_DEV)
|
||||
return(EIO);
|
||||
}
|
||||
|
||||
static ssize_t m_write(devminor_t minor, u64_t position, endpoint_t endpt,
|
||||
cp_grant_id_t grant, size_t size, int flags, cdev_id_t id)
|
||||
{
|
||||
/* Write to one of the driver's minor devices. */
|
||||
size_t offset, chunk;
|
||||
int r;
|
||||
|
||||
if (minor != MAILBOX_DEV)
|
||||
return(EIO);
|
||||
}
|
||||
|
||||
static int m_open(devminor_t minor, int access, endpoint_t user_endpt)
|
||||
{
|
||||
if (minor < 0 || minor >= NR_DEVS)
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
static int m_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
|
||||
{
|
||||
/* mailbox device is always writable; it's infinitely readable
|
||||
* once seeded, and doesn't block when it's not, so all operations
|
||||
* are instantly possible. we ignore CDEV_OP_ERR.
|
||||
*/
|
||||
int ready_ops = 0;
|
||||
if (minor != MAILBOX_DEV)
|
||||
return(EIO);
|
||||
return ops & (CDEV_OP_RD | CDEV_OP_WR);
|
||||
}
|
||||
110
minix/drivers/system/mailbox/mbox.c
Normal file
110
minix/drivers/system/mailbox/mbox.c
Normal file
@@ -0,0 +1,110 @@
|
||||
#include <minix/drivers.h>
|
||||
#include <minix/chardriver.h>
|
||||
#include <minix/type.h>
|
||||
#include <minix/log.h>
|
||||
#include <minix/vm.h>
|
||||
#include <minix/spin.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "mbox.h"
|
||||
|
||||
struct mailbox_t mailbox = {
|
||||
.read = 0x00,
|
||||
.res1 = 0x04,
|
||||
.res2 = 0x08,
|
||||
.res3 = 0x0c,
|
||||
.peek = 0x10,
|
||||
.sender = 0x14,
|
||||
.status = 0x18,
|
||||
.config = 0x1c,
|
||||
.write = 0x20
|
||||
};
|
||||
|
||||
struct mailbox_t *gmailbox;
|
||||
|
||||
uint32_t mbox_base;
|
||||
/*
|
||||
* Define a structure to be used for logging
|
||||
*/
|
||||
static struct log log = {
|
||||
.name = "mailbox",
|
||||
.log_level = LEVEL_INFO,
|
||||
.log_func = default_log
|
||||
};
|
||||
|
||||
static void write32(vir_bytes reg, uint32_t data)
|
||||
{
|
||||
assert(reg >= 0 && reg <= sizeof (struct mailbox_t));
|
||||
uint32_t addr = mbox_base + reg;
|
||||
addr = data;
|
||||
}
|
||||
|
||||
static uint32_t read32(vir_bytes reg)
|
||||
{
|
||||
assert(reg >= 0 && reg <= sizeof (struct mailbox_t));
|
||||
return mbox_base + reg;
|
||||
}
|
||||
|
||||
void mailbox_init()
|
||||
{
|
||||
uint32_t value;
|
||||
value = 0;
|
||||
struct minix_mem_range mr;
|
||||
|
||||
mr.mr_base = MBOX_BASE;
|
||||
mr.mr_limit = MBOX_BASE + sizeof (struct mailbox_t);
|
||||
|
||||
/* grant ourself rights to map the register memory */
|
||||
if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
|
||||
panic("Unable to request permission to map memory");
|
||||
}
|
||||
|
||||
/* Set the base address to use */
|
||||
mbox_base =
|
||||
(uint32_t) vm_map_phys(SELF, (void *) MBOX_BASE,
|
||||
sizeof (struct mailbox_t));
|
||||
|
||||
if (mbox_base == (uint32_t) MAP_FAILED)
|
||||
panic("Unable to map MMC memory");
|
||||
|
||||
gmailbox = &mailbox;
|
||||
}
|
||||
|
||||
uint32_t mbox_read(uint8_t chan)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
while (1) {
|
||||
while (read32(gmailbox->status) & MAILBOX_EMPTY) {
|
||||
log_debug(&log, "status: 0x%x\n", read32(gmailbox->status));
|
||||
//mem barrier
|
||||
}
|
||||
data = read32(gmailbox->read);
|
||||
|
||||
log_debug(&log, "received data %d\n", data);
|
||||
|
||||
if (((uint8_t) data & 0xf) == chan) {
|
||||
return (data & ~0xf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mbox_write(uint8_t chan, uint32_t data)
|
||||
{
|
||||
while (read32(gmailbox->status) & MAILBOX_FULL) ;
|
||||
|
||||
write32(gmailbox->write, (data & ~0xf) | (uint32_t) (chan & 0xf));
|
||||
}
|
||||
|
||||
void mbox_flush(void)
|
||||
{
|
||||
spin_t spin;
|
||||
while (!(read32(gmailbox->status) & MAILBOX_EMPTY)) {
|
||||
spin_init(&spin, 20000);
|
||||
while (1) {
|
||||
if(spin_check(&spin) == FALSE)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
139
minix/drivers/system/mailbox/mbox.h
Normal file
139
minix/drivers/system/mailbox/mbox.h
Normal file
@@ -0,0 +1,139 @@
|
||||
#ifndef _MBOX_H_
|
||||
#define _MBOX_H_
|
||||
|
||||
#define MBOX_BASE (0x3f000000 + 0xb880)
|
||||
|
||||
struct mailbox_t {
|
||||
vir_bytes read;
|
||||
vir_bytes res1;
|
||||
vir_bytes res2;
|
||||
vir_bytes res3;
|
||||
vir_bytes peek;
|
||||
vir_bytes sender;
|
||||
vir_bytes status;
|
||||
vir_bytes config;
|
||||
vir_bytes write;
|
||||
};
|
||||
|
||||
enum mail_chan {
|
||||
MBOX_POWER,
|
||||
MBOX_FRAMEBUFFER,
|
||||
MBOX_UART,
|
||||
MBOX_VCHIQ,
|
||||
MBOX_LEDS,
|
||||
MBOX_BUTTONS,
|
||||
MBOX_TOUCH,
|
||||
MBOX_NUSED,
|
||||
MBOX_PROP,
|
||||
MBOX_REVPROP
|
||||
};
|
||||
|
||||
void mailbox_init();
|
||||
|
||||
uint32_t mbox_read(uint8_t chan);
|
||||
|
||||
void mbox_write(uint8_t chan, uint32_t data);
|
||||
|
||||
void mbox_flush();
|
||||
|
||||
|
||||
#define MAILBOX_FULL 0x80000000
|
||||
#define MAILBOX_EMPTY 0x40000000
|
||||
#define MBX_TAG_GET_BOARD_MODEL 0x00010001
|
||||
#define MBX_TAG_GET_BOARD_REVISION 0x00010002
|
||||
|
||||
// Timers interrupt control registers
|
||||
#define CORE0_TIMER_IRQCNTL 0x40000040
|
||||
#define CORE1_TIMER_IRQCNTL 0x40000044
|
||||
#define CORE2_TIMER_IRQCNTL 0x40000048
|
||||
#define CORE3_TIMER_IRQCNTL 0x4000004C
|
||||
|
||||
// Where to route timer interrupt to, IRQ/FIQ
|
||||
// Setting both the IRQ and FIQ bit gives an FIQ
|
||||
#define TIMER0_IRQ 0x01
|
||||
#define TIMER1_IRQ 0x02
|
||||
#define TIMER2_IRQ 0x04
|
||||
#define TIMER3_IRQ 0x08
|
||||
#define TIMER0_FIQ 0x10
|
||||
#define TIMER1_FIQ 0x20
|
||||
#define TIMER2_FIQ 0x40
|
||||
#define TIMER3_FIQ 0x80
|
||||
|
||||
// Mailbox interrupt control registers
|
||||
#define CORE0_MBOX_IRQCNTL 0x40000050
|
||||
#define CORE1_MBOX_IRQCNTL 0x40000054
|
||||
#define CORE2_MBOX_IRQCNTL 0x40000058
|
||||
#define CORE3_MBOX_IRQCNTL 0x4000005C
|
||||
|
||||
// Where to route mailbox interrupt to, IRQ/FIQ
|
||||
// Setting both the IRQ and FIQ bit gives an FIQ
|
||||
#define MBOX0_IRQ 0x01
|
||||
#define MBOX1_IRQ 0x02
|
||||
#define MBOX2_IRQ 0x04
|
||||
#define MBOX3_IRQ 0x08
|
||||
#define MBOX0_FIQ 0x10
|
||||
#define MBOX1_FIQ 0x20
|
||||
#define MBOX2_FIQ 0x40
|
||||
#define MBOX3_FIQ 0x80
|
||||
|
||||
// IRQ & FIQ
|
||||
#define CORE0_IRQ_SOURCE 0x40000060
|
||||
#define CORE1_IRQ_SOURCE 0x40000064
|
||||
#define CORE2_IRQ_SOURCE 0x40000068
|
||||
#define CORE3_IRQ_SOURCE 0x4000006C
|
||||
#define CORE0_FIQ_SOURCE 0x40000070
|
||||
#define CORE1_FIQ_SOURCE 0x40000074
|
||||
#define CORE2_FIQ_SOURCE 0x40000078
|
||||
#define CORE3_FIQ_SOURCE 0x4000007C
|
||||
|
||||
// Interrupt source bits
|
||||
// IRQ and FIQ are the same
|
||||
// GPU bits can be set
|
||||
#define INT_SRC_TIMER0 0x00000001
|
||||
#define INT_SRC_TIMER1 0x00000002
|
||||
#define INT_SRC_TIMER2 0x00000004
|
||||
#define INT_SRC_TIMER3 0x00000008
|
||||
#define INT_SRC_MBOX0 0x00000010
|
||||
#define INT_SRC_MBOX1 0x00000020
|
||||
#define INT_SRC_MBOX2 0x00000040
|
||||
#define INT_SRC_MBOX3 0x00000080
|
||||
#define INT_SRC_GPU 0x00000100
|
||||
#define INT_SRC_PMU 0x00000200
|
||||
|
||||
// Mailbox write
|
||||
#define CORE0_MBOX0_SET 0x40000080
|
||||
#define CORE0_MBOX1_SET 0x40000084
|
||||
#define CORE0_MBOX2_SET 0x40000088
|
||||
#define CORE0_MBOX3_SET 0x4000008C
|
||||
#define CORE1_MBOX0_SET 0x40000090
|
||||
#define CORE1_MBOX1_SET 0x40000094
|
||||
#define CORE1_MBOX2_SET 0x40000098
|
||||
#define CORE1_MBOX3_SET 0x4000009C
|
||||
#define CORE2_MBOX0_SET 0x400000A0
|
||||
#define CORE2_MBOX1_SET 0x400000A4
|
||||
#define CORE2_MBOX2_SET 0x400000A8
|
||||
#define CORE2_MBOX3_SET 0x400000AC
|
||||
#define CORE3_MBOX0_SET 0x400000B0
|
||||
#define CORE3_MBOX1_SET 0x400000B4
|
||||
#define CORE3_MBOX2_SET 0x400000B8
|
||||
#define CORE3_MBOX3_SET 0x400000BC
|
||||
|
||||
// Mailbox write (Read & Write)
|
||||
#define CORE0_MBOX0_RDCLR 0x400000C0
|
||||
#define CORE0_MBOX1_RDCLR 0x400000C4
|
||||
#define CORE0_MBOX2_RDCLR 0x400000C8
|
||||
#define CORE0_MBOX3_RDCLR 0x400000CC
|
||||
#define CORE1_MBOX0_RDCLR 0x400000D0
|
||||
#define CORE1_MBOX1_RDCLR 0x400000D4
|
||||
#define CORE1_MBOX2_RDCLR 0x400000D8
|
||||
#define CORE1_MBOX3_RDCLR 0x400000DC
|
||||
#define CORE2_MBOX0_RDCLR 0x400000E0
|
||||
#define CORE2_MBOX1_RDCLR 0x400000E4
|
||||
#define CORE2_MBOX2_RDCLR 0x400000E8
|
||||
#define CORE2_MBOX3_RDCLR 0x400000EC
|
||||
#define CORE3_MBOX0_RDCLR 0x400000F0
|
||||
#define CORE3_MBOX1_RDCLR 0x400000F4
|
||||
#define CORE3_MBOX2_RDCLR 0x400000F8
|
||||
#define CORE3_MBOX3_RDCLR 0x400000FC
|
||||
|
||||
#endif /* _MBOX_H_ */
|
||||
Reference in New Issue
Block a user