diff --git a/libboard_zynq/src/gic.rs b/libboard_zynq/src/gic.rs new file mode 100644 index 0000000..2ae68e3 --- /dev/null +++ b/libboard_zynq/src/gic.rs @@ -0,0 +1,74 @@ +//! ARM Generic Interrupt Controller + +use bit_field::BitField; +use libregister::{RegisterW, RegisterRW}; +use super::mpcore; + +#[derive(Debug, Clone, Copy)] +pub struct InterruptId(u8); + +#[derive(Debug, Clone, Copy)] +pub enum InterruptSensitivity { + Level, + Edge, +} + +pub struct InterruptController { + mpcore: mpcore::RegisterBlock, +} + +impl InterruptController { + pub fn new(mpcore: mpcore::RegisterBlock) -> Self { + InterruptController { mpcore } + } + + pub fn disable_interrupts(&mut self) { + self.mpcore.iccicr.modify(|_, w| w.enable_ns(false) + .enable_s(false)); + self.mpcore.icddcr.modify(|_, w| w.enable_secure(false) + .enable_non_secure(false)); + } + + /// enable interrupt signaling + pub fn enable_interrupts(&mut self) { + self.mpcore.iccicr.modify(|_, w| w.enable_ns(true) + .enable_s(true)); + self.mpcore.icddcr.modify(|_, w| w.enable_secure(true)); + } + + pub fn enable(&mut self, id: InterruptId, target_cpu: u32, sensitivity: InterruptSensitivity) { + assert!(target_cpu < 2); + + self.disable_interrupts(); + + // enable + let m = (id.0 >> 5) as usize; + let n = (id.0 & 0x1F) as usize; + assert!(m < 3); + unsafe { + self.mpcore.icdiser[m].modify(|mut icdiser| *icdiser.set_bit(n, true)); + } + + // target cpu + let m = (id.0 >> 2) as usize; + let n = (8 * (id.0 & 3)) as usize; + unsafe { + self.mpcore.icdiptr[m].modify(|mut icdiptr| *icdiptr.set_bits(n..=n+1, target_cpu + 1)); + } + + // sensitivity + let m = (id.0 >> 4) as usize; + let n = (2 * (id.0 & 0xF)) as usize; + unsafe { + self.mpcore.icdicfr[m].modify(|mut icdicfr| *icdicfr.set_bits(n..=n+1, match sensitivity { + InterruptSensitivity::Level => 0b00, + InterruptSensitivity::Edge => 0b10, + })); + } + + // filter no interrupts (lowest priority) + self.mpcore.iccpmr.write(mpcore::ICCPMR::zeroed().priority(0xFF)); + + self.enable_interrupts(); + } +} diff --git a/libboard_zynq/src/lib.rs b/libboard_zynq/src/lib.rs index 04f7d8b..43494cc 100644 --- a/libboard_zynq/src/lib.rs +++ b/libboard_zynq/src/lib.rs @@ -15,6 +15,7 @@ pub mod axi_hp; pub mod axi_gp; pub mod ddr; pub mod mpcore; +pub mod gic; pub mod flash; pub mod time; pub mod timer; diff --git a/libboard_zynq/src/mpcore.rs b/libboard_zynq/src/mpcore.rs index 356f225..68ce472 100644 --- a/libboard_zynq/src/mpcore.rs +++ b/libboard_zynq/src/mpcore.rs @@ -93,12 +93,8 @@ pub struct RegisterBlock { pub icdisr1: RW, pub icdisr2: RW, unused8: [u32; 29], - /// Interrupt Set-enable Register 0 - pub icdiser0: RW, - /// Interrupt Set-enable Register 1 - pub icdiser1: RW, - /// Interrupt Set-enable Register 2 - pub icdiser2: RW, + /// Interrupt Set-enable Registers + pub icdiser: [RW; 3], unused9: [u32; 29], /// Interrupt Clear-Enable Register 0 pub icdicer0: RW, @@ -148,67 +144,11 @@ pub struct RegisterBlock { pub icdipr22: RW, pub icdipr23: RW, unused14: [u32; 232], - /// Interrupt Processor Targets Register 0 - pub icdiptr0: ICDIPTR0, - /// Interrupt Processor Targets Register 1 - pub icdiptr1: ICDIPTR1, - /// Interrupt Processor Targets Register 2 - pub icdiptr2: ICDIPTR2, - /// Interrupt Processor Targets Register 3 - pub icdiptr3: ICDIPTR3, - /// Interrupt Processor Targets Register 4 - pub icdiptr4: RW, - /// Interrupt Processor Targets Register 5 - pub icdiptr5: RO, - /// Interrupt Processor Targets Register 6 - pub icdiptr6: ICDIPTR6, - /// Interrupt Processor Targets Register 7 - pub icdiptr7: ICDIPTR7, - /// Interrupt Processor Targets Register 8 - pub icdiptr8: ICDIPTR8, - /// Interrupt Processor Targets Register 9 - pub icdiptr9: ICDIPTR9, - /// Interrupt Processor Targets Register 10 - pub icdiptr10: ICDIPTR10, - /// Interrupt Processor Targets Register 11 - pub icdiptr11: ICDIPTR11, - /// Interrupt Processor Targets Register 12 - pub icdiptr12: ICDIPTR12, - /// Interrupt Processor Targets Register 13 - pub icdiptr13: ICDIPTR13, - /// Interrupt Processor Targets Register 14 - pub icdiptr14: ICDIPTR14, - /// Interrupt Processor Targets Register 15 - pub icdiptr15: ICDIPTR15, - /// Interrupt Processor Targets Register 16 - pub icdiptr16: ICDIPTR16, - /// Interrupt Processor Targets Register 17 - pub icdiptr17: ICDIPTR17, - /// Interrupt Processor Targets Register 18 - pub icdiptr18: ICDIPTR18, - /// Interrupt Processor Targets Register 19 - pub icdiptr19: ICDIPTR19, - /// Interrupt Processor Targets Register 20 - pub icdiptr20: ICDIPTR20, - /// Interrupt Processor Targets Register 21 - pub icdiptr21: ICDIPTR21, - /// Interrupt Processor Targets Register 22 - pub icdiptr22: ICDIPTR22, - /// Interrupt Processor Targets Register 23 - pub icdiptr23: ICDIPTR23, + /// Interrupt Processor Targets Registers + pub icdiptr: [RW; 24], unused15: [u32; 232], - /// Interrupt Configuration Register 0 - pub icdicfr0: ICDICFR0, - /// Interrupt Configuration Register 1 - pub icdicfr1: ICDICFR1, - /// Interrupt Configuration Register 2 - pub icdicfr2: ICDICFR2, - /// Interrupt Configuration Register 3 - pub icdicfr3: ICDICFR3, - /// Interrupt Configuration Register 4 - pub icdicfr4: ICDICFR4, - /// Interrupt Configuration Register 5 - pub icdicfr5: ICDICFR5, + /// Interrupt Configuration Registers + pub icdicfr: [RW; 6], unused16: [u32; 58], /// PPI Status Register pub ppi_status: PpiStatus, @@ -391,232 +331,6 @@ register_bits!(icdiidr, implementation_version, u8, 24, 31); register_bits!(icdiidr, revision_number, u32, 12, 23); register_bits!(icdiidr, implementer, u32, 0, 11); -register!(icdipt_r0, ICDIPTR0, RO, u32); -register_bits!(icdipt_r0, target_3, u8, 24, 25); -register_bits!(icdipt_r0, target_2, u8, 16, 17); -register_bits!(icdipt_r0, target_1, u8, 8, 9); -register_bits!(icdipt_r0, target_0, u8, 0, 1); - -register!(icdipt_r1, ICDIPTR1, RO, u32); -register_bits!(icdipt_r1, target_7, u8, 24, 25); -register_bits!(icdipt_r1, target_6, u8, 16, 17); -register_bits!(icdipt_r1, target_5, u8, 8, 9); -register_bits!(icdipt_r1, target_4, u8, 0, 1); - -register!(icdipt_r2, ICDIPTR2, RO, u32); -register_bits!(icdipt_r2, target_11, u8, 24, 25); -register_bits!(icdipt_r2, target_10, u8, 16, 17); -register_bits!(icdipt_r2, target_9, u8, 8, 9); -register_bits!(icdipt_r2, target_8, u8, 0, 1); - -register!(icdipt_r3, ICDIPTR3, RO, u32); -register_bits!(icdipt_r3, target_15, u8, 24, 25); -register_bits!(icdipt_r3, target_14, u8, 16, 17); -register_bits!(icdipt_r3, target_13, u8, 8, 9); -register_bits!(icdipt_r3, target_12, u8, 0, 1); - -register!(icdipt_r6, ICDIPTR6, RO, u32); -register_bits!(icdipt_r6, target_27, u8, 24, 25); - -register!(icdipt_r7, ICDIPTR7, RO, u32); -register_bits!(icdipt_r7, target_31, u8, 24, 25); -register_bits!(icdipt_r7, target_30, u8, 16, 17); -register_bits!(icdipt_r7, target_29, u8, 8, 9); -register_bits!(icdipt_r7, target_28, u8, 0, 1); - -register!(icdipt_r8, ICDIPTR8, RW, u32); -register_bits!(icdipt_r8, target_35, u8, 24, 25); -register_bits!(icdipt_r8, target_34, u8, 16, 17); -register_bits!(icdipt_r8, target_33, u8, 8, 9); -register_bits!(icdipt_r8, target_32, u8, 0, 1); - -register!(icdipt_r9, ICDIPTR9, RW, u32); -register_bits!(icdipt_r9, target_39, u8, 24, 25); -register_bits!(icdipt_r9, target_38, u8, 16, 17); -register_bits!(icdipt_r9, target_37, u8, 8, 9); -register_bits!(icdipt_r9, target_36, u8, 0, 1); - -register!(icdipt_r10, ICDIPTR10, RW, u32); -register_bits!(icdipt_r10, target_43, u8, 24, 25); -register_bits!(icdipt_r10, target_42, u8, 16, 17); -register_bits!(icdipt_r10, target_41, u8, 8, 9); -register_bits!(icdipt_r10, target_40, u8, 0, 1); - -register!(icdipt_r11, ICDIPTR11, RW, u32); -register_bits!(icdipt_r11, target_47, u8, 24, 25); -register_bits!(icdipt_r11, target_46, u8, 16, 17); -register_bits!(icdipt_r11, target_45, u8, 8, 9); -register_bits!(icdipt_r11, target_44, u8, 0, 1); - -register!(icdipt_r12, ICDIPTR12, RW, u32); -register_bits!(icdipt_r12, target_51, u8, 24, 25); -register_bits!(icdipt_r12, target_50, u8, 16, 17); -register_bits!(icdipt_r12, target_49, u8, 8, 9); -register_bits!(icdipt_r12, target_48, u8, 0, 1); - -register!(icdipt_r13, ICDIPTR13, RW, u32); -register_bits!(icdipt_r13, target_55, u8, 24, 25); -register_bits!(icdipt_r13, target_54, u8, 16, 17); -register_bits!(icdipt_r13, target_53, u8, 8, 9); -register_bits!(icdipt_r13, target_52, u8, 0, 1); - -register!(icdipt_r14, ICDIPTR14, RW, u32); -register_bits!(icdipt_r14, target_59, u8, 24, 25); -register_bits!(icdipt_r14, target_58, u8, 16, 17); -register_bits!(icdipt_r14, target_57, u8, 8, 9); -register_bits!(icdipt_r14, target_56, u8, 0, 1); - -register!(icdipt_r15, ICDIPTR15, RW, u32); -register_bits!(icdipt_r15, target_63, u8, 24, 25); -register_bits!(icdipt_r15, target_62, u8, 16, 17); -register_bits!(icdipt_r15, target_61, u8, 8, 9); -register_bits!(icdipt_r15, target_60, u8, 0, 1); - -register!(icdipt_r16, ICDIPTR16, RW, u32); -register_bits!(icdipt_r16, target_67, u8, 24, 25); -register_bits!(icdipt_r16, target_66, u8, 16, 17); -register_bits!(icdipt_r16, target_65, u8, 8, 9); -register_bits!(icdipt_r16, target_64, u8, 0, 1); - -register!(icdipt_r17, ICDIPTR17, RW, u32); -register_bits!(icdipt_r17, target_71, u8, 24, 25); -register_bits!(icdipt_r17, target_70, u8, 16, 17); -register_bits!(icdipt_r17, target_69, u8, 8, 9); -register_bits!(icdipt_r17, target_68, u8, 0, 1); - -register!(icdipt_r18, ICDIPTR18, RW, u32); -register_bits!(icdipt_r18, target_75, u8, 24, 25); -register_bits!(icdipt_r18, target_74, u8, 16, 17); -register_bits!(icdipt_r18, target_73, u8, 8, 9); -register_bits!(icdipt_r18, target_72, u8, 0, 1); - -register!(icdipt_r19, ICDIPTR19, RW, u32); -register_bits!(icdipt_r19, target_79, u8, 24, 25); -register_bits!(icdipt_r19, target_78, u8, 16, 17); -register_bits!(icdipt_r19, target_77, u8, 8, 9); -register_bits!(icdipt_r19, target_76, u8, 0, 1); - -register!(icdipt_r20, ICDIPTR20, RW, u32); -register_bits!(icdipt_r20, target_83, u8, 24, 25); -register_bits!(icdipt_r20, target_82, u8, 16, 17); -register_bits!(icdipt_r20, target_81, u8, 8, 9); -register_bits!(icdipt_r20, target_80, u8, 0, 1); - -register!(icdipt_r21, ICDIPTR21, RW, u32); -register_bits!(icdipt_r21, target_87, u8, 24, 25); -register_bits!(icdipt_r21, target_86, u8, 16, 17); -register_bits!(icdipt_r21, target_85, u8, 8, 9); -register_bits!(icdipt_r21, target_84, u8, 0, 1); - -register!(icdipt_r22, ICDIPTR22, RW, u32); -register_bits!(icdipt_r22, target_91, u8, 24, 25); -register_bits!(icdipt_r22, target_90, u8, 16, 17); -register_bits!(icdipt_r22, target_89, u8, 8, 9); -register_bits!(icdipt_r22, target_88, u8, 0, 1); - -register!(icdipt_r23, ICDIPTR23, RW, u32); -register_bits!(icdipt_r23, target_95, u8, 24, 25); -register_bits!(icdipt_r23, target_94, u8, 16, 17); -register_bits!(icdipt_r23, target_93, u8, 8, 9); -register_bits!(icdipt_r23, target_92, u8, 0, 1); - -register!(icdicf_r0, ICDICFR0, RO, u32); -register_bits!(icdicf_r0, config_15, u8, 30, 31); -register_bits!(icdicf_r0, config_14, u8, 28, 29); -register_bits!(icdicf_r0, config_13, u8, 26, 27); -register_bits!(icdicf_r0, config_12, u8, 24, 25); -register_bits!(icdicf_r0, config_11, u8, 22, 23); -register_bits!(icdicf_r0, config_10, u8, 20, 21); -register_bits!(icdicf_r0, config_9, u8, 18, 19); -register_bits!(icdicf_r0, config_8, u8, 16, 17); -register_bits!(icdicf_r0, config_7, u8, 14, 15); -register_bits!(icdicf_r0, config_6, u8, 12, 13); -register_bits!(icdicf_r0, config_5, u8, 10, 11); -register_bits!(icdicf_r0, config_4, u8, 8, 9); -register_bits!(icdicf_r0, config_3, u8, 6, 7); -register_bits!(icdicf_r0, config_2, u8, 4, 5); -register_bits!(icdicf_r0, config_1, u8, 2, 3); -register_bits!(icdicf_r0, config_0, u8, 0, 1); - -register!(icdicf_r1, ICDICFR1, RW, u32); -register_bits!(icdicf_r1, config_31, u8, 30, 31); -register_bits!(icdicf_r1, config_30, u8, 28, 29); -register_bits!(icdicf_r1, config_29, u8, 26, 27); -register_bits!(icdicf_r1, config_28, u8, 24, 25); -register_bits!(icdicf_r1, config_27, u8, 22, 23); - -register!(icdicf_r2, ICDICFR2, RW, u32); -register_bits!(icdicf_r2, config_47, u8, 30, 31); -register_bits!(icdicf_r2, config_46, u8, 28, 29); -register_bits!(icdicf_r2, config_45, u8, 26, 27); -register_bits!(icdicf_r2, config_44, u8, 24, 25); -register_bits!(icdicf_r2, config_43, u8, 22, 23); -register_bits!(icdicf_r2, config_42, u8, 20, 21); -register_bits!(icdicf_r2, config_41, u8, 18, 19); -register_bits!(icdicf_r2, config_40, u8, 16, 17); -register_bits!(icdicf_r2, config_39, u8, 14, 15); -register_bits!(icdicf_r2, config_38, u8, 12, 13); -register_bits!(icdicf_r2, config_37, u8, 10, 11); -register_bits!(icdicf_r2, config_36, u8, 8, 9); -register_bits!(icdicf_r2, config_35, u8, 6, 7); -register_bits!(icdicf_r2, config_34, u8, 4, 5); -register_bits!(icdicf_r2, config_33, u8, 2, 3); -register_bits!(icdicf_r2, config_32, u8, 0, 1); - -register!(icdicf_r3, ICDICFR3, RW, u32); -register_bits!(icdicf_r3, config_63, u8, 30, 31); -register_bits!(icdicf_r3, config_62, u8, 28, 29); -register_bits!(icdicf_r3, config_61, u8, 26, 27); -register_bits!(icdicf_r3, config_60, u8, 24, 25); -register_bits!(icdicf_r3, config_59, u8, 22, 23); -register_bits!(icdicf_r3, config_58, u8, 20, 21); -register_bits!(icdicf_r3, config_57, u8, 18, 19); -register_bits!(icdicf_r3, config_56, u8, 16, 17); -register_bits!(icdicf_r3, config_55, u8, 14, 15); -register_bits!(icdicf_r3, config_54, u8, 12, 13); -register_bits!(icdicf_r3, config_53, u8, 10, 11); -register_bits!(icdicf_r3, config_52, u8, 8, 9); -register_bits!(icdicf_r3, config_51, u8, 6, 7); -register_bits!(icdicf_r3, config_50, u8, 4, 5); -register_bits!(icdicf_r3, config_49, u8, 2, 3); -register_bits!(icdicf_r3, config_48, u8, 0, 1); - -register!(icdicf_r4, ICDICFR4, RW, u32); -register_bits!(icdicf_r4, config_79, u8, 30, 31); -register_bits!(icdicf_r4, config_78, u8, 28, 29); -register_bits!(icdicf_r4, config_77, u8, 26, 27); -register_bits!(icdicf_r4, config_76, u8, 24, 25); -register_bits!(icdicf_r4, config_75, u8, 22, 23); -register_bits!(icdicf_r4, config_74, u8, 20, 21); -register_bits!(icdicf_r4, config_73, u8, 18, 19); -register_bits!(icdicf_r4, config_72, u8, 16, 17); -register_bits!(icdicf_r4, config_71, u8, 14, 15); -register_bits!(icdicf_r4, config_70, u8, 12, 13); -register_bits!(icdicf_r4, config_69, u8, 10, 11); -register_bits!(icdicf_r4, config_68, u8, 8, 9); -register_bits!(icdicf_r4, config_67, u8, 6, 7); -register_bits!(icdicf_r4, config_66, u8, 4, 5); -register_bits!(icdicf_r4, config_65, u8, 2, 3); -register_bits!(icdicf_r4, config_64, u8, 0, 1); - -register!(icdicf_r5, ICDICFR5, RW, u32); -register_bits!(icdicf_r5, config_95, u8, 30, 31); -register_bits!(icdicf_r5, config_94, u8, 28, 29); -register_bits!(icdicf_r5, config_93, u8, 26, 27); -register_bits!(icdicf_r5, config_92, u8, 24, 25); -register_bits!(icdicf_r5, config_91, u8, 22, 23); -register_bits!(icdicf_r5, config_90, u8, 20, 21); -register_bits!(icdicf_r5, config_89, u8, 18, 19); -register_bits!(icdicf_r5, config_88, u8, 16, 17); -register_bits!(icdicf_r5, config_87, u8, 14, 15); -register_bits!(icdicf_r5, config_86, u8, 12, 13); -register_bits!(icdicf_r5, config_85, u8, 10, 11); -register_bits!(icdicf_r5, config_84, u8, 8, 9); -register_bits!(icdicf_r5, config_83, u8, 6, 7); -register_bits!(icdicf_r5, config_82, u8, 4, 5); -register_bits!(icdicf_r5, config_81, u8, 2, 3); -register_bits!(icdicf_r5, config_80, u8, 0, 1); - register!(ppi_status, PpiStatus, RO, u32); register_bits!(ppi_status, ppi_status, u8, 11, 15); register_bits!(ppi_status, sbz, u32, 0, 10);