gint/include/gint/mpu/intc.h

300 lines
7.5 KiB
C

//---
// gint:core:intc - Interrupt Controller
//
// The interrupt controller is unwieldy because SH7705 and SH7305 have a
// completely different interface. Everything here is split up and you'll
// have to explicitly handle both to be able to use the device.
//
// gint's API provides higher-level and platform-agnostic interrupt
// management. This is probably what you are looking for.
//---
#ifndef GINT_CORE_INTC
#define GINT_CORE_INTC
#include <gint/defs/types.h>
//---
// SH7705 Interrupt Controller. Refer to:
// "Renesas SH7705 Group Hardware Manual"
// Section 6: "Interrupt Controller (INTC)"
//---
/* sh7705_intc_ipc_t - Interrupt Priority Controller
A set of 16-bit register that control the interrupt priorities. The SH7705's
IPC has its registers scattered everywhere in the memory, so there is a
pointer for each register. The SH7305 needs only one pointer for the whole
IPC because the registers are in a contiguous area. */
typedef struct
{
volatile word_union(*IPRA,
uint16_t TMU0 :4; /* Timer 0 */
uint16_t TMU1 :4; /* Timer 1 */
uint16_t TMU2 :4; /* Timer 2 */
uint16_t RTC :4; /* Real-Time Clock */
);
volatile word_union(*IPRB,
uint16_t WDT :4; /* Watchdog Timer */
uint16_t REF :4; /* BSC Refresh Request, SDRAM (?) */
uint16_t :4;
uint16_t :4;
);
volatile word_union(*IPRC,
uint16_t IRQ3 :4; /* Interrupt request 3 */
uint16_t IRQ2 :4; /* Interrupt request 2 */
uint16_t IRQ1 :4; /* Interrupt request 1 */
uint16_t IRQ0 :4; /* Interrupt request 0 */
);
volatile word_union(*IPRD,
uint16_t PINT0_7 :4; /* External interrupt pins 0 to 7 */
uint16_t PINT8_15 :4; /* External interrupt pins 8 to 15 */
uint16_t IRQ5 :4; /* Interrupt request 5 */
uint16_t IRQ4 :4; /* Interrupt request 4 */
);
volatile word_union(*IPRE,
uint16_t DMAC :4; /* Direct Memory Access Controller */
uint16_t SCIF0 :4; /* Serial Communication Interface 0 */
uint16_t SCIF2 :4; /* Serial Communication Interface 2 */
uint16_t ADC :4; /* Analog/Decimal Converter */
);
volatile word_union(*IPRF,
uint16_t :4;
uint16_t :4;
uint16_t USB :4; /* USB Controller */
uint16_t :4;
);
volatile word_union(*IPRG,
uint16_t TPU0 :4; /* Timer Pulse Unit 0 */
uint16_t TPU1 :4; /* Timer Pulse Unit 1 */
uint16_t :4;
uint16_t :4;
);
volatile word_union(*IPRH,
uint16_t TPU2 :4; /* Timer Pulse Unit 2 */
uint16_t TPU3 :4; /* Timer Pulse Unit 3 */
uint16_t :4;
uint16_t :4;
);
} GPACKED(4) sh7705_intc_ipc_t;
/* sh7705_intc_icr1_t - Interrupt Control Register 1 (general) */
typedef volatile word_union(sh7705_intc_icr1_t,
uint16_t MAI :1; /* Mask All Interrupts */
uint16_t IRQLVL :1; /* Interrupt Request Level Detect */
uint16_t BLMSK :1; /* Enable NMI when BL is set */
uint16_t :1;
uint16_t IRQ5E :2; /* IRQ 5 Edge Detection */
uint16_t IRQ4E :2; /* etc. */
uint16_t IRQ3E :2;
uint16_t IRQ2E :2;
uint16_t IRQ1E :2;
uint16_t IRQ0E :2;
);
/* sh7705_intc_t - the SH7705 interrupt controller */
typedef struct
{
/* All interrupt priority registers */
union {
sh7705_intc_ipc_t _;
volatile uint16_t *IPRS[8];
} GPACKED(4);
/* Control registers */
sh7705_intc_icr1_t *ICR1;
} GPACKED(4) sh7705_intc_t;
//---
// SH7305 Interrupt Controller. Refer to:
// "Renesas SH7724 User's Manual: Hardware"
// Section 13: "Interrupt Controller (INTC)"
//---
/* sh7305_intc_ipc_t - Interrupt Priority Controller
Some of the fields have been left unnamed because they correspond to SH7724
peripheral modules that are *very* unlikely to even exist in the SH7305, let
alone by of any use to us */
typedef volatile struct
{
word_union(IPRA,
uint16_t TMU0_0 :4; /* TMU0 Channel 0 */
uint16_t TMU0_1 :4; /* TMU0 Channel 1 */
uint16_t TMU0_2 :4; /* TMU0 Channel 2 */
uint16_t IrDA :4; /* Infrared Communication */
);
pad(2);
word_union(IPRB,
uint16_t :4;
uint16_t LCDC :4; /* LCD Controller */
uint16_t DMAC1A :4; /* Direct Memory Access Controller 1 */
uint16_t :4;
);
pad(2);
word_union(IPRC,
uint16_t TMU1_0 :4; /* TMU1 Channel 0 */
uint16_t TMU1_1 :4; /* TMU1 Channel 1 */
uint16_t TMU1_2 :4; /* TMU1 Channel 2 */
uint16_t :4;
);
pad(2);
word_union(IPRD,
uint16_t :4;
uint16_t MMCIF :4; /* MultiMedia Card Interface */
uint16_t :4;
uint16_t :4;
);
pad(2);
word_union(IPRE,
uint16_t DMAC0A :4; /* Direct Memory Access Controller 0 */
uint16_t :4;
uint16_t ETMU3 :4; /* Extra TMU 3 */
uint16_t :4;
);
pad(2);
word_union(IPRF,
uint16_t KEYSC :4; /* Key Scan Interface */
uint16_t DMACOB :4; /* DMAC0 transfer/error info */
uint16_t USB0_1 :4; /* USB controller */
uint16_t CMT :4; /* Compare Match Timer */
);
pad(2);
word_union(IPRG,
uint16_t SCIF0 :4; /* SCIF0 transfer/error info */
uint16_t ETMU1 :4; /* Extra TMU 1 */
uint16_t ETMU2 :4; /* Extra TMU 2 */
uint16_t :4;
);
pad(2);
word_union(IPRH,
uint16_t MSIOF0 :4; /* Clock-synchronized SCIF channel 0 */
uint16_t MSIOF1 :4; /* Clock-synchronized SCIF channel 1 */
uint16_t :4;
uint16_t :4;
);
pad(2);
word_union(IPRI,
uint16_t ETMU4 :4; /* Extra TMU 4 */
uint16_t :4;
uint16_t :4;
uint16_t :4;
);
pad(2);
word_union(IPRJ,
uint16_t ETMU0 :4; /* Extra TMU 0 */
uint16_t :4;
uint16_t FSI :4; /* FIFO-Buffered Serial Interface */
uint16_t SDHI1 :4; /* SD Card Host Interface channel 1 */
);
pad(2);
word_union(IPRK,
uint16_t RTC :4; /* Real-Time Clock */
uint16_t DMAC1B :4; /* DMAC1 transfer/error info */
uint16_t :4;
uint16_t SDHI0 :4; /* SD Card Host Interface channel 0 */
);
pad(2);
word_union(IPRL,
uint16_t ETMU5 :4; /* Extra TMU 5 */
uint16_t :4;
uint16_t TPU :4; /* Timer-Pulse Unit */
uint16_t :4;
);
pad(2);
} GPACKED(4) sh7305_intc_ipc_t;
/* sh7305_intc_masks_t - Interrupt mask management
Writing 1 to IMR masks interrupts; writing 1 to IMCRs clears the masks.
Writing 0 is ignored; reading from IMCRs yields undefined values */
typedef volatile struct
{
uint8_t IMR0; pad(3);
uint8_t IMR1; pad(3);
uint8_t IMR2; pad(3);
uint8_t IMR3; pad(3);
uint8_t IMR4; pad(3);
uint8_t IMR5; pad(3);
uint8_t IMR6; pad(3);
uint8_t IMR7; pad(3);
uint8_t IMR8; pad(3);
uint8_t IMR9; pad(3);
uint8_t IMR10; pad(3);
uint8_t IMR11; pad(3);
uint8_t IMR12;
} GPACKED(4) sh7305_intc_masks_t;
/* sh7305_intc_userimask_t - User Interrupt Mask
Sets the minimum required level for interrupts to be accepted.
WARNING: Writing to this register is only allowed when the upper bits of the
operand (ie. the new value of USERIMASK) are 0xa5; otherwise, the write is
ignored. To modify the value of this register, do not access the bit field
directly, backup the variable and modify it:
void set_user_imask(int new_level)
{
sh7305_intc_userimask_t mask = *(INTC._7305.USERIMASK);
mask._0xa5 = 0xa5;
mask.UIMASK = new_level & 0x0f;
*(INTC._7305.USERIMASK) = mask;
}
*/
typedef volatile lword_union(sh7305_intc_userimask_t,
uint32_t _0xa5 :8; /* Always set to 0xa5 before writing */
uint32_t :16;
uint32_t UIMASK :4; /* User Interrupt Mask Level */
uint32_t :4;
);
/* sh7305_intc_t - the SH7305 interrupt controller */
typedef struct
{
/* Interrupt priority registers */
union {
sh7305_intc_ipc_t *_;
volatile uint16_t *IPRS;
};
/* Interrupt mask & mask clear registers */
sh7305_intc_masks_t *MSK;
sh7305_intc_masks_t *MSKCLR;
/* Other registers */
sh7305_intc_userimask_t *USERIMASK;
} GPACKED(4) sh7305_intc_t;
//---
// Forward definitions
//---
/* Provided by core/gint.c */
extern sh7705_intc_t SH7705_INTC;
extern sh7305_intc_t SH7305_INTC;
#endif /* GINT_CORE_INTC */