#pragma once
#include <stdint.h>
struct vim
{
uint32_t irqindex;
uint32_t fiqindex;
uint32_t padding0[2];
uint32_t firqpr[4];
uint32_t intreq[4];
uint32_t reqenaset[4];
uint32_t reqenaclr[4];
uint32_t wakeenaset[4];
uint32_t wakeenaclr[4];
void (*irqvecreg)(void);
void (*fiqvecreg)(void);
uint32_t capevt;
uint32_t : 32;
uint32_t chanctrl[32];
};
struct vim_parity
{
uint32_t padding0[59];
uint32_t parflg;
uint32_t parctl;
uint32_t adderr;
void (*fbparerr)(void);
};
#define VIM_NUM_CHANNELS 127
struct vim_table
{
void (*phantom)(void);
void (*channel[VIM_NUM_CHANNELS])(void);
};
#define VIM_BASE 0xFFFFFE00UL
static volatile struct vim *const VIM = (volatile struct vim *)VIM_BASE;
static volatile struct vim_parity *const VIM_PARITY =
(volatile struct vim_parity *)0xFFFFFD00UL;
static volatile struct vim_table *const VIM_TABLE =
(volatile struct vim_table *)0xFFF82000UL;
#define VIM_PARCTL_ENABLE (UINT32_C(0xA))
static inline void vim_enable(uint32_t channel)
{
VIM->reqenaset[channel / 32] = UINT32_C(1) << (channel % 32);
}
static inline void vim_disable(uint32_t channel)
{
VIM->reqenaclr[channel / 32] = UINT32_C(1) << (channel % 32);
}
static inline void vim_clear(uint32_t channel)
{
VIM->intreq[channel / 32] = UINT32_C(1) << (channel % 32);
}
static inline void vim_set_req(uint32_t channel, uint32_t req)
{
const uint32_t reg = channel / 4;
const uint32_t shift = (3 - (channel % 4)) * 8;
const uint32_t mask = UINT32_C(0xFF) << shift;
VIM->chanctrl[reg] = ((VIM->chanctrl[reg] & ~mask) | (req << shift));
}
static inline void vim_set_is_fiq(uint32_t channel)
{
VIM->firqpr[channel / 32] |= UINT32_C(1) << (channel % 32);
}
static inline void vim_clear_is_fiq(uint32_t channel)
{
VIM->firqpr[channel / 32] &= ~(UINT32_C(1) << (channel % 32));
}
static inline void vim_set_phantom_handler(void (*handler)(void))
{
VIM_TABLE->phantom = handler;
}
static inline void vim_set_handler(uint32_t channel, void (*handler)(void))
{
VIM_TABLE->channel[channel] = handler;
}
static inline void vim_channel_init(uint32_t channel, uint32_t req,
void (*handler)(void))
{
vim_set_req(channel, req);
vim_set_handler(channel, handler);
vim_enable(channel);
}