diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 6c2c379..b395174 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -30,7 +30,8 @@ config RISCV
 	select SPARSE_IRQ
 	select SYSCTL_EXCEPTION_TRACE
 	select HAVE_ARCH_TRACEHOOK
-
+        select HAVE_IDE
+        
 config MMU
 	def_bool y
 
diff --git a/arch/riscv/include/uapi/asm/siginfo.h b/arch/riscv/include/uapi/asm/siginfo.h
index 29baf87..5db7078 100644
--- a/arch/riscv/include/uapi/asm/siginfo.h
+++ b/arch/riscv/include/uapi/asm/siginfo.h
@@ -17,7 +17,11 @@
 #ifndef __ASM_SIGINFO_H
 #define __ASM_SIGINFO_H
 
+#if __riscv_xlen == 64
 #define __ARCH_SI_PREAMBLE_SIZE	(4 * sizeof(int))
+#else
+#define __ARCH_SI_PREAMBLE_SIZE	(3 * sizeof(int))
+#endif
 
 #include <asm-generic/siginfo.h>
 
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index 88b5810..f7f748e 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -6,7 +6,7 @@ extra-y := head.o vmlinux.lds
 
 obj-y	:= cpu.o entry.o irq.o process.o ptrace.o reset.o setup.o \
 	   sbi.o signal.o syscall_table.o sys_riscv.o time.o traps.o \
-	   stacktrace.o vdso.o vdso/
+	   ide.o stacktrace.o vdso.o vdso/
 
 obj-$(CONFIG_SMP)		+= smpboot.o smp.o
 obj-$(CONFIG_SBI_CONSOLE)	+= sbi-con.o
diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c
index cf2b496..540c379 100644
--- a/arch/riscv/kernel/irq.c
+++ b/arch/riscv/kernel/irq.c
@@ -12,6 +12,7 @@ struct plic_context {
 	volatile int claim;
 };
 
+static int plic_irqs;
 static DEFINE_PER_CPU(struct plic_context *, plic_context);
 static DEFINE_PER_CPU(unsigned int, irq_in_progress);
 
@@ -37,11 +38,12 @@ static void plic_interrupt(void)
 	unsigned int cpu = smp_processor_id();
 	unsigned int irq = per_cpu(plic_context, cpu)->claim;
 
-	BUG_ON(per_cpu(irq_in_progress, cpu) != 0);
+        //	BUG_ON(per_cpu(irq_in_progress, cpu) != 0);
 
 	if (irq) {
 		per_cpu(irq_in_progress, cpu) = irq;
-		generic_handle_irq(irq);
+		generic_handle_irq(irq - 1);
+                per_cpu(plic_context, cpu)->claim = irq;
 	}
 }
 
@@ -73,19 +75,23 @@ asmlinkage void __irq_entry do_IRQ(unsigned int cause, struct pt_regs *regs)
 
 static void plic_irq_mask(struct irq_data *d)
 {
+#if 0
 	unsigned int cpu = smp_processor_id();
 
 	BUG_ON(d->irq != per_cpu(irq_in_progress, cpu));
+#endif
 }
 
 static void plic_irq_unmask(struct irq_data *d)
 {
+#if 0
 	unsigned int cpu = smp_processor_id();
 
 	BUG_ON(d->irq != per_cpu(irq_in_progress, cpu));
 
 	per_cpu(plic_context, cpu)->claim = per_cpu(irq_in_progress, cpu);
 	per_cpu(irq_in_progress, cpu) = 0;
+#endif
 }
 
 struct irq_chip plic_irq_chip = {
@@ -97,6 +103,24 @@ struct irq_chip plic_irq_chip = {
 
 void __init init_IRQ(void)
 {
+        int irq;
+        
+	/* Allocate our IRQs */
+	plic_irqs = /* config_string_u64(pdev, "ndevs") */ 32;
+	irq = irq_alloc_descs(0, 0, plic_irqs, 0);
+
+	if (irq != 0) {
+		printk("could not allocate %d PLIC IRQs at 0!\n", plic_irqs);
+		return;
+	}
+
+	for (irq = 0; irq < plic_irqs; ++irq) {
+		irq_set_chip_and_handler(irq, &plic_irq_chip, handle_simple_irq);
+	}
+
+        per_cpu(plic_context, 0) = ioremap(0x40002000, 8);
+        
 	/* Enable software interrupts (and disable the others) */
-	csr_write(sie, SIE_SSIE);
+        /* enable external interrupts */
+        csr_write(sie, SIE_SSIE | 0x200);
 }
diff --git a/arch/riscv/kernel/sbi-con.c b/arch/riscv/kernel/sbi-con.c
index 10e499d..677417e 100644
--- a/arch/riscv/kernel/sbi-con.c
+++ b/arch/riscv/kernel/sbi-con.c
@@ -88,9 +88,8 @@ static int __init sbi_console_init(void)
 	int ret;
 
 	register_console(&sbi_console);
-
-	sbi_tty_driver = tty_alloc_driver(1,
-		TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
+        
+	sbi_tty_driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
 	if (unlikely(IS_ERR(sbi_tty_driver)))
 		return PTR_ERR(sbi_tty_driver);
 
diff --git a/arch/riscv/kernel/time.c b/arch/riscv/kernel/time.c
index 58fbca0..9c64174 100644
--- a/arch/riscv/kernel/time.c
+++ b/arch/riscv/kernel/time.c
@@ -78,8 +78,11 @@ void __init time_init(void)
 {
 	timebase = sbi_timebase();
 	lpj_fine = timebase;
+#if __riscv_xlen == 64
 	do_div(lpj_fine, HZ);
-
+#else
+	lpj_fine /= HZ;
+#endif
 	clocksource_register_hz(&riscv_clocksource, timebase);
 	init_clockevent();
 
diff --git a/arch/riscv/lib/delay.c b/arch/riscv/lib/delay.c
index 29097b6..ea9fb47 100644
--- a/arch/riscv/lib/delay.c
+++ b/arch/riscv/lib/delay.c
@@ -12,13 +12,28 @@ void __delay(unsigned long cycles)
 
 void udelay(unsigned long usecs)
 {
+#if __riscv_xlen == 64
 	__delay((unsigned long)(((u64)usecs * timebase) / 1000000UL));
-
+#else
+        /* XXX: inefficient */
+        uint64_t a;
+        a = (u64)usecs * timebase;
+        do_div(a, 1000000UL);
+        __delay(a);
+#endif
 }
 EXPORT_SYMBOL(udelay);
 
 void ndelay(unsigned long nsecs)
 {
+#if __riscv_xlen == 64
 	__delay((unsigned long)(((u64)nsecs * timebase) / 1000000000UL));
+#else
+        /* XXX: inefficient */
+        uint64_t a;
+        a = (u64)nsecs * timebase;
+        do_div(a, 1000000000UL);
+        __delay(a);
+#endif
 }
 EXPORT_SYMBOL(ndelay);
