Fix Rocket Chip serial interrupt

master
Jiajie Chen 6 years ago
parent 2fb09109bb
commit 2e599b0bab

@ -75,7 +75,7 @@ board := raspi3
need_bootloader := true
endif
# currently only mipsel architecture and rocket-chip needs DTB linked to the kernel
# currently only mipsel architecture and rocket-chip need DTB linked to the kernel
ifeq ($(arch), mipsel)
dtb := src/arch/$(arch)/board/$(board)/device.dtb
endif

@ -91,16 +91,16 @@
serial0: serial@60000000 {
compatible = "xlnx,xps-uartlite-1.00.a";
reg = <0x0 0x6000000 0x1000>;
interrupt-parent = <&L10>;
reg = <0x6000000 0x1000>;
interrupt-parent = <&axi_intc>;
interrupts = <1>;
};
serial_net: serial@60010000 {
compatible = "xlnx,xps-uartlite-1.00.a";
reg = <0x0 0x60010000 0x1000>;
axi_intc: axi_intc@61200000 {
compatible = "xlnx,xps-intc-1.00.a";
reg = <0x61200000 0x1000>;
interrupt-parent = <&L10>;
interrupts = <2>;
interrupts = <1>;
};
};
L9: rom@10000 {

@ -4,15 +4,43 @@ use super::consts::KERNEL_OFFSET;
pub unsafe fn init_external_interrupt() {
const HART0_S_MODE_INTERRUPT_ENABLES: *mut u64 = (KERNEL_OFFSET + 0x0C00_2080) as *mut u64;
HART0_S_MODE_INTERRUPT_ENABLES.write_volatile(0xf);
// mask interrupts first
const AXI_INTC_IER: *mut u32 = (KERNEL_OFFSET + 0x1900_0008) as *mut u32;
AXI_INTC_IER.write_volatile(0x0);
// acknowledge all interrupts
const AXI_INTC_IAR: *mut u32 = (KERNEL_OFFSET + 0x1900_000C) as *mut u32;
AXI_INTC_IAR.write_volatile(0xffffffff);
const AXI_INTC_MER: *mut u32 = (KERNEL_OFFSET + 0x1900_001C) as *mut u32;
// Hardware Interrupt enable | Enable irq output
AXI_INTC_MER.write_volatile(0b11);
// enable all interrupts
AXI_INTC_IER.write_volatile(0xffffffff);
}
/// Claim and complete external interrupt by reading and writing to
/// PLIC Interrupt Claim/Complete Register.
pub unsafe fn handle_external_interrupt() {
const HART0_S_MODE_INTERRUPT_CLAIM_COMPLETE: *mut u32 =
(KERNEL_OFFSET + 0x0C20_2000) as *mut u32;
(KERNEL_OFFSET + 0x0C20_1004) as *mut u32;
// claim
let source = HART0_S_MODE_INTERRUPT_CLAIM_COMPLETE.read_volatile();
// complete
HART0_S_MODE_INTERRUPT_CLAIM_COMPLETE.write_volatile(source);
// acknowledge all interrupts
const AXI_INTC_IAR: *mut u32 = (KERNEL_OFFSET + 0x1900_000C) as *mut u32;
AXI_INTC_IAR.write_volatile(0xffffffff);
}
pub unsafe fn enable_serial_interrupt() {
const SERIAL_BASE: *mut u32 = (KERNEL_OFFSET + 0x18000000) as *mut u32;
const UART_CTRL_REG: usize = 3;
// Intr enable | rx reset | tx reset
const UART_IE: u32 = 0x13;
SERIAL_BASE.add(UART_CTRL_REG).write_volatile(UART_IE);
}

@ -74,7 +74,7 @@ pub extern "C" fn rust_trap(tf: &mut TrapFrame) {
}
fn external() {
#[cfg(feature = "board_u540")]
#[cfg(any(feature = "board_u540", feature = "board_rocket_chip"))]
unsafe {
super::board::handle_external_interrupt();
}

@ -133,6 +133,33 @@ fn remap_the_kernel(dtb: usize) {
Linear::new(offset),
"uart16550",
);
// map PLIC for Rocket Chip
#[cfg(feature = "board_rocket_chip")]
ms.push(
KERNEL_OFFSET + 0x0C20_1000,
KERNEL_OFFSET + 0x0C20_1000 + PAGE_SIZE,
MemoryAttr::default(),
Linear::new(offset),
"plic2",
);
// map UART for Rocket Chip
#[cfg(feature = "board_rocket_chip")]
ms.push(
KERNEL_OFFSET + 0x18000000,
KERNEL_OFFSET + 0x18000000 + PAGE_SIZE,
MemoryAttr::default(),
Linear::new(-(KERNEL_OFFSET as isize + 0x18000000 - 0x60000000)),
"uartlite",
);
// map AXI INTC for Rocket Chip
#[cfg(feature = "board_rocket_chip")]
ms.push(
KERNEL_OFFSET + 0x19000000,
KERNEL_OFFSET + 0x19000000 + PAGE_SIZE,
MemoryAttr::default(),
Linear::new(-(KERNEL_OFFSET as isize + 0x19000000 - 0x61200000)),
"axi_intc",
);
unsafe {
ms.activate();
}

@ -70,7 +70,6 @@ pub extern "C" fn rust_main(hartid: usize, device_tree_paddr: usize) -> ! {
crate::drivers::init(device_tree_vaddr);
#[cfg(not(feature = "board_k210"))]
unsafe {
#[cfg(not(feature = "board_rocket_chip"))]
board::enable_serial_interrupt();
board::init_external_interrupt();
}

@ -29,14 +29,7 @@ impl Stdin {
return c;
}
}
#[cfg(feature = "board_rocket_chip")]
loop {
let c = crate::arch::io::getchar();
if c != '\0' && c as u8 != 254 {
return c;
}
}
#[cfg(not(any(feature = "board_k210", feature = "board_rocket_chip")))]
#[cfg(not(feature = "board_k210"))]
loop {
let mut buf_lock = self.buf.lock();
match buf_lock.pop_front() {
@ -48,11 +41,6 @@ impl Stdin {
}
}
pub fn can_read(&self) -> bool {
// Currently, rocket-chip implementation rely on htif interface, the serial interrupt DO
// NOT work, so return true always
#[cfg(feature = "board_rocket_chip")]
return true;
#[cfg(not(feature = "board_rocket_chip"))]
return self.buf.lock().len() > 0;
}
}

Loading…
Cancel
Save