From 6be68d06aede492e1124d72670f544e423b3968c Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 24 Jan 2015 21:54:11 -0800 Subject: [PATCH 1/8] New debug option "-d instr": print executed MIPS instructions and state change to log file. --- include/qemu/log.h | 1 + qemu-log.c | 2 + target-mips/cpu.h | 10 + target-mips/helper.c | 26 +- target-mips/helper.h | 4 + target-mips/op_helper.c | 528 ++++++++++++++++++++++++++++++++++++++++ target-mips/translate.c | 59 ++++- 7 files changed, 623 insertions(+), 7 deletions(-) diff --git a/include/qemu/log.h b/include/qemu/log.h index d5154246e6dad..d83e02e9eb125 100644 --- a/include/qemu/log.h +++ b/include/qemu/log.h @@ -40,6 +40,7 @@ static inline bool qemu_log_enabled(void) #define CPU_LOG_RESET (1 << 9) #define LOG_UNIMP (1 << 10) #define LOG_GUEST_ERROR (1 << 11) +#define CPU_LOG_INSTR (1 << 12) /* Returns true if a bit is set in the current loglevel mask */ diff --git a/qemu-log.c b/qemu-log.c index 797f2af983aef..b13bd78f7060d 100644 --- a/qemu-log.c +++ b/qemu-log.c @@ -104,6 +104,8 @@ const QEMULogItem qemu_log_items[] = { "show interrupts/exceptions in short format" }, { CPU_LOG_EXEC, "exec", "show trace before each executed TB (lots of logs)" }, + { CPU_LOG_INSTR, "instr", + "show executed instructions and changed CPU state" }, { CPU_LOG_TB_CPU, "cpu", "show CPU state before block translation" }, { CPU_LOG_PCALL, "pcall", diff --git a/target-mips/cpu.h b/target-mips/cpu.h index c01bbdac2d671..36abca0db3d0f 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -582,6 +582,15 @@ struct CPUMIPSState { const mips_def_t *cpu_model; void *irq[8]; QEMUTimer *timer; /* Internal timer */ + + /* Processor state after the last instruction. + * Used for instruction tracing. */ + target_ulong last_gpr[32]; + target_ulong last_HI[MIPS_DSP_ACC]; + target_ulong last_LO[MIPS_DSP_ACC]; + target_ulong last_DSPControl; + target_ulong last_cop0[32*8]; + const char *last_mode; }; #include "cpu-qom.h" @@ -772,6 +781,7 @@ hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address, int rw); #endif target_ulong exception_resume_pc (CPUMIPSState *env); +void mips_dump_changed_state(CPUMIPSState *env); /* op_helper.c */ extern unsigned int ieee_rm[]; diff --git a/target-mips/helper.c b/target-mips/helper.c index 3a93c206e4ce3..b9ede25adee89 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -340,9 +340,9 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, #if 0 log_cpu_state(cs, 0); -#endif qemu_log("%s pc " TARGET_FMT_lx " ad %" VADDR_PRIx " rw %d mmu_idx %d\n", __func__, env->active_tc.PC, address, rw, mmu_idx); +#endif /* data access */ #if !defined(CONFIG_USER_ONLY) @@ -351,9 +351,6 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, access_type = ACCESS_INT; ret = get_physical_address(env, &physical, &prot, address, rw, access_type); - qemu_log("%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx - " prot %d\n", - __func__, address, ret, physical, prot); if (ret == TLBRET_MATCH) { tlb_set_page(cs, address & TARGET_PAGE_MASK, physical & TARGET_PAGE_MASK, prot | PAGE_EXEC, @@ -362,6 +359,11 @@ int mips_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, } else if (ret < 0) #endif { +#if !defined(CONFIG_USER_ONLY) + qemu_log("%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx + " prot %d\n", + __func__, address, ret, physical, prot); +#endif raise_mmu_exception(env, address, rw, ret); ret = 1; } @@ -492,9 +494,13 @@ void mips_cpu_do_interrupt(CPUState *cs) name = excp_names[cs->exception_index]; } - qemu_log("%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " %s exception\n", - __func__, env->active_tc.PC, env->CP0_EPC, name); + if (! qemu_loglevel_mask(CPU_LOG_INSTR)) + qemu_log("%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " %s exception\n", + __func__, env->active_tc.PC, env->CP0_EPC, name); } + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + mips_dump_changed_state(env); + if (cs->exception_index == EXCP_EXT_INTERRUPT && (env->hflags & MIPS_HFLAG_DM)) { cs->exception_index = EXCP_DINT; @@ -744,6 +750,14 @@ void mips_cpu_do_interrupt(CPUState *cs) printf("Invalid MIPS exception %d. Exiting\n", cs->exception_index); exit(1); } + if (qemu_loglevel_mask(CPU_LOG_INSTR)) { + if (cs->exception_index == EXCP_EXT_INTERRUPT) + fprintf (qemu_logfile, "--- Interrupt, vector "TARGET_FMT_lx"\n", + env->active_tc.PC); + else + fprintf (qemu_logfile, "--- Exception #%u: %s, vector "TARGET_FMT_lx"\n", + cause, name, env->active_tc.PC); + } else if (qemu_log_enabled() && cs->exception_index != EXCP_EXT_INTERRUPT) { qemu_log("%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d\n" " S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n", diff --git a/target-mips/helper.h b/target-mips/helper.h index 9d0275891cfc0..3d2080772335d 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -356,6 +356,10 @@ DEF_HELPER_1(rdhwr_ccres, tl, env) DEF_HELPER_2(pmon, void, env, int) DEF_HELPER_1(wait, void, env) +DEF_HELPER_3(dump_pc, void, env, int, int) +DEF_HELPER_4(dump_store, void, env, int, tl, tl) +DEF_HELPER_4(dump_load, void, env, int, tl, tl) + /* Loongson multimedia functions. */ DEF_HELPER_FLAGS_2(paddsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_2(paddush, TCG_CALL_NO_RWG_SE, i64, i64, i64) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 638c9f9dfba14..0ecae30284da4 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -22,6 +22,7 @@ #include "exec/helper-proto.h" #include "exec/cpu_ldst.h" #include "sysemu/kvm.h" +#include "disas/bfd.h" #ifndef CONFIG_USER_ONLY static inline void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global); @@ -1919,6 +1920,32 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx) tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12; } +static void r4k_dump_tlb(CPUMIPSState *env, int idx) +{ + r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[idx]; + unsigned pagemask, hi, lo0, lo1; + + if (tlb->EHINV) { + pagemask = 0; + hi = 1 << CP0EnHi_EHINV; + lo0 = 0; + lo1 = 0; + } else { + pagemask = tlb->PageMask; + hi = tlb->VPN | tlb->ASID; + lo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | + ((target_ulong)tlb->RI0 << CP0EnLo_RI) | + ((target_ulong)tlb->XI0 << CP0EnLo_XI) | + (tlb->C0 << 3) | (tlb->PFN[0] >> 6); + lo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | + ((target_ulong)tlb->RI1 << CP0EnLo_RI) | + ((target_ulong)tlb->XI1 << CP0EnLo_XI) | + (tlb->C1 << 3) | (tlb->PFN[1] >> 6); + } + fprintf(qemu_logfile, " Write TLB[%u] = %08x %08x %08x %08x\n", + idx, pagemask, hi, lo0, lo1); +} + void r4k_helper_tlbinv(CPUMIPSState *env) { int idx; @@ -1975,6 +2002,9 @@ void r4k_helper_tlbwi(CPUMIPSState *env) r4k_invalidate_tlb(env, idx, 0); r4k_fill_tlb(env, idx); + + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + r4k_dump_tlb(env, idx); } void r4k_helper_tlbwr(CPUMIPSState *env) @@ -1983,6 +2013,9 @@ void r4k_helper_tlbwr(CPUMIPSState *env) r4k_invalidate_tlb(env, r, 1); r4k_fill_tlb(env, r); + + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + r4k_dump_tlb(env, r); } void r4k_helper_tlbp(CPUMIPSState *env) @@ -2329,8 +2362,503 @@ void mips_cpu_unassigned_access(CPUState *cs, hwaddr addr, helper_raise_exception(env, EXCP_DBE); } } + +/* + * Print changed kernel/user/debug mode. + */ +static void dump_changed_mode(CPUMIPSState *env) +{ + const char *kernel0, *kernel1, *mode; + +#if defined(TARGET_MIPS64) + if (env->CP0_Status & (1 << CP0St_KX)) { + kernel0 = "Kernel mode (ERL=0, KX=1)"; + kernel1 = "Kernel mode (ERL=1, KX=1)"; + } else { + kernel0 = "Kernel mode (ERL=0, KX=0)"; + kernel1 = "Kernel mode (ERL=1, KX=0)"; + } +#else + kernel0 = "Kernel mode (ERL=0)"; + kernel1 = "Kernel mode (ERL=1)"; +#endif + + if (env->CP0_Debug & (1 << CP0DB_DM)) { + mode = "Debug mode"; + } else if (env->CP0_Status & (1 << CP0St_ERL)) { + mode = kernel1; + } else if (env->CP0_Status & (1 << CP0St_EXL)) { + mode = kernel0; + } else { + switch (extract32(env->CP0_Status, CP0St_KSU, 2)) { + case 0: mode = kernel0; break; + case 1: mode = "Supervisor mode"; break; + default: mode = "User mode"; break; + } + } + + if (mode != env->last_mode) { + env->last_mode = mode; + fprintf(qemu_logfile, "--- %s\n", mode); + } +} + +/* + * Names of coprocessor 0 registers. + */ +static const char *cop0_name[32*8] = { +/*0*/ "Index", "MVPControl", "MVPConf0", "MVPConf1", + 0, 0, 0, 0, +/*1*/ "Random", "VPEControl", "VPEConf0", "VPEConf1", + "YQMask", "VPESchedule", "VPEScheFBack", "VPEOpt", +/*2*/ "EntryLo0", "TCStatus", "TCBind", "TCRestart", + "TCHalt", "TCContext", "TCSchedule", "TCScheFBack", +/*3*/ "EntryLo1", 0, 0, 0, + 0, 0, 0, "TCOpt", +/*4*/ "Context", "ContextConfig","UserLocal", "XContextConfig", + 0, 0, 0, 0, +/*5*/ "PageMask", "PageGrain", "SegCtl0", "SegCtl1", + "SegCtl2", 0, 0, 0, +/*6*/ "Wired", "SRSConf0", "SRSConf1", "SRSConf2", + "SRSConf3", "SRSConf4", 0, 0, +/*7*/ "HWREna", 0, 0, 0, + 0, 0, 0, 0, +/*8*/ "BadVAddr", 0, 0, 0, + 0, 0, 0, 0, +/*9*/ "Count", 0, 0, 0, + 0, 0, 0, 0, +/*10*/ "EntryHi", 0, 0, 0, + 0, "MSAAccess", "MSASave", "MSARequest", +/*11*/ "Compare", 0, 0, 0, + 0, 0, 0, 0, +/*12*/ "Status", "IntCtl", "SRSCtl", "SRSMap", + "ViewIPL", "SRSMap2", 0, 0, +/*13*/ "Cause", 0, 0, 0, + "ViewRIPL", "NestedExc", 0, 0, +/*14*/ "EPC", 0, "NestedEPC", 0, + 0, 0, 0, 0, +/*15*/ "PRId", "EBase", "CDMMBase", "CMGCRBase", + 0, 0, 0, 0, +/*16*/ "Config", "Config1", "Config2", "Config3", + "Config4", "Config5", "Config6", "Config7", +/*17*/ "LLAddr", 0, 0, 0, + 0, 0, 0, 0, +/*18*/ "WatchLo", "WatchLo1", "WatchLo2", "WatchLo3", + "WatchLo4", "WatchLo5", "WatchLo6", "WatchLo7", +/*19*/ "WatchHi", "WatchHi1", "WatchHi2", "WatchHi3", + "WatchHi4", "WatchHi5", "WatchHi6", "WatchHi7", +/*20*/ "XContext", 0, 0, 0, + 0, 0, 0, 0, +/*21*/ 0, 0, 0, 0, + 0, 0, 0, 0, +/*22*/ 0, 0, 0, 0, + 0, 0, 0, 0, +/*23*/ "Debug", "TraceControl", "TraceControl2","UserTraceData", + "TraceIBPC", "TraceDBPC", "Debug2", 0, +/*24*/ "DEPC", 0, "TraceControl3","UserTraceData2", + 0, 0, 0, 0, +/*25*/ "PerfCnt", "PerfCnt1", "PerfCnt2", "PerfCnt3", + "PerfCnt4", "PerfCnt5", "PerfCnt6", "PerfCnt7", +/*26*/ "ErrCtl", 0, 0, 0, + 0, 0, 0, 0, +/*27*/ "CacheErr", 0, 0, 0, + 0, 0, 0, 0, +/*28*/ "ITagLo", "IDataLo", "DTagLo", "DDataLo", + "L23TagLo", "L23DataLo", 0, 0, +/*29*/ "ITagHi", "IDataHi", "DTagHi", 0, + 0, "L23DataHi", 0, 0, +/*30*/ "ErrorEPC", 0, 0, 0, + 0, 0, 0, 0, +/*31*/ "DESAVE", 0, "KScratch1", "KScratch2", + "KScratch3", "KScratch4", "KScratch5", "KScratch6", +}; + +/* + * Print changed values of COP0 registers. + */ +static void dump_changed_cop0_reg(CPUMIPSState *env, int idx, target_ulong value) +{ + if (value != env->last_cop0[idx]) { + env->last_cop0[idx] = value; + fprintf(qemu_logfile, " Write %s = %08x\n", + cop0_name[idx], (unsigned) value); + } +} + +/* + * Print changed values of COP0 registers. + */ +static void dump_changed_cop0(CPUMIPSState *env) +{ + dump_changed_cop0_reg(env, 0*8 + 0, env->CP0_Index); + if (env->CP0_Config3 & (1 << CP0C3_MT)) { + dump_changed_cop0_reg(env, 0*8 + 1, env->mvp->CP0_MVPControl); + dump_changed_cop0_reg(env, 0*8 + 2, env->mvp->CP0_MVPConf0); + dump_changed_cop0_reg(env, 0*8 + 3, env->mvp->CP0_MVPConf1); + + dump_changed_cop0_reg(env, 1*8 + 1, env->CP0_VPEControl); + dump_changed_cop0_reg(env, 1*8 + 2, env->CP0_VPEConf0); + dump_changed_cop0_reg(env, 1*8 + 3, env->CP0_VPEConf1); + dump_changed_cop0_reg(env, 1*8 + 4, env->CP0_YQMask); + dump_changed_cop0_reg(env, 1*8 + 5, env->CP0_VPESchedule); + dump_changed_cop0_reg(env, 1*8 + 6, env->CP0_VPEScheFBack); + dump_changed_cop0_reg(env, 1*8 + 7, env->CP0_VPEOpt); + } + + dump_changed_cop0_reg(env, 2*8 + 0, env->CP0_EntryLo0); + if (env->CP0_Config3 & (1 << CP0C3_MT)) { + dump_changed_cop0_reg(env, 2*8 + 1, env->active_tc.CP0_TCStatus); + dump_changed_cop0_reg(env, 2*8 + 2, env->active_tc.CP0_TCBind); + dump_changed_cop0_reg(env, 2*8 + 3, env->active_tc.PC); + dump_changed_cop0_reg(env, 2*8 + 4, env->active_tc.CP0_TCHalt); + dump_changed_cop0_reg(env, 2*8 + 5, env->active_tc.CP0_TCContext); + dump_changed_cop0_reg(env, 2*8 + 6, env->active_tc.CP0_TCSchedule); + dump_changed_cop0_reg(env, 2*8 + 7, env->active_tc.CP0_TCScheFBack); + } + + dump_changed_cop0_reg(env, 3*8 + 0, env->CP0_EntryLo1); + + dump_changed_cop0_reg(env, 4*8 + 0, env->CP0_Context); + /* 4/1 not implemented - ContextConfig */ + dump_changed_cop0_reg(env, 4*8 + 2, env->active_tc.CP0_UserLocal); + /* 4/3 not implemented - XContextConfig */ + + dump_changed_cop0_reg(env, 5*8 + 0, env->CP0_PageMask); + dump_changed_cop0_reg(env, 5*8 + 1, env->CP0_PageGrain); + + dump_changed_cop0_reg(env, 6*8 + 0, env->CP0_Wired); + dump_changed_cop0_reg(env, 6*8 + 1, env->CP0_SRSConf0); + dump_changed_cop0_reg(env, 6*8 + 2, env->CP0_SRSConf1); + dump_changed_cop0_reg(env, 6*8 + 3, env->CP0_SRSConf2); + dump_changed_cop0_reg(env, 6*8 + 4, env->CP0_SRSConf3); + dump_changed_cop0_reg(env, 6*8 + 5, env->CP0_SRSConf4); + + dump_changed_cop0_reg(env, 7*8 + 0, env->CP0_HWREna); + + dump_changed_cop0_reg(env, 8*8 + 0, env->CP0_BadVAddr); + if (env->CP0_Config3 & (1 << CP0C3_BI)) + dump_changed_cop0_reg(env, 8*8 + 1, env->CP0_BadInstr); + if (env->CP0_Config3 & (1 << CP0C3_BP)) + dump_changed_cop0_reg(env, 8*8 + 1, env->CP0_BadInstrP); + + dump_changed_cop0_reg(env, 10*8 + 0, env->CP0_EntryHi); + + dump_changed_cop0_reg(env, 11*8 + 0, env->CP0_Compare); + + dump_changed_cop0_reg(env, 12*8 + 0, env->CP0_Status); + dump_changed_cop0_reg(env, 12*8 + 1, env->CP0_IntCtl); + dump_changed_cop0_reg(env, 12*8 + 2, env->CP0_SRSCtl); + dump_changed_cop0_reg(env, 12*8 + 3, env->CP0_SRSMap); + + dump_changed_cop0_reg(env, 13*8 + 0, env->CP0_Cause); + + dump_changed_cop0_reg(env, 14*8 + 0, env->CP0_EPC); + + dump_changed_cop0_reg(env, 15*8 + 0, env->CP0_PRid); + dump_changed_cop0_reg(env, 15*8 + 1, env->CP0_EBase); + + dump_changed_cop0_reg(env, 16*8 + 0, env->CP0_Config0); + dump_changed_cop0_reg(env, 16*8 + 1, env->CP0_Config1); + dump_changed_cop0_reg(env, 16*8 + 2, env->CP0_Config2); + dump_changed_cop0_reg(env, 16*8 + 3, env->CP0_Config3); + dump_changed_cop0_reg(env, 16*8 + 4, env->CP0_Config4); + dump_changed_cop0_reg(env, 16*8 + 5, env->CP0_Config5); + dump_changed_cop0_reg(env, 16*8 + 6, env->CP0_Config6); + dump_changed_cop0_reg(env, 16*8 + 7, env->CP0_Config7); + + dump_changed_cop0_reg(env, 17*8 + 0, env->lladdr >> env->CP0_LLAddr_shift); + + dump_changed_cop0_reg(env, 18*8 + 0, env->CP0_WatchLo[0]); + dump_changed_cop0_reg(env, 18*8 + 1, env->CP0_WatchLo[1]); + dump_changed_cop0_reg(env, 18*8 + 2, env->CP0_WatchLo[2]); + dump_changed_cop0_reg(env, 18*8 + 3, env->CP0_WatchLo[3]); + dump_changed_cop0_reg(env, 18*8 + 4, env->CP0_WatchLo[4]); + dump_changed_cop0_reg(env, 18*8 + 5, env->CP0_WatchLo[5]); + dump_changed_cop0_reg(env, 18*8 + 6, env->CP0_WatchLo[6]); + dump_changed_cop0_reg(env, 18*8 + 7, env->CP0_WatchLo[7]); + + dump_changed_cop0_reg(env, 19*8 + 0, env->CP0_WatchHi[0]); + dump_changed_cop0_reg(env, 19*8 + 1, env->CP0_WatchHi[1]); + dump_changed_cop0_reg(env, 19*8 + 2, env->CP0_WatchHi[2]); + dump_changed_cop0_reg(env, 19*8 + 3, env->CP0_WatchHi[3]); + dump_changed_cop0_reg(env, 19*8 + 4, env->CP0_WatchHi[4]); + dump_changed_cop0_reg(env, 19*8 + 5, env->CP0_WatchHi[5]); + dump_changed_cop0_reg(env, 19*8 + 6, env->CP0_WatchHi[6]); + dump_changed_cop0_reg(env, 19*8 + 7, env->CP0_WatchHi[7]); + +#if defined(TARGET_MIPS64) + dump_changed_cop0_reg(env, 20*8 + 0, env->CP0_XContext); +#endif + + dump_changed_cop0_reg(env, 21*8 + 0, env->CP0_Framemask); + + /* 22/x not defined */ + + dump_changed_cop0_reg(env, 23*8 + 0, helper_mfc0_debug(env)); + + dump_changed_cop0_reg(env, 24*8 + 0, env->CP0_DEPC); + + dump_changed_cop0_reg(env, 25*8 + 0, env->CP0_Performance0); + + /* 26/0 not implemented - ErrCtl */ + + /* 27/0 not implemented - CacheErr */ + + dump_changed_cop0_reg(env, 28*8 + 0, env->CP0_TagLo); + dump_changed_cop0_reg(env, 28*8 + 1, env->CP0_DataLo); + + dump_changed_cop0_reg(env, 29*8 + 0, env->CP0_TagHi); + dump_changed_cop0_reg(env, 29*8 + 1, env->CP0_DataHi); + + dump_changed_cop0_reg(env, 30*8 + 0, env->CP0_ErrorEPC); + + dump_changed_cop0_reg(env, 31*8 + 0, env->CP0_DESAVE); + dump_changed_cop0_reg(env, 31*8 + 2, env->CP0_KScratch[0]); + dump_changed_cop0_reg(env, 31*8 + 3, env->CP0_KScratch[1]); + dump_changed_cop0_reg(env, 31*8 + 4, env->CP0_KScratch[2]); + dump_changed_cop0_reg(env, 31*8 + 5, env->CP0_KScratch[3]); + dump_changed_cop0_reg(env, 31*8 + 6, env->CP0_KScratch[4]); + dump_changed_cop0_reg(env, 31*8 + 7, env->CP0_KScratch[5]); +} #endif /* !CONFIG_USER_ONLY */ +/* + * Print changed values of GPR, HI/LO and DSPControl registers. + */ +static void dump_changed_regs(CPUMIPSState *env) +{ + TCState *cur = &env->active_tc; + static const char * const gpr_name[] = { + "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", + }; + int i; + + for (i=1; i<32; i++) { + if (cur->gpr[i] != env->last_gpr[i]) { + env->last_gpr[i] = cur->gpr[i]; + fprintf(qemu_logfile, " Write %s = %08x\n", + gpr_name[i], (unsigned) cur->gpr[i]); + } + } + for (i=0; iLO[i] != env->last_LO[i]) { + env->last_LO[i] = cur->LO[i]; + fprintf(qemu_logfile, " Write Lo%u = %08x\n", + i, (unsigned) cur->LO[i]); + } + if (cur->HI[i] != env->last_HI[i]) { + env->last_HI[i] = cur->HI[i]; + fprintf(qemu_logfile, " Write Hi%u = %08x\n", + i, (unsigned) cur->HI[i]); + } + } + if (cur->DSPControl != env->last_DSPControl) { + env->last_DSPControl = cur->DSPControl; + fprintf(qemu_logfile, " Write DSPControl = %08x\n", + (unsigned) cur->DSPControl); + } +} + +/* + * Print the changed processor state. + */ +void mips_dump_changed_state(CPUMIPSState *env) +{ + /* Print changed state: GPR, HI/LO, COP0. */ + dump_changed_regs(env); + dump_changed_cop0(env); + + /* Print changed mode: kernel/user/debug */ + dump_changed_mode(env); +} + +static void dump_print_target_address(bfd_vma addr, struct disassemble_info *info) +{ + fprintf(qemu_logfile, "%08x", (unsigned) addr); +} + +/* + * Print the instruction to log file. + */ +void helper_dump_pc(CPUMIPSState *env, int pc, int isa) +{ + struct disassemble_info info; + char disasm_options[] = "cp0-names=mips32r2"; + int (*print_insn)(bfd_vma pc, disassemble_info *info); + int opcode, nbytes; + + /* Print changed state: GPR, HI/LO, COP0. */ + mips_dump_changed_state(env); + + /* Fetch opcode. */ + if (isa == 0) { + /* mips32 instruction set */ + opcode = cpu_ldl_code(env, pc); + nbytes = 4; + } else { + /* micromips or mips16 */ + opcode = cpu_lduw_code(env, pc); + nbytes = 2; + if (isa == 1) { + /* micromips */ + switch (opcode >> 10) { + case 0x01: case 0x02: case 0x03: case 0x09: + case 0x0a: case 0x0b: + case 0x11: case 0x12: case 0x13: case 0x19: + case 0x1a: case 0x1b: + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x28: case 0x29: case 0x2a: case 0x2b: + case 0x30: case 0x31: case 0x32: case 0x33: + case 0x38: case 0x39: case 0x3a: case 0x3b: + break; + default: + opcode <<= 16; + opcode |= cpu_lduw_code(env, pc + 2); + nbytes += 2; + break; + } + } else { + /* mips16 */ + switch (opcode >> 11) { + case 0x03: + case 0x1e: + opcode <<= 16; + opcode |= cpu_lduw_code(env, pc + 2); + nbytes += 2; + break; + } + } + } + + /* Setup disassemble descriptor. */ + INIT_DISASSEMBLE_INFO(info, qemu_logfile, fprintf); + info.read_memory_func = buffer_read_memory; + info.print_address_func = dump_print_target_address; + info.buffer_vma = pc; + info.buffer_length = nbytes; + info.buffer = (void*) &opcode; + info.disassembler_options = disasm_options; +#ifdef TARGET_WORDS_BIGENDIAN + info.endian = BFD_ENDIAN_BIG; + print_insn = print_insn_big_mips; +#else + info.endian = BFD_ENDIAN_LITTLE; + print_insn = print_insn_little_mips; +#endif + + /* Print instruction address, opcode and mnemonics. */ + if (nbytes == 2) + fprintf(qemu_logfile, "%08x: %04x ", pc, opcode); + else + fprintf(qemu_logfile, "%08x: %08x ", pc, opcode); + print_insn(pc, &info); + fprintf(qemu_logfile, "\n"); + + /* Handle magic opcodes. */ + if (opcode == 0x2c00abc1 || opcode == 0x2c00abc2) { + /* Halt the processor. */ + fprintf(qemu_logfile, "Application terminated with %s code.\n", + opcode == 0x2c00abc2 ? "PASS" : "FAIL"); + if (fileno(stdout) != fileno(qemu_logfile)) + printf("Application terminated with %s code.\n", + opcode == 0x2c00abc2 ? "PASS" : "FAIL"); + exit(1); + } +} + +enum { + /* Load and stores */ + OPC_LDL = (0x1A << 26), + OPC_LDR = (0x1B << 26), + OPC_LB = (0x20 << 26), + OPC_LH = (0x21 << 26), + OPC_LWL = (0x22 << 26), + OPC_LW = (0x23 << 26), + OPC_LWPC = OPC_LW | 0x5, + OPC_LBU = (0x24 << 26), + OPC_LHU = (0x25 << 26), + OPC_LWR = (0x26 << 26), + OPC_LWU = (0x27 << 26), + OPC_SB = (0x28 << 26), + OPC_SH = (0x29 << 26), + OPC_SWL = (0x2A << 26), + OPC_SW = (0x2B << 26), + OPC_SDL = (0x2C << 26), + OPC_SDR = (0x2D << 26), + OPC_SWR = (0x2E << 26), + OPC_LL = (0x30 << 26), + OPC_LLD = (0x34 << 26), + OPC_LD = (0x37 << 26), + OPC_LDPC = OPC_LD | 0x5, + OPC_SC = (0x38 << 26), + OPC_SCD = (0x3C << 26), + OPC_SD = (0x3F << 26), +}; + +/* + * Print the memory store to log file. + */ +void helper_dump_store(CPUMIPSState *env, int opc, target_ulong addr, target_ulong value) +{ + switch (opc) { +#if defined(TARGET_MIPS64) + case OPC_SD: + case OPC_SDL: + case OPC_SDR: + fprintf(qemu_logfile, " Memory Write ["TARGET_FMT_lx"] = "TARGET_FMT_lx"\n", addr, value); + break; +#endif + case OPC_SW: + case OPC_SWL: + case OPC_SWR: + fprintf(qemu_logfile, " Memory Write ["TARGET_FMT_lx"] = %08x\n", addr, (uint32_t) value); + break; + case OPC_SH: + fprintf(qemu_logfile, " Memory Write ["TARGET_FMT_lx"] = %04x\n", addr, (uint16_t) value); + break; + case OPC_SB: + fprintf(qemu_logfile, " Memory Write ["TARGET_FMT_lx"] = %02x\n", addr, (uint8_t) value); + break; + default: + fprintf(qemu_logfile, " Memory op%u ["TARGET_FMT_lx"] = %08x\n", opc, addr, (uint32_t) value); + } +} + +/* + * Print the memory load to log file. + */ +void helper_dump_load(CPUMIPSState *env, int opc, target_ulong addr, target_ulong value) +{ + switch (opc) { +#if defined(TARGET_MIPS64) + case OPC_LD: + case OPC_LDL: + case OPC_LDR: + case OPC_LDPC: + fprintf(qemu_logfile, " Memory Read ["TARGET_FMT_lx"] = "TARGET_FMT_lx"\n", addr, value); + break; + case OPC_LWU: +#endif + case OPC_LW: + case OPC_LWPC: + case OPC_LWL: + case OPC_LWR: + fprintf(qemu_logfile, " Memory Read ["TARGET_FMT_lx"] = %08x\n", addr, (uint32_t) value); + break; + case OPC_LH: + case OPC_LHU: + fprintf(qemu_logfile, " Memory Read ["TARGET_FMT_lx"] = %04x\n", addr, (uint16_t) value); + break; + case OPC_LB: + case OPC_LBU: + fprintf(qemu_logfile, " Memory Read ["TARGET_FMT_lx"] = %02x\n", addr, (uint8_t) value); + break; + } +} + /* Complex FPU operations which may need stack space. */ #define FLOAT_TWO32 make_float32(1 << 30) diff --git a/target-mips/translate.c b/target-mips/translate.c index f0b8e6ffe4e3a..29d962cd3da19 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1686,6 +1686,32 @@ generate_exception (DisasContext *ctx, int excp) gen_helper_0e0i(raise_exception, excp); } +static inline void +generate_dump_pc(int pc, int isa) +{ + TCGv_i32 tpc = tcg_const_i32(pc); + TCGv_i32 tisa = tcg_const_i32(isa); + gen_helper_dump_pc(cpu_env, tpc, tisa); + tcg_temp_free_i32(tpc); + tcg_temp_free_i32(tisa); +} + +static inline void +generate_dump_store(int op, TCGv addr, TCGv value) +{ + TCGv_i32 top = tcg_const_i32(op); + gen_helper_dump_store(cpu_env, top, addr, value); + tcg_temp_free_i32(top); +} + +static inline void +generate_dump_load(int op, TCGv addr, TCGv value) +{ + TCGv_i32 top = tcg_const_i32(op); + gen_helper_dump_load(cpu_env, top, addr, value); + tcg_temp_free_i32(top); +} + /* Addresses computation */ static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1) { @@ -1886,6 +1912,8 @@ static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \ case FMT_D: \ check_cp1_registers(ctx, fs | ft | fd); \ break; \ + default: \ + break; \ } \ gen_ldcmp_fpr ## bits(ctx, fp0, fs); \ gen_ldcmp_fpr ## bits(ctx, fp1, ft); \ @@ -2067,7 +2095,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, int rt, int base, int16_t offset) { const char *opn = "ld"; - TCGv t0, t1, t2; + TCGv t0, t1, t2, t3 = 0; if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) { /* Loongson CPU uses a load to zero register for prefetch. @@ -2080,15 +2108,23 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, t0 = tcg_temp_new(); gen_base_offset_addr(ctx, t0, base, offset); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) { + t3 = tcg_temp_new(); + tcg_gen_mov_tl(t3, t0); + } switch (opc) { #if defined(TARGET_MIPS64) case OPC_LWU: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + generate_dump_load(opc, t3, t0); gen_store_gpr(t0, rt); opn = "lwu"; break; case OPC_LD: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + generate_dump_load(opc, t3, t0); gen_store_gpr(t0, rt); opn = "ld"; break; @@ -2160,26 +2196,36 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, break; case OPC_LW: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + generate_dump_load(opc, t3, t0); gen_store_gpr(t0, rt); opn = "lw"; break; case OPC_LH: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + generate_dump_load(opc, t3, t0); gen_store_gpr(t0, rt); opn = "lh"; break; case OPC_LHU: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + generate_dump_load(opc, t3, t0); gen_store_gpr(t0, rt); opn = "lhu"; break; case OPC_LB: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + generate_dump_load(opc, t3, t0); gen_store_gpr(t0, rt); opn = "lb"; break; case OPC_LBU: tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + generate_dump_load(opc, t3, t0); gen_store_gpr(t0, rt); opn = "lbu"; break; @@ -2238,6 +2284,8 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); tcg_temp_free(t0); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + tcg_temp_free(t3); } /* Store */ @@ -2292,6 +2340,10 @@ static void gen_st (DisasContext *ctx, uint32_t opc, int rt, } (void)opn; /* avoid a compiler warning */ MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]); + + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + generate_dump_store(opc, t0, t1); + tcg_temp_free(t0); tcg_temp_free(t1); } @@ -19055,6 +19107,11 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) gen_io_start(); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + generate_dump_pc(ctx.pc, + (ctx.hflags & MIPS_HFLAG_M16) == 0 ? 0 : + (ctx.insn_flags & ASE_MICROMIPS) ? 1 : 2); + is_slot = ctx.hflags & MIPS_HFLAG_BMASK; if (!(ctx.hflags & MIPS_HFLAG_M16)) { ctx.opcode = cpu_ldl_code(env, ctx.pc); From 63c5ac7b3848e47f86a84d838816de7a9c27965d Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 24 Jan 2015 21:56:47 -0800 Subject: [PATCH 2/8] Speed of CPU timer made configurable per platform. Timer decreased when instruction tracing enabled, to compensate for slowdown. --- hw/mips/cputimer.c | 20 ++++++++++++++------ hw/mips/mips_fulong2e.c | 2 +- hw/mips/mips_jazz.c | 2 +- hw/mips/mips_malta.c | 4 ++-- hw/mips/mips_mipssim.c | 2 +- hw/mips/mips_r4k.c | 2 +- include/hw/mips/cpudevs.h | 2 +- target-mips/cpu.h | 1 + 8 files changed, 22 insertions(+), 13 deletions(-) diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c index 577c9aeab877d..7af0e6ec1307c 100644 --- a/hw/mips/cputimer.c +++ b/hw/mips/cputimer.c @@ -50,8 +50,8 @@ static void cpu_mips_timer_update(CPUMIPSState *env) now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); wait = env->CP0_Compare - env->CP0_Count - - (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec()); - next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ); + (uint32_t)muldiv64(now, env->count_freq, get_ticks_per_sec()); + next = now + muldiv64(wait, get_ticks_per_sec(), env->count_freq); timer_mod(env->timer, next); } @@ -80,7 +80,7 @@ uint32_t cpu_mips_get_count (CPUMIPSState *env) } return env->CP0_Count + - (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec()); + (uint32_t)muldiv64(now, env->count_freq, get_ticks_per_sec()); } } @@ -97,7 +97,7 @@ void cpu_mips_store_count (CPUMIPSState *env, uint32_t count) /* Store new count register */ env->CP0_Count = count - (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - TIMER_FREQ, get_ticks_per_sec()); + env->count_freq, get_ticks_per_sec()); /* Update timer timer */ cpu_mips_timer_update(env); } @@ -122,7 +122,7 @@ void cpu_mips_stop_count(CPUMIPSState *env) { /* Store the current value */ env->CP0_Count += (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - TIMER_FREQ, get_ticks_per_sec()); + env->count_freq, get_ticks_per_sec()); } static void mips_timer_cb (void *opaque) @@ -145,7 +145,7 @@ static void mips_timer_cb (void *opaque) env->CP0_Count--; } -void cpu_mips_clock_init (CPUMIPSState *env) +void cpu_mips_clock_init (CPUMIPSState *env, unsigned count_freq) { /* * If we're in KVM mode, don't create the periodic timer, that is handled in @@ -153,5 +153,13 @@ void cpu_mips_clock_init (CPUMIPSState *env) */ if (!kvm_enabled()) { env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env); + env->count_freq = count_freq; + + if (qemu_loglevel_mask(CPU_LOG_INSTR)) { + /* When instruction tracing enabled, + * we need to slow down the timer to adapt + * to the decreased simulation speed. */ + env->count_freq /= 10; + } } } diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index 6a9ebfa91161c..34da2b1696fc7 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -344,7 +344,7 @@ static void mips_fulong2e_init(MachineState *machine) /* Init internal devices */ cpu_mips_irq_init_cpu(env); - cpu_mips_clock_init(env); + cpu_mips_clock_init(env, 100*1000*1000); /* North bridge, Bonito --> IP2 */ pci_bus = bonito_init((qemu_irq *)&(env->irq[2])); diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c index 3f33093fd94b1..8ae0a8b4c12ef 100644 --- a/hw/mips/mips_jazz.c +++ b/hw/mips/mips_jazz.c @@ -210,7 +210,7 @@ static void mips_jazz_init(MemoryRegion *address_space, /* Init CPU internal devices */ cpu_mips_irq_init_cpu(env); - cpu_mips_clock_init(env); + cpu_mips_clock_init(env, 100*1000*1000); /* Chipset */ rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas, diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 5845158a740c6..4dc2446275c1e 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -978,7 +978,7 @@ void mips_malta_init(MachineState *machine) /* Init internal devices */ cpu_mips_irq_init_cpu(env); - cpu_mips_clock_init(env); + cpu_mips_clock_init(env, 100*1000*1000); qemu_register_reset(main_cpu_reset, cpu); } cpu = MIPS_CPU(first_cpu); @@ -1134,7 +1134,7 @@ void mips_malta_init(MachineState *machine) /* Init internal devices */ cpu_mips_irq_init_cpu(env); - cpu_mips_clock_init(env); + cpu_mips_clock_init(env, 100*1000*1000); /* * We have a circular dependency problem: pci_bus depends on isa_irq, diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c index 5d44c3f73d1c4..e8bcfef1bb72b 100644 --- a/hw/mips/mips_mipssim.c +++ b/hw/mips/mips_mipssim.c @@ -214,7 +214,7 @@ mips_mipssim_init(MachineState *machine) /* Init CPU internal devices. */ cpu_mips_irq_init_cpu(env); - cpu_mips_clock_init(env); + cpu_mips_clock_init(env, 100*1000*1000); /* Register 64 KB of ISA IO space at 0x1fd00000. */ memory_region_init_alias(isa, NULL, "isa_mmio", diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c index a7fe0ceadfb8e..52389e0bbe99a 100644 --- a/hw/mips/mips_r4k.c +++ b/hw/mips/mips_r4k.c @@ -265,7 +265,7 @@ void mips_r4k_init(MachineState *machine) /* Init CPU internal devices */ cpu_mips_irq_init_cpu(env); - cpu_mips_clock_init(env); + cpu_mips_clock_init(env, 100*1000*1000); /* The PIC is attached to the MIPS CPU INT0 pin */ isa_bus = isa_bus_new(NULL, get_system_io()); diff --git a/include/hw/mips/cpudevs.h b/include/hw/mips/cpudevs.h index b2626f2922f4c..4d4e62a0be22a 100644 --- a/include/hw/mips/cpudevs.h +++ b/include/hw/mips/cpudevs.h @@ -12,6 +12,6 @@ uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr); void cpu_mips_irq_init_cpu(CPUMIPSState *env); /* mips_timer.c */ -void cpu_mips_clock_init(CPUMIPSState *); +void cpu_mips_clock_init(CPUMIPSState *, unsigned count_freq); #endif diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 36abca0db3d0f..120e1ebcbdd46 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -582,6 +582,7 @@ struct CPUMIPSState { const mips_def_t *cpu_model; void *irq[8]; QEMUTimer *timer; /* Internal timer */ + unsigned count_freq; /* rate of Count register */ /* Processor state after the last instruction. * Used for instruction tracing. */ From 1fdac2662471a0fefc640e925063fc525b916c84 Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 24 Jan 2015 21:59:31 -0800 Subject: [PATCH 3/8] Stop simulation when processor is suspended forever by WAIT instruction with interrupts disabled. --- target-mips/op_helper.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 0ecae30284da4..9caf1933a5985 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -23,6 +23,7 @@ #include "exec/cpu_ldst.h" #include "sysemu/kvm.h" #include "disas/bfd.h" +#include "sysemu/sysemu.h" #ifndef CONFIG_USER_ONLY static inline void cpu_mips_tlb_flush (CPUMIPSState *env, int flush_global); @@ -2294,6 +2295,12 @@ void helper_wait(CPUMIPSState *env) { CPUState *cs = CPU(mips_env_get_cpu(env)); +#ifndef CONFIG_USER_ONLY + if (! (env->CP0_Status & (1 << CP0St_IE))) { + /* WAIT instruction with interrupts disabled - halt the simulation. */ + qemu_system_shutdown_request(); + } +#endif cs->halted = 1; cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE); helper_raise_exception(env, EXCP_HLT); From 6801cfc6733e764d46de53d63b1cd19dab076b7d Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 24 Jan 2015 22:01:19 -0800 Subject: [PATCH 4/8] Fixed random index generation for TLBWR instruction. It was not quite random and did not skip Wired entries. --- hw/mips/cputimer.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c index 7af0e6ec1307c..4e159a45b9af8 100644 --- a/hw/mips/cputimer.c +++ b/hw/mips/cputimer.c @@ -25,21 +25,13 @@ #include "qemu/timer.h" #include "sysemu/kvm.h" -#define TIMER_FREQ 100 * 1000 * 1000 - -/* XXX: do not use a global */ +/* Generate a random TLB index. + * Skip wired entries. */ uint32_t cpu_mips_get_random (CPUMIPSState *env) { - static uint32_t lfsr = 1; - static uint32_t prev_idx = 0; - uint32_t idx; - /* Don't return same value twice, so get another value */ - do { - lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u); - idx = lfsr % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired; - } while (idx == prev_idx); - prev_idx = idx; - return idx; + env->CP0_Random = env->CP0_Wired + + random() % (env->tlb->nb_tlb - env->CP0_Wired); + return env->CP0_Random; } /* MIPS R4K timer */ From 95db704a9155e66461d56794f452387a97c5db45 Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 24 Jan 2015 22:04:47 -0800 Subject: [PATCH 5/8] Added support for external interrupt controller (EIC) mode. --- hw/mips/cputimer.c | 17 +++++++++++++++-- hw/mips/mips_int.c | 11 +++++++++-- target-mips/cpu.h | 9 ++++++++- target-mips/helper.c | 20 ++++++++++++++------ 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c index 4e159a45b9af8..b56daf5a723e4 100644 --- a/hw/mips/cputimer.c +++ b/hw/mips/cputimer.c @@ -54,7 +54,13 @@ static void cpu_mips_timer_expire(CPUMIPSState *env) if (env->insn_flags & ISA_MIPS32R2) { env->CP0_Cause |= 1 << CP0Ca_TI; } - qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); + if (env->CP0_Config3 & (1 << CP0C3_VEIC)) { + /* External interrupt controller mode. */ + env->eic_timer_irq(env, 1); + } else { + /* Legacy or vectored interrupt mode. */ + qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); + } } uint32_t cpu_mips_get_count (CPUMIPSState *env) @@ -102,7 +108,14 @@ void cpu_mips_store_compare (CPUMIPSState *env, uint32_t value) cpu_mips_timer_update(env); if (env->insn_flags & ISA_MIPS32R2) env->CP0_Cause &= ~(1 << CP0Ca_TI); - qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); + + if (env->CP0_Config3 & (1 << CP0C3_VEIC)) { + /* External interrupt controller mode: nothing to do. */ + env->eic_timer_irq(env, 0); + } else { + /* Legacy or vectored interrupt mode. */ + qemu_irq_lower(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]); + } } void cpu_mips_start_count(CPUMIPSState *env) diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c index d740046ba1514..64dad0c266b6d 100644 --- a/hw/mips/mips_int.c +++ b/hw/mips/mips_int.c @@ -32,7 +32,7 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level) CPUMIPSState *env = &cpu->env; CPUState *cs = CPU(cpu); - if (irq < 0 || irq > 7) + if (irq < 0 || irq > 7 || (env->CP0_Config3 & (1 << CP0C3_VEIC))) return; if (level) { @@ -74,5 +74,12 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level) return; } - qemu_set_irq(env->irq[irq], level); + if (env->CP0_Config3 & (1 << CP0C3_VEIC)) { + /* External interrupt controller mode. */ + if (level > 0) + env->eic_soft_irq(env, irq); + } else { + /* Legacy or vectored interrupt mode. */ + qemu_set_irq(env->irq[irq], level); + } } diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 120e1ebcbdd46..cc8b96e065659 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -592,6 +592,11 @@ struct CPUMIPSState { target_ulong last_DSPControl; target_ulong last_cop0[32*8]; const char *last_mode; + + /* Fields for external interrupt controller. */ + void *eic_context; + void (*eic_timer_irq)(CPUMIPSState *env, int raise); + void (*eic_soft_irq)(CPUMIPSState *env, int num); }; #include "cpu-qom.h" @@ -662,7 +667,9 @@ static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env) if (env->CP0_Config3 & (1 << CP0C3_VEIC)) { /* A MIPS configured with a vectorizing external interrupt controller will feed a vector into the Cause pending lines. The core treats - the status lines as a vector level, not as indiviual masks. */ + the status lines as a vector level, not as individual masks. */ + pending >>= CP0Ca_IP + 2; + status >>= CP0Ca_IP + 2; r = pending > status; } else { /* A MIPS configured with compatibility or VInt (Vectored Interrupts) diff --git a/target-mips/helper.c b/target-mips/helper.c index b9ede25adee89..d600a34d2e828 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -572,23 +572,31 @@ void mips_cpu_do_interrupt(CPUState *cs) unsigned int vector; unsigned int pending = (env->CP0_Cause & CP0Ca_IP_mask) >> 8; - pending &= env->CP0_Status >> 8; /* Compute the Vector Spacing. */ spacing = (env->CP0_IntCtl >> CP0IntCtl_VS) & ((1 << 6) - 1); spacing <<= 5; - if (env->CP0_Config3 & (1 << CP0C3_VInt)) { + if (env->CP0_Config3 & (1 << CP0C3_VEIC)) { + /* For VEIC mode, the external interrupt controller feeds the + * vector through the CP0Cause IP lines. */ + vector = pending; + + /* Architecturally, this is chip-specific behavior. + * TODO: some processors, like PIC32MZ, + * provide vector in a different way. + * Some processors, like PIC32, have a separate + * bit INTCON.MVEC to explicitly enable vectored mode, + * disabled by default. */ + spacing = 0; + } else { /* For VInt mode, the MIPS computes the vector internally. */ + pending &= env->CP0_Status >> 8; for (vector = 7; vector > 0; vector--) { if (pending & (1 << vector)) { /* Found it. */ break; } } - } else { - /* For VEIC mode, the external interrupt controller feeds the - vector through the CP0Cause IP lines. */ - vector = pending; } offset = 0x200 + vector * spacing; } From a0eba4b4ea5d54ba596d678f9a980c19ce83dcbf Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 24 Jan 2015 22:06:05 -0800 Subject: [PATCH 6/8] Two new processor variants: M4K and microAptivP. --- target-mips/cpu.h | 2 ++ target-mips/translate_init.c | 46 ++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index cc8b96e065659..8e8b0bd245ded 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -387,6 +387,7 @@ struct CPUMIPSState { #define CP0C0_M 31 #define CP0C0_K23 28 #define CP0C0_KU 25 +#define CP0C0_SB 21 #define CP0C0_MDU 20 #define CP0C0_MM 17 #define CP0C0_BM 16 @@ -468,6 +469,7 @@ struct CPUMIPSState { #define CP0C5_NFExists 0 int32_t CP0_Config6; int32_t CP0_Config7; +#define CP0C7_WII 31 /* XXX: Maybe make LLAddr per-TC? */ target_ulong lladdr; target_ulong llval; diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 148b394cf0545..8470da75f9720 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -231,6 +231,52 @@ static const mips_def_t mips_defs[] = .insn_flags = CPU_MIPS32R2 | ASE_MIPS16, .mmu_type = MMU_TYPE_FMT, }, + { + /* Configuration for Microchip PIC32MX microcontroller. */ + .name = "M4K", + .CP0_PRid = 0x00018765, + .CP0_Config0 = MIPS_CONFIG0 | (2 << CP0C0_K23) | (2 << CP0C0_KU) | + (1 << CP0C0_SB) | (1 << CP0C0_BM) | + (1 << CP0C0_AR) | (MMU_TYPE_FMT << CP0C0_MT), + .CP0_Config1 = (1U << CP0C1_M) | (1 << CP0C1_CA) | (1 << CP0C1_EP), + .CP0_Config2 = MIPS_CONFIG2, + .CP0_Config3 = (1 << CP0C3_VEIC) | (1 << CP0C3_VInt), + .CP0_LLAddr_rw_bitmask = 0, + .CP0_LLAddr_shift = 4, + .SYNCI_Step = 32, + .CCRes = 2, + .CP0_Status_rw_bitmask = 0x1258FF17, + .SEGBITS = 32, + .PABITS = 32, + .insn_flags = CPU_MIPS32R2 | ASE_MIPS16, + .mmu_type = MMU_TYPE_FMT, + }, + { + /* Configuration for Microchip PIC32MZ microcontroller. */ + .name = "microAptivP", + .CP0_PRid = 0x00019e28, + .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | + (MMU_TYPE_R4000 << CP0C0_MT), + .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) | (1 << CP0C1_PC), + .CP0_Config2 = MIPS_CONFIG2, + .CP0_Config3 = (1 << CP0C3_M) | (1 << CP0C3_IPLW) | (1 << CP0C3_MCU) | + (2 << CP0C3_ISA) | (1 << CP0C3_ULRI) | (1 << CP0C3_RXI) | + (1 << CP0C3_DSP2P) | (1 << CP0C3_DSPP) | (1 << CP0C3_VEIC) | + (1 << CP0C3_VInt), + .CP0_Config4 = (1 << CP0C4_M), + .CP0_Config5 = (1 << CP0C5_NFExists), + .CP0_Config6 = 0, + .CP0_Config7 = (1 << CP0C7_WII), + .CP0_LLAddr_rw_bitmask = 0, + .CP0_LLAddr_shift = 4, + .SYNCI_Step = 32, + .CCRes = 2, + .CP0_Status_rw_bitmask = 0x1278FF17, + .SEGBITS = 32, + .PABITS = 32, + .insn_flags = CPU_MIPS32R2, + .mmu_type = MMU_TYPE_R4000, + }, { .name = "24Kc", .CP0_PRid = 0x00019300, From 326a69b8b6fec044d3fbfb6ce7b9ed6943a61a4c Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 24 Jan 2015 22:09:16 -0800 Subject: [PATCH 7/8] Two new machine platforms: pic32mz7 and pic32mz. --- hw/mips/Makefile.objs | 2 + hw/mips/mips_pic32mx7.c | 1584 ++++++++++++++++++++++++++ hw/mips/mips_pic32mz.c | 2093 +++++++++++++++++++++++++++++++++++ hw/mips/pic32_gpio.c | 39 + hw/mips/pic32_load_hex.c | 230 ++++ hw/mips/pic32_peripherals.h | 164 +++ hw/mips/pic32_sdcard.c | 388 +++++++ hw/mips/pic32_spi.c | 121 ++ hw/mips/pic32_uart.c | 226 ++++ hw/mips/pic32mx.h | 1255 +++++++++++++++++++++ hw/mips/pic32mz.h | 1778 +++++++++++++++++++++++++++++ 11 files changed, 7880 insertions(+) create mode 100644 hw/mips/mips_pic32mx7.c create mode 100644 hw/mips/mips_pic32mz.c create mode 100644 hw/mips/pic32_gpio.c create mode 100644 hw/mips/pic32_load_hex.c create mode 100644 hw/mips/pic32_peripherals.h create mode 100644 hw/mips/pic32_sdcard.c create mode 100644 hw/mips/pic32_spi.c create mode 100644 hw/mips/pic32_uart.c create mode 100644 hw/mips/pic32mx.h create mode 100644 hw/mips/pic32mz.h diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs index 0a652f85217d0..059af197fa48d 100644 --- a/hw/mips/Makefile.objs +++ b/hw/mips/Makefile.objs @@ -2,3 +2,5 @@ obj-y += mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o obj-y += addr.o cputimer.o mips_int.o obj-$(CONFIG_FULONG) += mips_fulong2e.o obj-y += gt64xxx_pci.o +obj-y += mips_pic32mz.o mips_pic32mx7.o +obj-y += pic32_load_hex.o pic32_sdcard.o pic32_spi.o pic32_uart.o pic32_gpio.o diff --git a/hw/mips/mips_pic32mx7.c b/hw/mips/mips_pic32mx7.c new file mode 100644 index 0000000000000..3e00a8acad5b3 --- /dev/null +++ b/hw/mips/mips_pic32mx7.c @@ -0,0 +1,1584 @@ +/* + * QEMU support for Microchip PIC32MX7 microcontroller. + * + * Copyright (c) 2015 Serge Vakulenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* Only 32-bit little endian mode supported. */ +#include "config.h" +#if !defined TARGET_MIPS64 && !defined TARGET_WORDS_BIGENDIAN + +#include "hw/i386/pc.h" +#include "hw/char/serial.h" +#include "hw/mips/cpudevs.h" +#include "sysemu/char.h" +#include "hw/loader.h" +#include "qemu/error-report.h" +#include "hw/empty_slot.h" +#include + +#define PIC32MX7 +#include "pic32mx.h" +#include "pic32_peripherals.h" + +/* Hardware addresses */ +#define PROGRAM_FLASH_START 0x1d000000 +#define BOOT_FLASH_START 0x1fc00000 +#define DATA_MEM_START 0x00000000 +#define IO_MEM_START 0x1f800000 + +#define PROGRAM_FLASH_SIZE (512*1024) // 512 kbytes +#define BOOT_FLASH_SIZE (12*1024) // 12 kbytes +#define DATA_MEM_SIZE (128*1024) // 128 kbytes +#define USER_MEM_START 0xbf000000 + +#define TYPE_MIPS_PIC32 "mips-pic32mx7" + +/* + * Board variants. + */ +enum { + BOARD_MAX32, /* chipKIT Max32 board */ + BOARD_MAXIMITE, /* Geoff's Maximite board */ + BOARD_EXPLORER16, /* Microchip Explorer-16 board */ +}; + +static const char *board_name[] = { + "chipKIT Max32", + "Geoff's Maximite Computer", + "Microchip Explorer16", +}; + +/* + * Pointers to Flash memory contents. + */ +static char *prog_ptr; +static char *boot_ptr; + +#define BOOTMEM(addr) ((uint32_t*) boot_ptr) [(addr & 0xffff) >> 2] + +/* + * PIC32MX7 specific table: + * translate IRQ number to interrupt vector. + */ +static const int irq_to_vector[] = { + PIC32_VECT_CT, /* 0 - Core Timer Interrupt */ + PIC32_VECT_CS0, /* 1 - Core Software Interrupt 0 */ + PIC32_VECT_CS1, /* 2 - Core Software Interrupt 1 */ + PIC32_VECT_INT0, /* 3 - External Interrupt 0 */ + PIC32_VECT_T1, /* 4 - Timer1 */ + PIC32_VECT_IC1, /* 5 - Input Capture 1 */ + PIC32_VECT_OC1, /* 6 - Output Compare 1 */ + PIC32_VECT_INT1, /* 7 - External Interrupt 1 */ + PIC32_VECT_T2, /* 8 - Timer2 */ + PIC32_VECT_IC2, /* 9 - Input Capture 2 */ + PIC32_VECT_OC2, /* 10 - Output Compare 2 */ + PIC32_VECT_INT2, /* 11 - External Interrupt 2 */ + PIC32_VECT_T3, /* 12 - Timer3 */ + PIC32_VECT_IC3, /* 13 - Input Capture 3 */ + PIC32_VECT_OC3, /* 14 - Output Compare 3 */ + PIC32_VECT_INT3, /* 15 - External Interrupt 3 */ + PIC32_VECT_T4, /* 16 - Timer4 */ + PIC32_VECT_IC4, /* 17 - Input Capture 4 */ + PIC32_VECT_OC4, /* 18 - Output Compare 4 */ + PIC32_VECT_INT4, /* 19 - External Interrupt 4 */ + PIC32_VECT_T5, /* 20 - Timer5 */ + PIC32_VECT_IC5, /* 21 - Input Capture 5 */ + PIC32_VECT_OC5, /* 22 - Output Compare 5 */ + PIC32_VECT_SPI1, /* 23 - SPI1 Fault */ + PIC32_VECT_SPI1, /* 24 - SPI1 Transfer Done */ + PIC32_VECT_SPI1, /* 25 - SPI1 Receive Done */ + + PIC32_VECT_U1 | /* 26 - UART1 Error */ + PIC32_VECT_SPI3 | /* 26 - SPI3 Fault */ + PIC32_VECT_I2C3, /* 26 - I2C3 Bus Collision Event */ + + PIC32_VECT_U1 | /* 27 - UART1 Receiver */ + PIC32_VECT_SPI3 | /* 27 - SPI3 Transfer Done */ + PIC32_VECT_I2C3, /* 27 - I2C3 Slave Event */ + + PIC32_VECT_U1 | /* 28 - UART1 Transmitter */ + PIC32_VECT_SPI3 | /* 28 - SPI3 Receive Done */ + PIC32_VECT_I2C3, /* 28 - I2C3 Master Event */ + + PIC32_VECT_I2C1, /* 29 - I2C1 Bus Collision Event */ + PIC32_VECT_I2C1, /* 30 - I2C1 Slave Event */ + PIC32_VECT_I2C1, /* 31 - I2C1 Master Event */ + PIC32_VECT_CN, /* 32 - Input Change Interrupt */ + PIC32_VECT_AD1, /* 33 - ADC1 Convert Done */ + PIC32_VECT_PMP, /* 34 - Parallel Master Port */ + PIC32_VECT_CMP1, /* 35 - Comparator Interrupt */ + PIC32_VECT_CMP2, /* 36 - Comparator Interrupt */ + + PIC32_VECT_U3 | /* 37 - UART3 Error */ + PIC32_VECT_SPI2 | /* 37 - SPI2 Fault */ + PIC32_VECT_I2C4, /* 37 - I2C4 Bus Collision Event */ + + PIC32_VECT_U3 | /* 38 - UART3 Receiver */ + PIC32_VECT_SPI2 | /* 38 - SPI2 Transfer Done */ + PIC32_VECT_I2C4, /* 38 - I2C4 Slave Event */ + + PIC32_VECT_U3 | /* 39 - UART3 Transmitter */ + PIC32_VECT_SPI2 | /* 39 - SPI2 Receive Done */ + PIC32_VECT_I2C4, /* 39 - I2C4 Master Event */ + + PIC32_VECT_U2 | /* 40 - UART2 Error */ + PIC32_VECT_SPI4 | /* 40 - SPI4 Fault */ + PIC32_VECT_I2C5, /* 40 - I2C5 Bus Collision Event */ + + PIC32_VECT_U2 | /* 41 - UART2 Receiver */ + PIC32_VECT_SPI4 | /* 41 - SPI4 Transfer Done */ + PIC32_VECT_I2C5, /* 41 - I2C5 Slave Event */ + + PIC32_VECT_U2 | /* 42 - UART2 Transmitter */ + PIC32_VECT_SPI4 | /* 42 - SPI4 Receive Done */ + PIC32_VECT_I2C5, /* 42 - I2C5 Master Event */ + + PIC32_VECT_I2C2, /* 43 - I2C2 Bus Collision Event */ + PIC32_VECT_I2C2, /* 44 - I2C2 Slave Event */ + PIC32_VECT_I2C2, /* 45 - I2C2 Master Event */ + PIC32_VECT_FSCM, /* 46 - Fail-Safe Clock Monitor */ + PIC32_VECT_RTCC, /* 47 - Real-Time Clock and Calendar */ + PIC32_VECT_DMA0, /* 48 - DMA Channel 0 */ + PIC32_VECT_DMA1, /* 49 - DMA Channel 1 */ + PIC32_VECT_DMA2, /* 50 - DMA Channel 2 */ + PIC32_VECT_DMA3, /* 51 - DMA Channel 3 */ + PIC32_VECT_DMA4, /* 52 - DMA Channel 4 */ + PIC32_VECT_DMA5, /* 53 - DMA Channel 5 */ + PIC32_VECT_DMA6, /* 54 - DMA Channel 6 */ + PIC32_VECT_DMA7, /* 55 - DMA Channel 7 */ + PIC32_VECT_FCE, /* 56 - Flash Control Event */ + PIC32_VECT_USB, /* 57 - USB */ + PIC32_VECT_CAN1, /* 58 - Control Area Network 1 */ + PIC32_VECT_CAN2, /* 59 - Control Area Network 2 */ + PIC32_VECT_ETH, /* 60 - Ethernet Interrupt */ + PIC32_VECT_IC1, /* 61 - Input Capture 1 Error */ + PIC32_VECT_IC2, /* 62 - Input Capture 2 Error */ + PIC32_VECT_IC3, /* 63 - Input Capture 3 Error */ + PIC32_VECT_IC4, /* 64 - Input Capture 4 Error */ + PIC32_VECT_IC5, /* 65 - Input Capture 5 Error */ + PIC32_VECT_PMP, /* 66 - Parallel Master Port Error */ + PIC32_VECT_U4, /* 67 - UART4 Error */ + PIC32_VECT_U4, /* 68 - UART4 Receiver */ + PIC32_VECT_U4, /* 69 - UART4 Transmitter */ + PIC32_VECT_U6, /* 70 - UART6 Error */ + PIC32_VECT_U6, /* 71 - UART6 Receiver */ + PIC32_VECT_U6, /* 72 - UART6 Transmitter */ + PIC32_VECT_U5, /* 73 - UART5 Error */ + PIC32_VECT_U5, /* 74 - UART5 Receiver */ + PIC32_VECT_U5, /* 75 - UART5 Transmitter */ +}; + +static void update_irq_status(pic32_t *s) +{ + /* Assume no interrupts pending. */ + int cause_ripl = 0; + int vector = 0; + CPUMIPSState *env = &s->cpu->env; + int current_ripl = (env->CP0_Cause >> (CP0Ca_IP + 2)) & 0x3f; + + VALUE(INTSTAT) = 0; + + if ((VALUE(IFS0) & VALUE(IEC0)) || + (VALUE(IFS1) & VALUE(IEC1)) || + (VALUE(IFS2) & VALUE(IEC2))) + { + /* Find the most prioritive pending interrupt, + * it's vector and level. */ + int irq; + for (irq=0; irq> 5; + + if (((VALUE(IFS(n)) & VALUE(IEC(n))) >> (irq & 31)) & 1) { + /* Interrupt is pending. */ + int v = irq_to_vector [irq]; + if (v < 0) + continue; + + int level = VALUE(IPC(v >> 2)); + level >>= 2 + (v & 3) * 8; + level &= 7; + if (level > cause_ripl) { + vector = v; + cause_ripl = level; + } + } + } + VALUE(INTSTAT) = vector | (cause_ripl << 8); + } + + if (cause_ripl == current_ripl) + return; + + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Priority level Cause.RIPL = %u\n", + cause_ripl); + + /* + * Modify Cause.RIPL field and take EIC interrupt. + */ + env->CP0_Cause &= ~(0x3f << (CP0Ca_IP + 2)); + env->CP0_Cause |= cause_ripl << (CP0Ca_IP + 2); + cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HARD); +} + +/* + * Set interrupt flag status + */ +static void irq_raise(pic32_t *s, int irq) +{ + if (VALUE(IFS(irq >> 5)) & (1 << (irq & 31))) + return; + + VALUE(IFS(irq >> 5)) |= 1 << (irq & 31); + update_irq_status(s); +} + +/* + * Clear interrupt flag status + */ +static void irq_clear(pic32_t *s, int irq) +{ + if (! (VALUE(IFS(irq >> 5)) & (1 << (irq & 31)))) + return; + + VALUE(IFS(irq >> 5)) &= ~(1 << (irq & 31)); + update_irq_status(s); +} + +/* + * Timer interrupt. + */ +static void pic32_timer_irq(CPUMIPSState *env, int raise) +{ + pic32_t *s = env->eic_context; + + if (raise) { + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- %08x: Timer interrupt\n", + env->active_tc.PC); + irq_raise(s, 0); + } else { + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Clear timer interrupt\n"); + irq_clear(s, 0); + } +} + +/* + * Software interrupt. + */ +static void pic32_soft_irq(CPUMIPSState *env, int num) +{ + pic32_t *s = env->eic_context; + + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- %08x: Soft interrupt %u\n", + env->active_tc.PC, num); + irq_raise(s, num + 1); +} + +/* + * Perform an assign/clear/set/invert operation. + */ +static inline unsigned write_op(int a, int b, int op) +{ + switch (op & 0xc) { + case 0x0: a = b; break; // Assign + case 0x4: a &= ~b; break; // Clear + case 0x8: a |= b; break; // Set + case 0xc: a ^= b; break; // Invert + } + return a; +} + +static void io_reset(pic32_t *s) +{ + int i; + + /* + * Bus matrix control registers. + */ + VALUE(BMXCON) = 0x001f0041; // Bus Matrix Control + VALUE(BMXDKPBA) = 0; // Data RAM kernel program base address + VALUE(BMXDUDBA) = 0; // Data RAM user data base address + VALUE(BMXDUPBA) = 0; // Data RAM user program base address + VALUE(BMXPUPBA) = 0; // Program Flash user program base address + VALUE(BMXDRMSZ) = 128 * 1024; // Data RAM memory size + VALUE(BMXPFMSZ) = 512 * 1024; // Program Flash memory size + VALUE(BMXBOOTSZ) = 12 * 1024; // Boot Flash size + + /* + * Prefetch controller. + */ + VALUE(CHECON) = 0x00000007; + + /* + * System controller. + */ + VALUE(OSCTUN) = 0; + VALUE(DDPCON) = 0; + VALUE(SYSKEY) = 0; + VALUE(RCON) = 0; + VALUE(RSWRST) = 0; + s->syskey_unlock = 0; + + /* + * Analog to digital converter. + */ + VALUE(AD1CON1) = 0; // Control register 1 + VALUE(AD1CON2) = 0; // Control register 2 + VALUE(AD1CON3) = 0; // Control register 3 + VALUE(AD1CHS) = 0; // Channel select + VALUE(AD1CSSL) = 0; // Input scan selection + VALUE(AD1PCFG) = 0; // Port configuration + + /* + * General purpose IO signals. + * All pins are inputs, high, open drains and pullups disabled. + * No interrupts on change. + */ + VALUE(TRISA) = 0xFFFF; // Port A: mask of inputs + VALUE(PORTA) = 0xFFFF; // Port A: read inputs, write outputs + VALUE(LATA) = 0xFFFF; // Port A: read/write outputs + VALUE(ODCA) = 0; // Port A: open drain configuration + VALUE(TRISB) = 0xFFFF; // Port B: mask of inputs + VALUE(PORTB) = 0xFFFF; // Port B: read inputs, write outputs + VALUE(LATB) = 0xFFFF; // Port B: read/write outputs + VALUE(ODCB) = 0; // Port B: open drain configuration + VALUE(TRISC) = 0xFFFF; // Port C: mask of inputs + VALUE(PORTC) = 0xFFFF; // Port C: read inputs, write outputs + VALUE(LATC) = 0xFFFF; // Port C: read/write outputs + VALUE(ODCC) = 0; // Port C: open drain configuration + VALUE(TRISD) = 0xFFFF; // Port D: mask of inputs + VALUE(PORTD) = 0xFFFF; // Port D: read inputs, write outputs + VALUE(LATD) = 0xFFFF; // Port D: read/write outputs + VALUE(ODCD) = 0; // Port D: open drain configuration + VALUE(TRISE) = 0xFFFF; // Port E: mask of inputs + VALUE(PORTE) = 0xFFFF; // Port D: read inputs, write outputs + VALUE(LATE) = 0xFFFF; // Port E: read/write outputs + VALUE(ODCE) = 0; // Port E: open drain configuration + VALUE(TRISF) = 0xFFFF; // Port F: mask of inputs + VALUE(PORTF) = 0xFFFF; // Port F: read inputs, write outputs + VALUE(LATF) = 0xFFFF; // Port F: read/write outputs + VALUE(ODCF) = 0; // Port F: open drain configuration + VALUE(TRISG) = 0xFFFF; // Port G: mask of inputs + VALUE(PORTG) = 0xFFFF; // Port G: read inputs, write outputs + VALUE(LATG) = 0xFFFF; // Port G: read/write outputs + VALUE(ODCG) = 0; // Port G: open drain configuration + VALUE(CNCON) = 0; // Interrupt-on-change control + VALUE(CNEN) = 0; // Input change interrupt enable + VALUE(CNPUE) = 0; // Input pin pull-up enable + + /* + * Reset UARTs. + */ + VALUE(U1MODE) = 0; + VALUE(U1STA) = PIC32_USTA_RIDLE | PIC32_USTA_TRMT; + VALUE(U1TXREG) = 0; + VALUE(U1RXREG) = 0; + VALUE(U1BRG) = 0; + VALUE(U2MODE) = 0; + VALUE(U2STA) = PIC32_USTA_RIDLE | PIC32_USTA_TRMT; + VALUE(U2TXREG) = 0; + VALUE(U2RXREG) = 0; + VALUE(U2BRG) = 0; + VALUE(U3MODE) = 0; + VALUE(U3STA) = PIC32_USTA_RIDLE | PIC32_USTA_TRMT; + VALUE(U3TXREG) = 0; + VALUE(U3RXREG) = 0; + VALUE(U3BRG) = 0; + VALUE(U4MODE) = 0; + VALUE(U4STA) = PIC32_USTA_RIDLE | PIC32_USTA_TRMT; + VALUE(U4TXREG) = 0; + VALUE(U4RXREG) = 0; + VALUE(U4BRG) = 0; + VALUE(U5MODE) = 0; + VALUE(U5STA) = PIC32_USTA_RIDLE | PIC32_USTA_TRMT; + VALUE(U5TXREG) = 0; + VALUE(U5RXREG) = 0; + VALUE(U5BRG) = 0; + VALUE(U6MODE) = 0; + VALUE(U6STA) = PIC32_USTA_RIDLE | PIC32_USTA_TRMT; + VALUE(U6TXREG) = 0; + VALUE(U6RXREG) = 0; + VALUE(U6BRG) = 0; + + /* + * Reset SPI. + */ + VALUE(SPI1CON) = 0; + VALUE(SPI1STAT) = PIC32_SPISTAT_SPITBE; // Transmit buffer is empty + VALUE(SPI1BRG) = 0; + + VALUE(SPI2CON) = 0; + VALUE(SPI2STAT) = PIC32_SPISTAT_SPITBE; // Transmit buffer is empty + VALUE(SPI2BRG) = 0; + + VALUE(SPI3CON) = 0; + VALUE(SPI3STAT) = PIC32_SPISTAT_SPITBE; // Transmit buffer is empty + VALUE(SPI3BRG) = 0; + + VALUE(SPI4CON) = 0; + VALUE(SPI4STAT) = PIC32_SPISTAT_SPITBE; // Transmit buffer is empty + VALUE(SPI4BRG) = 0; + + for (i=0; ispi[i].rfifo = 0; + s->spi[i].wfifo = 0; + } +} + +static unsigned io_read32(pic32_t *s, unsigned offset, const char **namep) +{ + unsigned *bufp = &VALUE(offset); + + switch (offset) { + /*------------------------------------------------------------------------- + * Bus matrix control registers. + */ + STORAGE(BMXCON); break; // Bus Mmatrix Control + STORAGE(BMXDKPBA); break; // Data RAM kernel program base address + STORAGE(BMXDUDBA); break; // Data RAM user data base address + STORAGE(BMXDUPBA); break; // Data RAM user program base address + STORAGE(BMXPUPBA); break; // Program Flash user program base address + STORAGE(BMXDRMSZ); break; // Data RAM memory size + STORAGE(BMXPFMSZ); break; // Program Flash memory size + STORAGE(BMXBOOTSZ); break; // Boot Flash size + + /*------------------------------------------------------------------------- + * Interrupt controller registers. + */ + STORAGE(INTCON); break; // Interrupt Control + STORAGE(INTSTAT); break; // Interrupt Status + STORAGE(IFS0); break; // IFS(0..2) - Interrupt Flag Status + STORAGE(IFS1); break; + STORAGE(IFS2); break; + STORAGE(IEC0); break; // IEC(0..2) - Interrupt Enable Control + STORAGE(IEC1); break; + STORAGE(IEC2); break; + STORAGE(IPC0); break; // IPC(0..11) - Interrupt Priority Control + STORAGE(IPC1); break; + STORAGE(IPC2); break; + STORAGE(IPC3); break; + STORAGE(IPC4); break; + STORAGE(IPC5); break; + STORAGE(IPC6); break; + STORAGE(IPC7); break; + STORAGE(IPC8); break; + STORAGE(IPC9); break; + STORAGE(IPC10); break; + STORAGE(IPC11); break; + STORAGE(IPC12); break; + + /*------------------------------------------------------------------------- + * Prefetch controller. + */ + STORAGE(CHECON); break; // Prefetch Control + + /*------------------------------------------------------------------------- + * System controller. + */ + STORAGE(OSCCON); break; // Oscillator Control + STORAGE(OSCTUN); break; // Oscillator Tuning + STORAGE(DDPCON); break; // Debug Data Port Control + STORAGE(DEVID); break; // Device Identifier + STORAGE(SYSKEY); break; // System Key + STORAGE(RCON); break; // Reset Control + STORAGE(RSWRST); // Software Reset + if ((VALUE(RSWRST) & 1) && s->stop_on_reset) { + exit(0); + } + break; + + /*------------------------------------------------------------------------- + * DMA controller. + */ + STORAGE(DMACON); break; // DMA Control + STORAGE(DMASTAT); break; // DMA Status + STORAGE(DMAADDR); break; // DMA Address + + /*------------------------------------------------------------------------- + * Analog to digital converter. + */ + STORAGE(AD1CON1); break; // Control register 1 + STORAGE(AD1CON2); break; // Control register 2 + STORAGE(AD1CON3); break; // Control register 3 + STORAGE(AD1CHS); break; // Channel select + STORAGE(AD1CSSL); break; // Input scan selection + STORAGE(AD1PCFG); break; // Port configuration + STORAGE(ADC1BUF0); break; // Result words + STORAGE(ADC1BUF1); break; + STORAGE(ADC1BUF2); break; + STORAGE(ADC1BUF3); break; + STORAGE(ADC1BUF4); break; + STORAGE(ADC1BUF5); break; + STORAGE(ADC1BUF6); break; + STORAGE(ADC1BUF7); break; + STORAGE(ADC1BUF8); break; + STORAGE(ADC1BUF9); break; + STORAGE(ADC1BUFA); break; + STORAGE(ADC1BUFB); break; + STORAGE(ADC1BUFC); break; + STORAGE(ADC1BUFD); break; + STORAGE(ADC1BUFE); break; + STORAGE(ADC1BUFF); break; + + /*-------------------------------------- + * USB registers. + */ + STORAGE(U1OTGIR); break; // OTG interrupt flags + STORAGE(U1OTGIE); break; // OTG interrupt enable + STORAGE(U1OTGSTAT); break; // Comparator and pin status + STORAGE(U1OTGCON); break; // Resistor and pin control + STORAGE(U1PWRC); break; // Power control + STORAGE(U1IR); break; // Pending interrupt + STORAGE(U1IE); break; // Interrupt enable + STORAGE(U1EIR); break; // Pending error interrupt + STORAGE(U1EIE); break; // Error interrupt enable + STORAGE(U1STAT); break; // Status FIFO + STORAGE(U1CON); break; // Control + STORAGE(U1ADDR); break; // Address + STORAGE(U1BDTP1); break; // Buffer descriptor table pointer 1 + STORAGE(U1FRML); break; // Frame counter low + STORAGE(U1FRMH); break; // Frame counter high + STORAGE(U1TOK); break; // Host control + STORAGE(U1SOF); break; // SOF counter + STORAGE(U1BDTP2); break; // Buffer descriptor table pointer 2 + STORAGE(U1BDTP3); break; // Buffer descriptor table pointer 3 + STORAGE(U1CNFG1); break; // Debug and idle + STORAGE(U1EP(0)); break; // Endpoint control + STORAGE(U1EP(1)); break; + STORAGE(U1EP(2)); break; + STORAGE(U1EP(3)); break; + STORAGE(U1EP(4)); break; + STORAGE(U1EP(5)); break; + STORAGE(U1EP(6)); break; + STORAGE(U1EP(7)); break; + STORAGE(U1EP(8)); break; + STORAGE(U1EP(9)); break; + STORAGE(U1EP(10)); break; + STORAGE(U1EP(11)); break; + STORAGE(U1EP(12)); break; + STORAGE(U1EP(13)); break; + STORAGE(U1EP(14)); break; + STORAGE(U1EP(15)); break; + + /*------------------------------------------------------------------------- + * General purpose IO signals. + */ + STORAGE(TRISA); break; // Port A: mask of inputs + STORAGE(PORTA); break; // Port A: read inputs + STORAGE(LATA); break; // Port A: read outputs + STORAGE(ODCA); break; // Port A: open drain configuration + STORAGE(TRISB); break; // Port B: mask of inputs + STORAGE(PORTB); break; // Port B: read inputs + STORAGE(LATB); break; // Port B: read outputs + STORAGE(ODCB); break; // Port B: open drain configuration + STORAGE(TRISC); break; // Port C: mask of inputs + STORAGE(PORTC); break; // Port C: read inputs + STORAGE(LATC); break; // Port C: read outputs + STORAGE(ODCC); break; // Port C: open drain configuration + STORAGE(TRISD); break; // Port D: mask of inputs + STORAGE(PORTD); break; // Port D: read inputs + STORAGE(LATD); break; // Port D: read outputs + STORAGE(ODCD); break; // Port D: open drain configuration + STORAGE(TRISE); break; // Port E: mask of inputs + STORAGE(PORTE); break; // Port E: read inputs + STORAGE(LATE); break; // Port E: read outputs + STORAGE(ODCE); break; // Port E: open drain configuration + STORAGE(TRISF); break; // Port F: mask of inputs + STORAGE(PORTF); break; // Port F: read inputs + STORAGE(LATF); break; // Port F: read outputs + STORAGE(ODCF); break; // Port F: open drain configuration + STORAGE(TRISG); break; // Port G: mask of inputs + STORAGE(PORTG); break; // Port G: read inputs + STORAGE(LATG); break; // Port G: read outputs + STORAGE(ODCG); break; // Port G: open drain configuration + STORAGE(CNCON); break; // Interrupt-on-change control + STORAGE(CNEN); break; // Input change interrupt enable + STORAGE(CNPUE); break; // Input pin pull-up enable + + /*------------------------------------------------------------------------- + * UART 1. + */ + STORAGE(U1RXREG); // Receive data + *bufp = pic32_uart_get_char(s, 0); + break; + STORAGE(U1BRG); break; // Baud rate + STORAGE(U1MODE); break; // Mode + STORAGE(U1STA); // Status and control + pic32_uart_poll_status(s, 0); + break; + STORAGE(U1TXREG); *bufp = 0; break; // Transmit + STORAGE(U1MODECLR); *bufp = 0; break; + STORAGE(U1MODESET); *bufp = 0; break; + STORAGE(U1MODEINV); *bufp = 0; break; + STORAGE(U1STACLR); *bufp = 0; break; + STORAGE(U1STASET); *bufp = 0; break; + STORAGE(U1STAINV); *bufp = 0; break; + STORAGE(U1BRGCLR); *bufp = 0; break; + STORAGE(U1BRGSET); *bufp = 0; break; + STORAGE(U1BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * UART 2. + */ + STORAGE(U2RXREG); // Receive data + *bufp = pic32_uart_get_char(s, 1); + break; + STORAGE(U2BRG); break; // Baud rate + STORAGE(U2MODE); break; // Mode + STORAGE(U2STA); // Status and control + pic32_uart_poll_status(s, 1); + break; + STORAGE(U2TXREG); *bufp = 0; break; // Transmit + STORAGE(U2MODECLR); *bufp = 0; break; + STORAGE(U2MODESET); *bufp = 0; break; + STORAGE(U2MODEINV); *bufp = 0; break; + STORAGE(U2STACLR); *bufp = 0; break; + STORAGE(U2STASET); *bufp = 0; break; + STORAGE(U2STAINV); *bufp = 0; break; + STORAGE(U2BRGCLR); *bufp = 0; break; + STORAGE(U2BRGSET); *bufp = 0; break; + STORAGE(U2BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * UART 3. + */ + STORAGE(U3RXREG); // Receive data + *bufp = pic32_uart_get_char(s, 2); + break; + STORAGE(U3BRG); break; // Baud rate + STORAGE(U3MODE); break; // Mode + STORAGE(U3STA); // Status and control + pic32_uart_poll_status(s, 2); + break; + STORAGE(U3TXREG); *bufp = 0; break; // Transmit + STORAGE(U3MODECLR); *bufp = 0; break; + STORAGE(U3MODESET); *bufp = 0; break; + STORAGE(U3MODEINV); *bufp = 0; break; + STORAGE(U3STACLR); *bufp = 0; break; + STORAGE(U3STASET); *bufp = 0; break; + STORAGE(U3STAINV); *bufp = 0; break; + STORAGE(U3BRGCLR); *bufp = 0; break; + STORAGE(U3BRGSET); *bufp = 0; break; + STORAGE(U3BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * UART 4. + */ + STORAGE(U4RXREG); // Receive data + *bufp = pic32_uart_get_char(s, 3); + break; + STORAGE(U4BRG); break; // Baud rate + STORAGE(U4MODE); break; // Mode + STORAGE(U4STA); // Status and control + pic32_uart_poll_status(s, 3); + break; + STORAGE(U4TXREG); *bufp = 0; break; // Transmit + STORAGE(U4MODECLR); *bufp = 0; break; + STORAGE(U4MODESET); *bufp = 0; break; + STORAGE(U4MODEINV); *bufp = 0; break; + STORAGE(U4STACLR); *bufp = 0; break; + STORAGE(U4STASET); *bufp = 0; break; + STORAGE(U4STAINV); *bufp = 0; break; + STORAGE(U4BRGCLR); *bufp = 0; break; + STORAGE(U4BRGSET); *bufp = 0; break; + STORAGE(U4BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * UART 5. + */ + STORAGE(U5RXREG); // Receive data + *bufp = pic32_uart_get_char(s, 4); + break; + STORAGE(U5BRG); break; // Baud rate + STORAGE(U5MODE); break; // Mode + STORAGE(U5STA); // Status and control + pic32_uart_poll_status(s, 4); + break; + STORAGE(U5TXREG); *bufp = 0; break; // Transmit + STORAGE(U5MODECLR); *bufp = 0; break; + STORAGE(U5MODESET); *bufp = 0; break; + STORAGE(U5MODEINV); *bufp = 0; break; + STORAGE(U5STACLR); *bufp = 0; break; + STORAGE(U5STASET); *bufp = 0; break; + STORAGE(U5STAINV); *bufp = 0; break; + STORAGE(U5BRGCLR); *bufp = 0; break; + STORAGE(U5BRGSET); *bufp = 0; break; + STORAGE(U5BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * UART 6. + */ + STORAGE(U6RXREG); // Receive data + *bufp = pic32_uart_get_char(s, 5); + break; + STORAGE(U6BRG); break; // Baud rate + STORAGE(U6MODE); break; // Mode + STORAGE(U6STA); // Status and control + pic32_uart_poll_status(s, 5); + break; + STORAGE(U6TXREG); *bufp = 0; break; // Transmit + STORAGE(U6MODECLR); *bufp = 0; break; + STORAGE(U6MODESET); *bufp = 0; break; + STORAGE(U6MODEINV); *bufp = 0; break; + STORAGE(U6STACLR); *bufp = 0; break; + STORAGE(U6STASET); *bufp = 0; break; + STORAGE(U6STAINV); *bufp = 0; break; + STORAGE(U6BRGCLR); *bufp = 0; break; + STORAGE(U6BRGSET); *bufp = 0; break; + STORAGE(U6BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * SPI 1. + */ + STORAGE(SPI1CON); break; // Control + STORAGE(SPI1CONCLR); *bufp = 0; break; + STORAGE(SPI1CONSET); *bufp = 0; break; + STORAGE(SPI1CONINV); *bufp = 0; break; + STORAGE(SPI1STAT); break; // Status + STORAGE(SPI1STATCLR); *bufp = 0; break; + STORAGE(SPI1STATSET); *bufp = 0; break; + STORAGE(SPI1STATINV); *bufp = 0; break; + STORAGE(SPI1BUF); // Buffer + *bufp = pic32_spi_readbuf(s, 0); + break; + STORAGE(SPI1BRG); break; // Baud rate + STORAGE(SPI1BRGCLR); *bufp = 0; break; + STORAGE(SPI1BRGSET); *bufp = 0; break; + STORAGE(SPI1BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * SPI 2. + */ + STORAGE(SPI2CON); break; // Control + STORAGE(SPI2CONCLR); *bufp = 0; break; + STORAGE(SPI2CONSET); *bufp = 0; break; + STORAGE(SPI2CONINV); *bufp = 0; break; + STORAGE(SPI2STAT); break; // Status + STORAGE(SPI2STATCLR); *bufp = 0; break; + STORAGE(SPI2STATSET); *bufp = 0; break; + STORAGE(SPI2STATINV); *bufp = 0; break; + STORAGE(SPI2BUF); // Buffer + *bufp = pic32_spi_readbuf(s, 1); + break; + STORAGE(SPI2BRG); break; // Baud rate + STORAGE(SPI2BRGCLR); *bufp = 0; break; + STORAGE(SPI2BRGSET); *bufp = 0; break; + STORAGE(SPI2BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * SPI 3. + */ + STORAGE(SPI3CON); break; // Control + STORAGE(SPI3CONCLR); *bufp = 0; break; + STORAGE(SPI3CONSET); *bufp = 0; break; + STORAGE(SPI3CONINV); *bufp = 0; break; + STORAGE(SPI3STAT); break; // Status + STORAGE(SPI3STATCLR); *bufp = 0; break; + STORAGE(SPI3STATSET); *bufp = 0; break; + STORAGE(SPI3STATINV); *bufp = 0; break; + STORAGE(SPI3BUF); // SPIx Buffer + *bufp = pic32_spi_readbuf(s, 2); + break; + STORAGE(SPI3BRG); break; // Baud rate + STORAGE(SPI3BRGCLR); *bufp = 0; break; + STORAGE(SPI3BRGSET); *bufp = 0; break; + STORAGE(SPI3BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * SPI 4. + */ + STORAGE(SPI4CON); break; // Control + STORAGE(SPI4CONCLR); *bufp = 0; break; + STORAGE(SPI4CONSET); *bufp = 0; break; + STORAGE(SPI4CONINV); *bufp = 0; break; + STORAGE(SPI4STAT); break; // Status + STORAGE(SPI4STATCLR); *bufp = 0; break; + STORAGE(SPI4STATSET); *bufp = 0; break; + STORAGE(SPI4STATINV); *bufp = 0; break; + STORAGE(SPI4BUF); // Buffer + *bufp = pic32_spi_readbuf(s, 3); + break; + STORAGE(SPI4BRG); break; // Baud rate + STORAGE(SPI4BRGCLR); *bufp = 0; break; + STORAGE(SPI4BRGSET); *bufp = 0; break; + STORAGE(SPI4BRGINV); *bufp = 0; break; + + default: + printf("--- Read 1f8%05x: peripheral register not supported\n", + offset); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Read 1f8%05x: peripheral register not supported\n", + offset); + exit(1); + } + return *bufp; +} + +static void io_write32(pic32_t *s, unsigned offset, unsigned data, const char **namep) +{ + unsigned *bufp = &VALUE(offset); + + switch (offset) { + /*------------------------------------------------------------------------- + * Bus matrix control registers. + */ + WRITEOP(BMXCON); return; // Bus Matrix Control + STORAGE(BMXDKPBA); break; // Data RAM kernel program base address + STORAGE(BMXDUDBA); break; // Data RAM user data base address + STORAGE(BMXDUPBA); break; // Data RAM user program base address + STORAGE(BMXPUPBA); break; // Program Flash user program base address + READONLY(BMXDRMSZ); // Data RAM memory size + READONLY(BMXPFMSZ); // Program Flash memory size + READONLY(BMXBOOTSZ); // Boot Flash size + + /*------------------------------------------------------------------------- + * Interrupt controller registers. + */ + WRITEOP(INTCON); return; // Interrupt Control + READONLY(INTSTAT); // Interrupt Status + WRITEOP(IPTMR); return; // Temporal Proximity Timer + WRITEOP(IFS0); goto irq; // IFS(0..2) - Interrupt Flag Status + WRITEOP(IFS1); goto irq; + WRITEOP(IFS2); goto irq; + WRITEOP(IEC0); goto irq; // IEC(0..2) - Interrupt Enable Control + WRITEOP(IEC1); goto irq; + WRITEOP(IEC2); goto irq; + WRITEOP(IPC0); goto irq; // IPC(0..11) - Interrupt Priority Control + WRITEOP(IPC1); goto irq; + WRITEOP(IPC2); goto irq; + WRITEOP(IPC3); goto irq; + WRITEOP(IPC4); goto irq; + WRITEOP(IPC5); goto irq; + WRITEOP(IPC6); goto irq; + WRITEOP(IPC7); goto irq; + WRITEOP(IPC8); goto irq; + WRITEOP(IPC9); goto irq; + WRITEOP(IPC10); goto irq; + WRITEOP(IPC11); goto irq; + WRITEOP(IPC12); +irq: update_irq_status(s); + return; + + /*------------------------------------------------------------------------- + * Prefetch controller. + */ + WRITEOP(CHECON); return; // Prefetch Control + + /*------------------------------------------------------------------------- + * System controller. + */ + STORAGE(OSCCON); break; // Oscillator Control + STORAGE(OSCTUN); break; // Oscillator Tuning + STORAGE(DDPCON); break; // Debug Data Port Control + READONLY(DEVID); // Device Identifier + STORAGE(SYSKEY); // System Key + /* Unlock state machine. */ + if (s->syskey_unlock == 0 && VALUE(SYSKEY) == 0xaa996655) + s->syskey_unlock = 1; + if (s->syskey_unlock == 1 && VALUE(SYSKEY) == 0x556699aa) + s->syskey_unlock = 2; + else + s->syskey_unlock = 0; + break; + STORAGE(RCON); break; // Reset Control + WRITEOP(RSWRST); // Software Reset + if (s->syskey_unlock == 2 && (VALUE(RSWRST) & 1)) { + /* Reset CPU. */ + qemu_system_reset_request(); + + /* Reset all devices */ + io_reset(s); + pic32_sdcard_reset(s); + } + break; + + /*------------------------------------------------------------------------- + * DMA controller. + */ + WRITEOP(DMACON); return; // DMA Control + STORAGE(DMASTAT); break; // DMA Status + STORAGE(DMAADDR); break; // DMA Address + + /*------------------------------------------------------------------------- + * Analog to digital converter. + */ + WRITEOP(AD1CON1); return; // Control register 1 + WRITEOP(AD1CON2); return; // Control register 2 + WRITEOP(AD1CON3); return; // Control register 3 + WRITEOP(AD1CHS); return; // Channel select + WRITEOP(AD1CSSL); return; // Input scan selection + WRITEOP(AD1PCFG); return; // Port configuration + READONLY(ADC1BUF0); // Result words + READONLY(ADC1BUF1); + READONLY(ADC1BUF2); + READONLY(ADC1BUF3); + READONLY(ADC1BUF4); + READONLY(ADC1BUF5); + READONLY(ADC1BUF6); + READONLY(ADC1BUF7); + READONLY(ADC1BUF8); + READONLY(ADC1BUF9); + READONLY(ADC1BUFA); + READONLY(ADC1BUFB); + READONLY(ADC1BUFC); + READONLY(ADC1BUFD); + READONLY(ADC1BUFE); + READONLY(ADC1BUFF); + + /*-------------------------------------- + * USB registers. + */ + STORAGE(U1OTGIR); // OTG interrupt flags + VALUE(U1OTGIR) = 0; + return; + STORAGE(U1OTGIE); break; // OTG interrupt enable + READONLY(U1OTGSTAT); // Comparator and pin status + STORAGE(U1OTGCON); break; // Resistor and pin control + STORAGE(U1PWRC); break; // Power control + STORAGE(U1IR); // Pending interrupt + VALUE(U1IR) = 0; + return; + STORAGE(U1IE); break; // Interrupt enable + STORAGE(U1EIR); // Pending error interrupt + VALUE(U1EIR) = 0; + return; + STORAGE(U1EIE); break; // Error interrupt enable + READONLY(U1STAT); // Status FIFO + STORAGE(U1CON); break; // Control + STORAGE(U1ADDR); break; // Address + STORAGE(U1BDTP1); break; // Buffer descriptor table pointer 1 + READONLY(U1FRML); // Frame counter low + READONLY(U1FRMH); // Frame counter high + STORAGE(U1TOK); break; // Host control + STORAGE(U1SOF); break; // SOF counter + STORAGE(U1BDTP2); break; // Buffer descriptor table pointer 2 + STORAGE(U1BDTP3); break; // Buffer descriptor table pointer 3 + STORAGE(U1CNFG1); break; // Debug and idle + STORAGE(U1EP(0)); break; // Endpoint control + STORAGE(U1EP(1)); break; + STORAGE(U1EP(2)); break; + STORAGE(U1EP(3)); break; + STORAGE(U1EP(4)); break; + STORAGE(U1EP(5)); break; + STORAGE(U1EP(6)); break; + STORAGE(U1EP(7)); break; + STORAGE(U1EP(8)); break; + STORAGE(U1EP(9)); break; + STORAGE(U1EP(10)); break; + STORAGE(U1EP(11)); break; + STORAGE(U1EP(12)); break; + STORAGE(U1EP(13)); break; + STORAGE(U1EP(14)); break; + STORAGE(U1EP(15)); break; + + /*------------------------------------------------------------------------- + * General purpose IO signals. + */ + WRITEOP(TRISA); return; // Port A: mask of inputs + WRITEOPX(PORTA, LATA); // Port A: write outputs + WRITEOP(LATA); // Port A: write outputs + pic32_gpio_write(s, 0, VALUE(LATA)); + return; + WRITEOP(ODCA); return; // Port A: open drain configuration + WRITEOP(TRISB); return; // Port B: mask of inputs + WRITEOPX(PORTB, LATB); // Port B: write outputs + WRITEOP(LATB); // Port B: write outputs + pic32_gpio_write(s, 1, VALUE(LATB)); + return; + WRITEOP(ODCB); return; // Port B: open drain configuration + WRITEOP(TRISC); return; // Port C: mask of inputs + WRITEOPX(PORTC, LATC); // Port C: write outputs + WRITEOP(LATC); // Port C: write outputs + pic32_gpio_write(s, 2, VALUE(LATC)); + return; + WRITEOP(ODCC); return; // Port C: open drain configuration + WRITEOP(TRISD); return; // Port D: mask of inputs + WRITEOPX(PORTD, LATD); // Port D: write outputs + WRITEOP(LATD); // Port D: write outputs + pic32_gpio_write(s, 3, VALUE(LATD)); + return; + WRITEOP(ODCD); return; // Port D: open drain configuration + WRITEOP(TRISE); return; // Port E: mask of inputs + WRITEOPX(PORTE, LATE); // Port E: write outputs + WRITEOP(LATE); // Port E: write outputs + pic32_gpio_write(s, 4, VALUE(LATE)); + return; + WRITEOP(ODCE); return; // Port E: open drain configuration + WRITEOP(TRISF); return; // Port F: mask of inputs + WRITEOPX(PORTF, LATF); // Port F: write outputs + WRITEOP(LATF); // Port F: write outputs + pic32_gpio_write(s, 5, VALUE(LATF)); + return; + WRITEOP(ODCF); return; // Port F: open drain configuration + WRITEOP(TRISG); return; // Port G: mask of inputs + WRITEOPX(PORTG, LATG); // Port G: write outputs + WRITEOP(LATG); // Port G: write outputs + pic32_gpio_write(s, 6, VALUE(LATG)); + return; + WRITEOP(ODCG); return; // Port G: open drain configuration + WRITEOP(CNCON); return; // Interrupt-on-change control + WRITEOP(CNEN); return; // Input change interrupt enable + WRITEOP(CNPUE); return; // Input pin pull-up enable + + /*------------------------------------------------------------------------- + * UART 1. + */ + STORAGE(U1TXREG); // Transmit + pic32_uart_put_char(s, 0, data); + break; + WRITEOP(U1MODE); // Mode + pic32_uart_update_mode(s, 0); + return; + WRITEOPR(U1STA, // Status and control + PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR | + PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF); + pic32_uart_update_status(s, 0); + return; + WRITEOP(U1BRG); return; // Baud rate + READONLY(U1RXREG); // Receive + + /*------------------------------------------------------------------------- + * UART 2. + */ + STORAGE(U2TXREG); // Transmit + pic32_uart_put_char(s, 1, data); + break; + WRITEOP(U2MODE); // Mode + pic32_uart_update_mode(s, 1); + return; + WRITEOPR(U2STA, // Status and control + PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR | + PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF); + pic32_uart_update_status(s, 1); + return; + WRITEOP(U2BRG); return; // Baud rate + READONLY(U2RXREG); // Receive + + /*------------------------------------------------------------------------- + * UART 3. + */ + STORAGE(U3TXREG); // Transmit + pic32_uart_put_char(s, 2, data); + break; + WRITEOP(U3MODE); // Mode + pic32_uart_update_mode(s, 2); + return; + WRITEOPR(U3STA, // Status and control + PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR | + PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF); + pic32_uart_update_status(s, 2); + return; + WRITEOP(U3BRG); return; // Baud rate + READONLY(U3RXREG); // Receive + + /*------------------------------------------------------------------------- + * UART 4. + */ + STORAGE(U4TXREG); // Transmit + pic32_uart_put_char(s, 3, data); + break; + WRITEOP(U4MODE); // Mode + pic32_uart_update_mode(s, 3); + return; + WRITEOPR(U4STA, // Status and control + PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR | + PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF); + pic32_uart_update_status(s, 3); + return; + WRITEOP(U4BRG); return; // Baud rate + READONLY(U4RXREG); // Receive + + /*------------------------------------------------------------------------- + * UART 5. + */ + STORAGE(U5TXREG); // Transmit + pic32_uart_put_char(s, 4, data); + break; + WRITEOP(U5MODE); // Mode + pic32_uart_update_mode(s, 4); + return; + WRITEOPR(U5STA, // Status and control + PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR | + PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF); + pic32_uart_update_status(s, 4); + return; + WRITEOP(U5BRG); return; // Baud rate + READONLY(U5RXREG); // Receive + + /*------------------------------------------------------------------------- + * UART 6. + */ + STORAGE(U6TXREG); // Transmit + pic32_uart_put_char(s, 5, data); + break; + WRITEOP(U6MODE); // Mode + pic32_uart_update_mode(s, 5); + return; + WRITEOPR(U6STA, // Status and control + PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR | + PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF); + pic32_uart_update_status(s, 5); + return; + WRITEOP(U6BRG); return; // Baud rate + READONLY(U6RXREG); // Receive + + /*------------------------------------------------------------------------- + * SPI. + */ + WRITEOP(SPI1CON); // Control + pic32_spi_control(s, 0); + return; + WRITEOPR(SPI1STAT, ~PIC32_SPISTAT_SPIROV); // Status + return; // Only ROV bit is writable + STORAGE(SPI1BUF); // Buffer + pic32_spi_writebuf(s, 0, data); + return; + WRITEOP(SPI1BRG); return; // Baud rate + WRITEOP(SPI2CON); // Control + pic32_spi_control(s, 1); + return; + WRITEOPR(SPI2STAT, ~PIC32_SPISTAT_SPIROV); // Status + return; // Only ROV bit is writable + STORAGE(SPI2BUF); // Buffer + pic32_spi_writebuf(s, 1, data); + return; + WRITEOP(SPI2BRG); return; // Baud rate + WRITEOP(SPI3CON); // Control + pic32_spi_control(s, 2); + return; + WRITEOPR(SPI3STAT, ~PIC32_SPISTAT_SPIROV); // Status + return; // Only ROV bit is writable + STORAGE(SPI3BUF); // Buffer + pic32_spi_writebuf(s, 2, data); + return; + WRITEOP(SPI3BRG); return; // Baud rate + WRITEOP(SPI4CON); // Control + pic32_spi_control(s, 3); + return; + WRITEOPR(SPI4STAT, ~PIC32_SPISTAT_SPIROV); // Status + return; // Only ROV bit is writable + STORAGE(SPI4BUF); // Buffer + pic32_spi_writebuf(s, 3, data); + return; + WRITEOP(SPI4BRG); return; // Baud rate + + default: + printf("--- Write %08x to 1f8%05x: peripheral register not supported\n", + data, offset); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Write %08x to 1f8%05x: peripheral register not supported\n", + data, offset); + exit(1); +readonly: + printf("--- Write %08x to %s: readonly register\n", + data, *namep); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Write %08x to %s: readonly register\n", + data, *namep); + *namep = 0; + return; + } + *bufp = data; +} + +static uint64_t pic32_io_read(void *opaque, hwaddr addr, unsigned bytes) +{ + pic32_t *s = opaque; + uint32_t offset = addr & 0xfffff; + const char *name = "???"; + uint32_t data = 0; + + data = io_read32(s, offset & ~3, &name); + switch (bytes) { + case 1: + if ((offset &= 3) != 0) { + // Unaligned read. + data >>= offset * 8; + } + data = (uint8_t) data; + if (qemu_loglevel_mask(CPU_LOG_INSTR)) { + fprintf(qemu_logfile, "--- I/O Read %02x from %s\n", data, name); + } + break; + case 2: + if (offset & 2) { + // Unaligned read. + data >>= 16; + } + data = (uint16_t) data; + if (qemu_loglevel_mask(CPU_LOG_INSTR)) { + fprintf(qemu_logfile, "--- I/O Read %04x from %s\n", data, name); + } + break; + default: + if (qemu_loglevel_mask(CPU_LOG_INSTR)) { + fprintf(qemu_logfile, "--- I/O Read %08x from %s\n", data, name); + } + break; + } + return data; +} + +static void pic32_io_write(void *opaque, hwaddr addr, uint64_t data, unsigned bytes) +{ + pic32_t *s = opaque; + uint32_t offset = addr & 0xfffff; + const char *name = "???"; + + // Fetch data and align to word format. + switch (bytes) { + case 1: + data = (uint8_t) data; + data <<= (offset & 3) * 8; + break; + case 2: + data = (uint16_t) data; + data <<= (offset & 2) * 8; + break; + } + io_write32(s, offset & ~3, data, &name); + + if (qemu_loglevel_mask(CPU_LOG_INSTR) && name != 0) { + fprintf(qemu_logfile, "--- I/O Write %08x to %s\n", + (uint32_t) data, name); + } +} + +static const MemoryRegionOps pic32_io_ops = { + .read = pic32_io_read, + .write = pic32_io_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void main_cpu_reset(void *opaque) +{ + MIPSCPU *cpu = opaque; + CPUMIPSState *env = &cpu->env; + int i; + + cpu_reset(CPU(cpu)); + + /* Adjust the initial configuration for M4K core. */ + env->CP0_IntCtl = 0; + env->CP0_Debug = (1 << CP0DB_CNT) | (3 << CP0DB_VER); + for (i=0; i<7; i++) + env->CP0_WatchHi[i] = 0; +} + +static void store_byte(unsigned address, unsigned char byte) +{ + if (address >= PROGRAM_FLASH_START && + address < PROGRAM_FLASH_START + PROGRAM_FLASH_SIZE) + { + //printf("Store %02x to program memory %08x\n", byte, address); + prog_ptr[address & 0xfffff] = byte; + } + else if (address >= BOOT_FLASH_START && + address < BOOT_FLASH_START + BOOT_FLASH_SIZE) + { + //printf("Store %02x to boot memory %08x\n", byte, address); + boot_ptr[address & 0xffff] = byte; + } + else { + printf("Bad hex file: incorrect address %08X, must be %08X-%08X or %08X-%08X\n", + address, PROGRAM_FLASH_START, + PROGRAM_FLASH_START + PROGRAM_FLASH_SIZE - 1, + BOOT_FLASH_START, BOOT_FLASH_START + BOOT_FLASH_SIZE - 1); + exit(1); + } +} + +/* + * Ignore ^C and ^\ signals and pass these characters to the target. + */ +static void pic32_pass_signal_chars(void) +{ + struct termios tty; + + tcgetattr(0, &tty); + tty.c_lflag &= ~ISIG; + tcsetattr(0, TCSANOW, &tty); +} + +static void pic32_init(MachineState *machine, int board_type) +{ + const char *cpu_model = machine->cpu_model; + unsigned ram_size = DATA_MEM_SIZE; + MemoryRegion *system_memory = get_system_memory(); + MemoryRegion *ram_main = g_new(MemoryRegion, 1); + MemoryRegion *prog_mem = g_new(MemoryRegion, 1); + MemoryRegion *boot_mem = g_new(MemoryRegion, 1); + MemoryRegion *io_mem = g_new(MemoryRegion, 1); + MIPSCPU *cpu; + CPUMIPSState *env; + + DeviceState *dev = qdev_create(NULL, TYPE_MIPS_PIC32); + pic32_t *s = OBJECT_CHECK(pic32_t, dev, TYPE_MIPS_PIC32); + s->board_type = board_type; + s->stop_on_reset = 1; /* halt simulation on soft reset */ + s->iomem = g_malloc0(IO_MEM_SIZE); /* backing storage for I/O area */ + + qdev_init_nofail(dev); + + /* Init CPU. */ + if (! cpu_model) { + cpu_model = "M4K"; + } + printf("Board: %s\n", board_name[board_type]); + if (qemu_logfile) + fprintf(qemu_logfile, "Board: %s\n", board_name[board_type]); + + printf("Processor: %s\n", cpu_model); + if (qemu_logfile) + fprintf(qemu_logfile, "Processor: %s\n", cpu_model); + + cpu = cpu_mips_init(cpu_model); + if (! cpu) { + fprintf(stderr, "Unable to find CPU definition\n"); + exit(1); + } + s->cpu = cpu; + env = &cpu->env; + + /* Register RAM */ + printf("RAM size: %u kbytes\n", ram_size / 1024); + if (qemu_logfile) + fprintf(qemu_logfile, "RAM size: %u kbytes\n", ram_size / 1024); + + memory_region_init_ram(ram_main, NULL, "kernel.ram", + ram_size, &error_abort); + vmstate_register_ram_global(ram_main); + memory_region_add_subregion(system_memory, DATA_MEM_START, ram_main); + + /* Alias for user space 96 kbytes. + * For MX family only. */ + MemoryRegion *ram_user = g_new(MemoryRegion, 1); + memory_region_init_alias(ram_user, NULL, "user.ram", + ram_main, 0x8000, ram_size - 0x8000); + memory_region_add_subregion(system_memory, USER_MEM_START + 0x8000, ram_user); + + /* Special function registers. */ + memory_region_init_io(io_mem, NULL, &pic32_io_ops, s, + "io", IO_MEM_SIZE); + memory_region_add_subregion(system_memory, IO_MEM_START, io_mem); + + /* + * Map the flash memory. + */ + memory_region_init_ram(boot_mem, NULL, "boot.flash", BOOT_FLASH_SIZE, &error_abort); + memory_region_init_ram(prog_mem, NULL, "prog.flash", PROGRAM_FLASH_SIZE, &error_abort); + + /* Load a Flash memory image. */ + if (! machine->kernel_filename) { + error_report("No -kernel argument was specified."); + exit(1); + } + prog_ptr = memory_region_get_ram_ptr(prog_mem); + boot_ptr = memory_region_get_ram_ptr(boot_mem); + if (bios_name) + pic32_load_hex_file(bios_name, store_byte); + pic32_load_hex_file(machine->kernel_filename, store_byte); + + memory_region_set_readonly(boot_mem, true); + memory_region_set_readonly(prog_mem, true); + memory_region_add_subregion(system_memory, BOOT_FLASH_START, boot_mem); + memory_region_add_subregion(system_memory, PROGRAM_FLASH_START, prog_mem); + + /* Init internal devices */ + s->irq_raise = irq_raise; + s->irq_clear = irq_clear; + qemu_register_reset(main_cpu_reset, cpu); + + /* Setup interrupt controller in EIC mode. */ + env->CP0_Config3 |= 1 << CP0C3_VEIC; + cpu_mips_irq_init_cpu(env); + env->eic_timer_irq = pic32_timer_irq; + env->eic_soft_irq = pic32_soft_irq; + env->eic_context = s; + + /* CPU runs at 80MHz. + * Count register increases at half this rate. */ + cpu_mips_clock_init(env, 40*1000*1000); + + /* + * Initialize board-specific parameters. + */ + int cs0_port, cs0_pin, cs1_port, cs1_pin; + switch (board_type) { + default: + case BOARD_MAX32: + BOOTMEM(DEVCFG0) = 0xffffff7f; // Max32 board + BOOTMEM(DEVCFG1) = 0x5bfd6aff; // console on UART1 + BOOTMEM(DEVCFG2) = 0xd979f8f9; + BOOTMEM(DEVCFG3) = 0xffff0722; + VALUE(DEVID) = 0x04307053; // MX795F512L + VALUE(OSCCON) = 0x01453320; // external oscillator 8MHz + s->sdcard_spi_port = 3; // SD card at SPI4, + cs0_port = 3; cs0_pin = 3; // select0 at D3, + cs1_port = 3; cs1_pin = 4; // select1 at D4 + break; + case BOARD_MAXIMITE: + BOOTMEM(DEVCFG0) = 0xffffff7f; // TODO: get real data from Maximite board + BOOTMEM(DEVCFG1) = 0x5bfd6aff; // console on UART1 + BOOTMEM(DEVCFG2) = 0xd979f8f9; + BOOTMEM(DEVCFG3) = 0xffff0722; + VALUE(DEVID) = 0x04307053; // MX795F512L + VALUE(OSCCON) = 0x01453320; // external oscillator 8MHz + s->sdcard_spi_port = 3; // SD card at SPI4, + cs0_port = 4; cs0_pin = 0; // select0 at E0, + cs1_port = -1; cs1_pin = -1; // select1 not available + break; + case BOARD_EXPLORER16: + BOOTMEM(DEVCFG0) = 0xffffff7f; // TODO: get real data from Explorer16 board + BOOTMEM(DEVCFG1) = 0x5bfd6aff; // console on UART2 + BOOTMEM(DEVCFG2) = 0xd979f8f9; + BOOTMEM(DEVCFG3) = 0xffff0722; + VALUE(DEVID) = 0x04307053; // MX795F512L + VALUE(OSCCON) = 0x01453320; // external oscillator 8MHz + s->sdcard_spi_port = 0; // SD card at SPI1, + cs0_port = 1; cs0_pin = 1; // select0 at B1, + cs1_port = 1; cs1_pin = 2; // select1 at B2 + break; + } + + /* UARTs */ + pic32_uart_init(s, 0, PIC32_IRQ_U1E, U1STA, U1MODE); + pic32_uart_init(s, 1, PIC32_IRQ_U2E, U2STA, U2MODE); + pic32_uart_init(s, 2, PIC32_IRQ_U3E, U3STA, U3MODE); + pic32_uart_init(s, 3, PIC32_IRQ_U4E, U4STA, U4MODE); + pic32_uart_init(s, 4, PIC32_IRQ_U5E, U5STA, U5MODE); + pic32_uart_init(s, 5, PIC32_IRQ_U6E, U6STA, U6MODE); + + /* SPIs */ + pic32_spi_init(s, 0, PIC32_IRQ_SPI1E, SPI1CON, SPI1STAT); + pic32_spi_init(s, 1, PIC32_IRQ_SPI2E, SPI2CON, SPI2STAT); + pic32_spi_init(s, 2, PIC32_IRQ_SPI3E, SPI3CON, SPI3STAT); + pic32_spi_init(s, 3, PIC32_IRQ_SPI4E, SPI4CON, SPI4STAT); + + /* + * Load SD card images. + * Use options: + * -sd filename + * or -hda filename + * and -hdb filename + */ + const char *sd0_file = 0, *sd1_file = 0; + DriveInfo *dinfo = drive_get(IF_IDE, 0, 0); + if (dinfo) { + sd0_file = qemu_opt_get(dinfo->opts, "file"); + dinfo->is_default = 1; + + dinfo = drive_get(IF_IDE, 0, 1); + if (dinfo) { + sd1_file = qemu_opt_get(dinfo->opts, "file"); + dinfo->is_default = 1; + } + } + if (! sd0_file) { + dinfo = drive_get(IF_SD, 0, 0); + if (dinfo) { + sd0_file = qemu_opt_get(dinfo->opts, "file"); + dinfo->is_default = 1; + } + } + pic32_sdcard_init(s, 0, "sd0", sd0_file, cs0_port, cs0_pin); + pic32_sdcard_init(s, 1, "sd1", sd1_file, cs1_port, cs1_pin); + + io_reset(s); + pic32_sdcard_reset(s); + pic32_pass_signal_chars(); +} + +static void pic32_init_max32(MachineState *machine) +{ + pic32_init(machine, BOARD_MAX32); +} + +static void pic32_init_maximite(MachineState *machine) +{ + pic32_init(machine, BOARD_MAXIMITE); +} + +static void pic32_init_explorer16(MachineState *machine) +{ + pic32_init(machine, BOARD_EXPLORER16); +} + +static int pic32_sysbus_device_init(SysBusDevice *sysbusdev) +{ + return 0; +} + +static void pic32_class_init(ObjectClass *klass, void *data) +{ + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pic32_sysbus_device_init; +} + +static const TypeInfo pic32_device = { + .name = TYPE_MIPS_PIC32, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(pic32_t), + .class_init = pic32_class_init, +}; + +static void pic32_register_types(void) +{ + type_register_static(&pic32_device); +} + +static QEMUMachine pic32_board[3] = { + { + .name = "pic32mx7-max32", + .desc = "PIC32MX7 microcontroller on chipKIT Max32 board", + .init = pic32_init_max32, + .max_cpus = 1, + }, + { + .name = "pic32mx7-maximite", + .desc = "PIC32MX7 microcontroller on Geoff's Maximite board", + .init = pic32_init_maximite, + .max_cpus = 1, + }, + { + .name = "pic32mx7-explorer16", + .desc = "PIC32MX7 microcontroller on Microchip Explorer-16 board", + .init = pic32_init_explorer16, + .max_cpus = 1, + }, +}; + +static void pic32_machine_init(void) +{ + qemu_register_machine(&pic32_board[0]); + qemu_register_machine(&pic32_board[1]); + qemu_register_machine(&pic32_board[2]); +} + +type_init(pic32_register_types) +machine_init(pic32_machine_init); + +#endif /* !TARGET_MIPS64 && !TARGET_WORDS_BIGENDIAN */ diff --git a/hw/mips/mips_pic32mz.c b/hw/mips/mips_pic32mz.c new file mode 100644 index 0000000000000..d25beef55f2a9 --- /dev/null +++ b/hw/mips/mips_pic32mz.c @@ -0,0 +1,2093 @@ +/* + * QEMU support for Microchip PIC32MZ microcontroller. + * + * Copyright (c) 2015 Serge Vakulenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* Only 32-bit little endian mode supported. */ +#include "config.h" +#if !defined TARGET_MIPS64 && !defined TARGET_WORDS_BIGENDIAN + +#include "hw/i386/pc.h" +#include "hw/char/serial.h" +#include "hw/mips/cpudevs.h" +#include "sysemu/char.h" +#include "hw/loader.h" +#include "qemu/error-report.h" +#include "hw/empty_slot.h" +#include + +#include "pic32mz.h" +#include "pic32_peripherals.h" + +/* Hardware addresses */ +#define PROGRAM_FLASH_START 0x1d000000 +#define BOOT_FLASH_START 0x1fc00000 +#define DATA_MEM_START 0x00000000 +#define IO_MEM_START 0x1f800000 + +#define PROGRAM_FLASH_SIZE (2*1024*1024) // 2 Mbytes +#define BOOT_FLASH_SIZE (64*1024) // 64 kbytes +#define DATA_MEM_SIZE (512*1024) // 512 kbytes + +#define TYPE_MIPS_PIC32 "mips-pic32mz" + +/* + * Board variants. + */ +enum { + BOARD_WIFIRE, /* chipKIT WiFire board */ + BOARD_MEBII, /* Microchip MEB-II board */ + BOARD_EXPLORER16, /* Microchip Explorer-16 board */ +}; + +static const char *board_name[] = { + "chipKIT WiFire", + "Microchip MEB-II", + "Microchip Explorer16", +}; + +/* + * Pointers to Flash memory contents. + */ +static char *prog_ptr; +static char *boot_ptr; + +#define BOOTMEM(addr) ((uint32_t*) boot_ptr) [(addr & 0xffff) >> 2] + +static void update_irq_status(pic32_t *s) +{ + /* Assume no interrupts pending. */ + int cause_ripl = 0; + int vector = 0; + CPUMIPSState *env = &s->cpu->env; + int current_ripl = (env->CP0_Cause >> (CP0Ca_IP + 2)) & 0x3f; + + VALUE(INTSTAT) = 0; + + if ((VALUE(IFS0) & VALUE(IEC0)) || + (VALUE(IFS1) & VALUE(IEC1)) || + (VALUE(IFS2) & VALUE(IEC2)) || + (VALUE(IFS3) & VALUE(IEC3)) || + (VALUE(IFS4) & VALUE(IEC4)) || + (VALUE(IFS5) & VALUE(IEC5))) + { + /* Find the most prioritive pending interrupt, + * it's vector and level. */ + int irq; + for (irq=0; irq<=PIC32_IRQ_LAST; irq++) { + int n = irq >> 5; + + if (((VALUE(IFS(n)) & VALUE(IEC(n))) >> (irq & 31)) & 1) { + /* Interrupt is pending. */ + int level = VALUE(IPC(irq >> 2)); + level >>= 2 + (irq & 3) * 8; + level &= 7; + if (level > cause_ripl) { + vector = irq; + cause_ripl = level; + } + } + } + VALUE(INTSTAT) = vector | (cause_ripl << 8); + } + + if (cause_ripl == current_ripl) + return; + + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Priority level Cause.RIPL = %u\n", + cause_ripl); + + /* + * Modify Cause.RIPL field and take EIC interrupt. + */ + env->CP0_Cause &= ~(0x3f << (CP0Ca_IP + 2)); + env->CP0_Cause |= cause_ripl << (CP0Ca_IP + 2); + cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HARD); +} + +/* + * Set interrupt flag status + */ +static void irq_raise(pic32_t *s, int irq) +{ + if (VALUE(IFS(irq >> 5)) & (1 << (irq & 31))) + return; + + VALUE(IFS(irq >> 5)) |= 1 << (irq & 31); + update_irq_status(s); +} + +/* + * Clear interrupt flag status + */ +static void irq_clear(pic32_t *s, int irq) +{ + if (! (VALUE(IFS(irq >> 5)) & (1 << (irq & 31)))) + return; + + VALUE(IFS(irq >> 5)) &= ~(1 << (irq & 31)); + update_irq_status(s); +} + +/* + * Timer interrupt. + */ +static void pic32_timer_irq(CPUMIPSState *env, int raise) +{ + pic32_t *s = env->eic_context; + + if (raise) { + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- %08x: Timer interrupt\n", + env->active_tc.PC); + irq_raise(s, 0); + } else { + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Clear timer interrupt\n"); + irq_clear(s, 0); + } +} + +/* + * Software interrupt. + */ +static void pic32_soft_irq(CPUMIPSState *env, int num) +{ + pic32_t *s = env->eic_context; + + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- %08x: Soft interrupt %u\n", + env->active_tc.PC, num); + irq_raise(s, num + 1); +} + +/* + * Perform an assign/clear/set/invert operation. + */ +static inline unsigned write_op(int a, int b, int op) +{ + switch (op & 0xc) { + case 0x0: a = b; break; // Assign + case 0x4: a &= ~b; break; // Clear + case 0x8: a |= b; break; // Set + case 0xc: a ^= b; break; // Invert + } + return a; +} + +static void io_reset(pic32_t *s) +{ + int i; + + /* + * Prefetch controller. + */ + VALUE(PRECON) = 0x00000007; + + /* + * System controller. + */ + s->syskey_unlock = 0; + VALUE(CFGCON) = PIC32_CFGCON_ECC_DISWR | PIC32_CFGCON_TDOEN; + VALUE(SYSKEY) = 0; + VALUE(RCON) = 0; + VALUE(RSWRST) = 0; + VALUE(OSCTUN) = 0; + VALUE(SPLLCON)= 0x01310201; + VALUE(PB1DIV) = 0x00008801; + VALUE(PB2DIV) = 0x00008801; + VALUE(PB3DIV) = 0x00008801; + VALUE(PB4DIV) = 0x00008801; + VALUE(PB5DIV) = 0x00008801; + VALUE(PB7DIV) = 0x00008800; + VALUE(PB8DIV) = 0x00008801; + + /* + * General purpose IO signals. + * All pins are inputs, high, open drains and pullups disabled. + * No interrupts on change. + */ + VALUE(ANSELA) = 0xFFFF; // Port A: analog select + VALUE(TRISA) = 0xFFFF; // Port A: mask of inputs + VALUE(PORTA) = 0xFFCF; // Port A: read inputs, write outputs + VALUE(LATA) = 0xFFFF; // Port A: read/write outputs + VALUE(ODCA) = 0; // Port A: open drain configuration + VALUE(CNPUA) = 0; // Input pin pull-up + VALUE(CNPDA) = 0; // Input pin pull-down + VALUE(CNCONA) = 0; // Interrupt-on-change control + VALUE(CNENA) = 0; // Input change interrupt enable + VALUE(CNSTATA) = 0; // Input change status + + VALUE(ANSELB) = 0xFFFF; // Port B: analog select + VALUE(TRISB) = 0xFFFF; // Port B: mask of inputs + VALUE(PORTB) = 0xFFFF; // Port B: read inputs, write outputs + VALUE(LATB) = 0xFFFF; // Port B: read/write outputs + VALUE(ODCB) = 0; // Port B: open drain configuration + VALUE(CNPUB) = 0; // Input pin pull-up + VALUE(CNPDB) = 0; // Input pin pull-down + VALUE(CNCONB) = 0; // Interrupt-on-change control + VALUE(CNENB) = 0; // Input change interrupt enable + VALUE(CNSTATB) = 0; // Input change status + + VALUE(ANSELC) = 0xFFFF; // Port C: analog select + VALUE(TRISC) = 0xFFFF; // Port C: mask of inputs + VALUE(PORTC) = 0xFFFF; // Port C: read inputs, write outputs + VALUE(LATC) = 0xFFFF; // Port C: read/write outputs + if (s->board_type == BOARD_WIFIRE) + VALUE(LATC) ^= 0x1000; // Disable latc[15] for the chipKIT bootloader + VALUE(ODCC) = 0; // Port C: open drain configuration + VALUE(CNPUC) = 0; // Input pin pull-up + VALUE(CNPDC) = 0; // Input pin pull-down + VALUE(CNCONC) = 0; // Interrupt-on-change control + VALUE(CNENC) = 0; // Input change interrupt enable + VALUE(CNSTATC) = 0; // Input change status + + VALUE(ANSELD) = 0xFFFF; // Port D: analog select + VALUE(TRISD) = 0xFFFF; // Port D: mask of inputs + VALUE(PORTD) = 0xFFFF; // Port D: read inputs, write outputs + VALUE(LATD) = 0xFFFF; // Port D: read/write outputs + VALUE(ODCD) = 0; // Port D: open drain configuration + VALUE(CNPUD) = 0; // Input pin pull-up + VALUE(CNPDD) = 0; // Input pin pull-down + VALUE(CNCOND) = 0; // Interrupt-on-change control + VALUE(CNEND) = 0; // Input change interrupt enable + VALUE(CNSTATD) = 0; // Input change status + + VALUE(ANSELE) = 0xFFFF; // Port E: analog select + VALUE(TRISE) = 0xFFFF; // Port E: mask of inputs + VALUE(PORTE) = 0xFFFF; // Port E: read inputs, write outputs + VALUE(LATE) = 0xFFFF; // Port E: read/write outputs + VALUE(ODCE) = 0; // Port E: open drain configuration + VALUE(CNPUE) = 0; // Input pin pull-up + VALUE(CNPDE) = 0; // Input pin pull-down + VALUE(CNCONE) = 0; // Interrupt-on-change control + VALUE(CNENE) = 0; // Input change interrupt enable + VALUE(CNSTATE) = 0; // Input change status + + VALUE(ANSELF) = 0xFFFF; // Port F: analog select + VALUE(TRISF) = 0xFFFF; // Port F: mask of inputs + VALUE(PORTF) = 0xFFFF; // Port F: read inputs, write outputs + VALUE(LATF) = 0xFFFF; // Port F: read/write outputs + VALUE(ODCF) = 0; // Port F: open drain configuration + VALUE(CNPUF) = 0; // Input pin pull-up + VALUE(CNPDF) = 0; // Input pin pull-down + VALUE(CNCONF) = 0; // Interrupt-on-change control + VALUE(CNENF) = 0; // Input change interrupt enable + VALUE(CNSTATF) = 0; // Input change status + + VALUE(ANSELG) = 0xFFFF; // Port G: analog select + VALUE(TRISG) = 0xFFFF; // Port G: mask of inputs + VALUE(PORTG) = 0xFFFF; // Port G: read inputs, write outputs + VALUE(LATG) = 0xFFFF; // Port G: read/write outputs + VALUE(ODCG) = 0; // Port G: open drain configuration + VALUE(CNPUG) = 0; // Input pin pull-up + VALUE(CNPDG) = 0; // Input pin pull-down + VALUE(CNCONG) = 0; // Interrupt-on-change control + VALUE(CNENG) = 0; // Input change interrupt enable + VALUE(CNSTATG) = 0; // Input change status + + /* + * Reset UARTs. + */ + VALUE(U1MODE) = 0; + VALUE(U1STA) = PIC32_USTA_RIDLE | PIC32_USTA_TRMT; + VALUE(U1TXREG) = 0; + VALUE(U1RXREG) = 0; + VALUE(U1BRG) = 0; + VALUE(U2MODE) = 0; + VALUE(U2STA) = PIC32_USTA_RIDLE | PIC32_USTA_TRMT; + VALUE(U2TXREG) = 0; + VALUE(U2RXREG) = 0; + VALUE(U2BRG) = 0; + VALUE(U3MODE) = 0; + VALUE(U3STA) = PIC32_USTA_RIDLE | PIC32_USTA_TRMT; + VALUE(U3TXREG) = 0; + VALUE(U3RXREG) = 0; + VALUE(U3BRG) = 0; + VALUE(U4MODE) = 0; + VALUE(U4STA) = PIC32_USTA_RIDLE | PIC32_USTA_TRMT; + VALUE(U4TXREG) = 0; + VALUE(U4RXREG) = 0; + VALUE(U4BRG) = 0; + VALUE(U5MODE) = 0; + VALUE(U5STA) = PIC32_USTA_RIDLE | PIC32_USTA_TRMT; + VALUE(U5TXREG) = 0; + VALUE(U5RXREG) = 0; + VALUE(U5BRG) = 0; + VALUE(U6MODE) = 0; + VALUE(U6STA) = PIC32_USTA_RIDLE | PIC32_USTA_TRMT; + VALUE(U6TXREG) = 0; + VALUE(U6RXREG) = 0; + VALUE(U6BRG) = 0; + + /* + * Reset SPI. + */ + VALUE(SPI1CON) = 0; + VALUE(SPI1STAT) = PIC32_SPISTAT_SPITBE; // Transmit buffer is empty + VALUE(SPI1BRG) = 0; + + VALUE(SPI2CON) = 0; + VALUE(SPI2STAT) = PIC32_SPISTAT_SPITBE; // Transmit buffer is empty + VALUE(SPI2BRG) = 0; + + VALUE(SPI3CON) = 0; + VALUE(SPI3STAT) = PIC32_SPISTAT_SPITBE; // Transmit buffer is empty + VALUE(SPI3BRG) = 0; + + VALUE(SPI4CON) = 0; + VALUE(SPI4STAT) = PIC32_SPISTAT_SPITBE; // Transmit buffer is empty + VALUE(SPI4BRG) = 0; + + VALUE(SPI5CON) = 0; + VALUE(SPI5STAT) = PIC32_SPISTAT_SPITBE; // Transmit buffer is empty + VALUE(SPI5BRG) = 0; + + VALUE(SPI6CON) = 0; + VALUE(SPI6STAT) = PIC32_SPISTAT_SPITBE; // Transmit buffer is empty + VALUE(SPI6BRG) = 0; + + VALUE(SPI1CON2) = 0; + VALUE(SPI2CON2) = 0; + VALUE(SPI3CON2) = 0; + VALUE(SPI4CON2) = 0; + VALUE(SPI5CON2) = 0; + VALUE(SPI6CON2) = 0; + + for (i=0; ispi[i].rfifo = 0; + s->spi[i].wfifo = 0; + } + + /* + * Reset Ethernet. + */ + VALUE(ETHCON1) = 0; // Control 1 + VALUE(ETHCON2) = 0; // Control 2: RX data buffer size + VALUE(ETHTXST) = 0; // Tx descriptor start address + VALUE(ETHRXST) = 0; // Rx descriptor start address + VALUE(ETHHT0) = 0; // Hash tasble 0 + VALUE(ETHHT1) = 0; // Hash tasble 1 + VALUE(ETHPMM0) = 0; // Pattern match mask 0 + VALUE(ETHPMM1) = 0; // Pattern match mask 1 + VALUE(ETHPMCS) = 0; // Pattern match checksum + VALUE(ETHPMO) = 0; // Pattern match offset + VALUE(ETHRXFC) = 0; // Receive filter configuration + VALUE(ETHRXWM) = 0; // Receive watermarks + VALUE(ETHIEN) = 0; // Interrupt enable + VALUE(ETHIRQ) = 0; // Interrupt request + VALUE(ETHSTAT) = 0; // Status + VALUE(ETHRXOVFLOW) = 0; // Receive overflow statistics + VALUE(ETHFRMTXOK) = 0; // Frames transmitted OK statistics + VALUE(ETHSCOLFRM) = 0; // Single collision frames statistics + VALUE(ETHMCOLFRM) = 0; // Multiple collision frames statistics + VALUE(ETHFRMRXOK) = 0; // Frames received OK statistics + VALUE(ETHFCSERR) = 0; // Frame check sequence error statistics + VALUE(ETHALGNERR) = 0; // Alignment errors statistics + VALUE(EMAC1CFG1) = 0x800d; // MAC configuration 1 + VALUE(EMAC1CFG2) = 0x4082; // MAC configuration 2 + VALUE(EMAC1IPGT) = 0x0012; // MAC back-to-back interpacket gap + VALUE(EMAC1IPGR) = 0x0c12; // MAC non-back-to-back interpacket gap + VALUE(EMAC1CLRT) = 0x370f; // MAC collision window/retry limit + VALUE(EMAC1MAXF) = 0x05ee; // MAC maximum frame length + VALUE(EMAC1SUPP) = 0x1000; // MAC PHY support + VALUE(EMAC1TEST) = 0; // MAC test + VALUE(EMAC1MCFG) = 0x0020; // MII configuration + VALUE(EMAC1MCMD) = 0; // MII command + VALUE(EMAC1MADR) = 0x0100; // MII address + VALUE(EMAC1MWTD) = 0; // MII write data + VALUE(EMAC1MRDD) = 0; // MII read data + VALUE(EMAC1MIND) = 0; // MII indicators + VALUE(EMAC1SA0) = 0x79c1; // MAC station address 0 + VALUE(EMAC1SA1) = 0xcbc0; // MAC station address 1 + VALUE(EMAC1SA2) = 0x1e00; // MAC station address 2 +} + +static unsigned io_read32(pic32_t *s, unsigned offset, const char **namep) +{ + unsigned *bufp = &VALUE(offset); + + switch (offset) { + /*------------------------------------------------------------------------- + * Interrupt controller registers. + */ + STORAGE(INTCON); break; // Interrupt Control + STORAGE(INTSTAT); break; // Interrupt Status + STORAGE(IFS0); break; // IFS(0..2) - Interrupt Flag Status + STORAGE(IFS1); break; + STORAGE(IFS2); break; + STORAGE(IFS3); break; + STORAGE(IFS4); break; + STORAGE(IFS5); break; + STORAGE(IEC0); break; // IEC(0..2) - Interrupt Enable Control + STORAGE(IEC1); break; + STORAGE(IEC2); break; + STORAGE(IEC3); break; + STORAGE(IEC4); break; + STORAGE(IEC5); break; + STORAGE(IPC0); break; // IPC(0..11) - Interrupt Priority Control + STORAGE(IPC1); break; + STORAGE(IPC2); break; + STORAGE(IPC3); break; + STORAGE(IPC4); break; + STORAGE(IPC5); break; + STORAGE(IPC6); break; + STORAGE(IPC7); break; + STORAGE(IPC8); break; + STORAGE(IPC9); break; + STORAGE(IPC10); break; + STORAGE(IPC11); break; + STORAGE(IPC12); break; + STORAGE(IPC13); break; + STORAGE(IPC14); break; + STORAGE(IPC15); break; + STORAGE(IPC16); break; + STORAGE(IPC17); break; + STORAGE(IPC18); break; + STORAGE(IPC19); break; + STORAGE(IPC20); break; + STORAGE(IPC21); break; + STORAGE(IPC22); break; + STORAGE(IPC23); break; + STORAGE(IPC24); break; + STORAGE(IPC25); break; + STORAGE(IPC26); break; + STORAGE(IPC27); break; + STORAGE(IPC28); break; + STORAGE(IPC29); break; + STORAGE(IPC30); break; + STORAGE(IPC31); break; + STORAGE(IPC32); break; + STORAGE(IPC33); break; + STORAGE(IPC34); break; + STORAGE(IPC35); break; + STORAGE(IPC36); break; + STORAGE(IPC37); break; + STORAGE(IPC38); break; + STORAGE(IPC39); break; + STORAGE(IPC40); break; + STORAGE(IPC41); break; + STORAGE(IPC42); break; + STORAGE(IPC43); break; + STORAGE(IPC44); break; + STORAGE(IPC45); break; + STORAGE(IPC46); break; + STORAGE(IPC47); break; + + /*------------------------------------------------------------------------- + * Prefetch controller. + */ + STORAGE(PRECON); break; // Prefetch Control + STORAGE(PRESTAT); break; // Prefetch Status + + /*------------------------------------------------------------------------- + * System controller. + */ + STORAGE(CFGCON); break; // Configuration Control + STORAGE(DEVID); break; // Device Identifier + STORAGE(SYSKEY); break; // System Key + STORAGE(RCON); break; // Reset Control + STORAGE(RSWRST); // Software Reset + if ((VALUE(RSWRST) & 1) && s->stop_on_reset) { + exit(0); + } + break; + STORAGE(OSCCON); break; // Oscillator Control + STORAGE(OSCTUN); break; // Oscillator Tuning + STORAGE(SPLLCON); break; // System PLL Control + STORAGE(PB1DIV); break; // Peripheral bus 1 divisor + STORAGE(PB2DIV); break; // Peripheral bus 2 divisor + STORAGE(PB3DIV); break; // Peripheral bus 3 divisor + STORAGE(PB4DIV); break; // Peripheral bus 4 divisor + STORAGE(PB5DIV); break; // Peripheral bus 5 divisor + STORAGE(PB7DIV); break; // Peripheral bus 7 divisor + STORAGE(PB8DIV); break; // Peripheral bus 8 divisor + + /*------------------------------------------------------------------------- + * Peripheral port select registers: input. + */ + STORAGE(INT1R); break; + STORAGE(INT2R); break; + STORAGE(INT3R); break; + STORAGE(INT4R); break; + STORAGE(T2CKR); break; + STORAGE(T3CKR); break; + STORAGE(T4CKR); break; + STORAGE(T5CKR); break; + STORAGE(T6CKR); break; + STORAGE(T7CKR); break; + STORAGE(T8CKR); break; + STORAGE(T9CKR); break; + STORAGE(IC1R); break; + STORAGE(IC2R); break; + STORAGE(IC3R); break; + STORAGE(IC4R); break; + STORAGE(IC5R); break; + STORAGE(IC6R); break; + STORAGE(IC7R); break; + STORAGE(IC8R); break; + STORAGE(IC9R); break; + STORAGE(OCFAR); break; + STORAGE(U1RXR); break; + STORAGE(U1CTSR); break; + STORAGE(U2RXR); break; + STORAGE(U2CTSR); break; + STORAGE(U3RXR); break; + STORAGE(U3CTSR); break; + STORAGE(U4RXR); break; + STORAGE(U4CTSR); break; + STORAGE(U5RXR); break; + STORAGE(U5CTSR); break; + STORAGE(U6RXR); break; + STORAGE(U6CTSR); break; + STORAGE(SDI1R); break; + STORAGE(SS1R); break; + STORAGE(SDI2R); break; + STORAGE(SS2R); break; + STORAGE(SDI3R); break; + STORAGE(SS3R); break; + STORAGE(SDI4R); break; + STORAGE(SS4R); break; + STORAGE(SDI5R); break; + STORAGE(SS5R); break; + STORAGE(SDI6R); break; + STORAGE(SS6R); break; + STORAGE(C1RXR); break; + STORAGE(C2RXR); break; + STORAGE(REFCLKI1R); break; + STORAGE(REFCLKI3R); break; + STORAGE(REFCLKI4R); break; + + /*------------------------------------------------------------------------- + * Peripheral port select registers: output. + */ + STORAGE(RPA14R); break; + STORAGE(RPA15R); break; + STORAGE(RPB0R); break; + STORAGE(RPB1R); break; + STORAGE(RPB2R); break; + STORAGE(RPB3R); break; + STORAGE(RPB5R); break; + STORAGE(RPB6R); break; + STORAGE(RPB7R); break; + STORAGE(RPB8R); break; + STORAGE(RPB9R); break; + STORAGE(RPB10R); break; + STORAGE(RPB14R); break; + STORAGE(RPB15R); break; + STORAGE(RPC1R); break; + STORAGE(RPC2R); break; + STORAGE(RPC3R); break; + STORAGE(RPC4R); break; + STORAGE(RPC13R); break; + STORAGE(RPC14R); break; + STORAGE(RPD0R); break; + STORAGE(RPD1R); break; + STORAGE(RPD2R); break; + STORAGE(RPD3R); break; + STORAGE(RPD4R); break; + STORAGE(RPD5R); break; + STORAGE(RPD6R); break; + STORAGE(RPD7R); break; + STORAGE(RPD9R); break; + STORAGE(RPD10R); break; + STORAGE(RPD11R); break; + STORAGE(RPD12R); break; + STORAGE(RPD14R); break; + STORAGE(RPD15R); break; + STORAGE(RPE3R); break; + STORAGE(RPE5R); break; + STORAGE(RPE8R); break; + STORAGE(RPE9R); break; + STORAGE(RPF0R); break; + STORAGE(RPF1R); break; + STORAGE(RPF2R); break; + STORAGE(RPF3R); break; + STORAGE(RPF4R); break; + STORAGE(RPF5R); break; + STORAGE(RPF8R); break; + STORAGE(RPF12R); break; + STORAGE(RPF13R); break; + STORAGE(RPG0R); break; + STORAGE(RPG1R); break; + STORAGE(RPG6R); break; + STORAGE(RPG7R); break; + STORAGE(RPG8R); break; + STORAGE(RPG9R); break; + + /*------------------------------------------------------------------------- + * General purpose IO signals. + */ + STORAGE(ANSELA); break; // Port A: analog select + STORAGE(TRISA); break; // Port A: mask of inputs + STORAGE(PORTA); break; // Port A: read inputs + STORAGE(LATA); break; // Port A: read outputs + STORAGE(ODCA); break; // Port A: open drain configuration + STORAGE(CNPUA); break; // Input pin pull-up + STORAGE(CNPDA); break; // Input pin pull-down + STORAGE(CNCONA); break; // Interrupt-on-change control + STORAGE(CNENA); break; // Input change interrupt enable + STORAGE(CNSTATA); break; // Input change status + + STORAGE(ANSELB); break; // Port B: analog select + STORAGE(TRISB); break; // Port B: mask of inputs + STORAGE(PORTB); break; // Port B: read inputs + STORAGE(LATB); break; // Port B: read outputs + STORAGE(ODCB); break; // Port B: open drain configuration + STORAGE(CNPUB); break; // Input pin pull-up + STORAGE(CNPDB); break; // Input pin pull-down + STORAGE(CNCONB); break; // Interrupt-on-change control + STORAGE(CNENB); break; // Input change interrupt enable + STORAGE(CNSTATB); break; // Input change status + + STORAGE(ANSELC); break; // Port C: analog select + STORAGE(TRISC); break; // Port C: mask of inputs + STORAGE(PORTC); break; // Port C: read inputs + STORAGE(LATC); break; // Port C: read outputs + STORAGE(ODCC); break; // Port C: open drain configuration + STORAGE(CNPUC); break; // Input pin pull-up + STORAGE(CNPDC); break; // Input pin pull-down + STORAGE(CNCONC); break; // Interrupt-on-change control + STORAGE(CNENC); break; // Input change interrupt enable + STORAGE(CNSTATC); break; // Input change status + + STORAGE(ANSELD); break; // Port D: analog select + STORAGE(TRISD); break; // Port D: mask of inputs + STORAGE(PORTD); break; // Port D: read inputs + STORAGE(LATD); break; // Port D: read outputs + STORAGE(ODCD); break; // Port D: open drain configuration + STORAGE(CNPUD); break; // Input pin pull-up + STORAGE(CNPDD); break; // Input pin pull-down + STORAGE(CNCOND); break; // Interrupt-on-change control + STORAGE(CNEND); break; // Input change interrupt enable + STORAGE(CNSTATD); break; // Input change status + + STORAGE(ANSELE); break; // Port E: analog select + STORAGE(TRISE); break; // Port E: mask of inputs + STORAGE(PORTE); break; // Port E: read inputs + STORAGE(LATE); break; // Port E: read outputs + STORAGE(ODCE); break; // Port E: open drain configuration + STORAGE(CNPUE); break; // Input pin pull-up + STORAGE(CNPDE); break; // Input pin pull-down + STORAGE(CNCONE); break; // Interrupt-on-change control + STORAGE(CNENE); break; // Input change interrupt enable + STORAGE(CNSTATE); break; // Input change status + + STORAGE(ANSELF); break; // Port F: analog select + STORAGE(TRISF); break; // Port F: mask of inputs + STORAGE(PORTF); break; // Port F: read inputs + STORAGE(LATF); break; // Port F: read outputs + STORAGE(ODCF); break; // Port F: open drain configuration + STORAGE(CNPUF); break; // Input pin pull-up + STORAGE(CNPDF); break; // Input pin pull-down + STORAGE(CNCONF); break; // Interrupt-on-change control + STORAGE(CNENF); break; // Input change interrupt enable + STORAGE(CNSTATF); break; // Input change status + + STORAGE(ANSELG); break; // Port G: analog select + STORAGE(TRISG); break; // Port G: mask of inputs + STORAGE(PORTG); break; // Port G: read inputs + STORAGE(LATG); break; // Port G: read outputs + STORAGE(ODCG); break; // Port G: open drain configuration + STORAGE(CNPUG); break; // Input pin pull-up + STORAGE(CNPDG); break; // Input pin pull-down + STORAGE(CNCONG); break; // Interrupt-on-change control + STORAGE(CNENG); break; // Input change interrupt enable + STORAGE(CNSTATG); break; // Input change status + + /*------------------------------------------------------------------------- + * UART 1. + */ + STORAGE(U1RXREG); // Receive data + *bufp = pic32_uart_get_char(s, 0); + break; + STORAGE(U1BRG); break; // Baud rate + STORAGE(U1MODE); break; // Mode + STORAGE(U1STA); // Status and control + pic32_uart_poll_status(s, 0); + break; + STORAGE(U1TXREG); *bufp = 0; break; // Transmit + STORAGE(U1MODECLR); *bufp = 0; break; + STORAGE(U1MODESET); *bufp = 0; break; + STORAGE(U1MODEINV); *bufp = 0; break; + STORAGE(U1STACLR); *bufp = 0; break; + STORAGE(U1STASET); *bufp = 0; break; + STORAGE(U1STAINV); *bufp = 0; break; + STORAGE(U1BRGCLR); *bufp = 0; break; + STORAGE(U1BRGSET); *bufp = 0; break; + STORAGE(U1BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * UART 2. + */ + STORAGE(U2RXREG); // Receive data + *bufp = pic32_uart_get_char(s, 1); + break; + STORAGE(U2BRG); break; // Baud rate + STORAGE(U2MODE); break; // Mode + STORAGE(U2STA); // Status and control + pic32_uart_poll_status(s, 1); + break; + STORAGE(U2TXREG); *bufp = 0; break; // Transmit + STORAGE(U2MODECLR); *bufp = 0; break; + STORAGE(U2MODESET); *bufp = 0; break; + STORAGE(U2MODEINV); *bufp = 0; break; + STORAGE(U2STACLR); *bufp = 0; break; + STORAGE(U2STASET); *bufp = 0; break; + STORAGE(U2STAINV); *bufp = 0; break; + STORAGE(U2BRGCLR); *bufp = 0; break; + STORAGE(U2BRGSET); *bufp = 0; break; + STORAGE(U2BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * UART 3. + */ + STORAGE(U3RXREG); // Receive data + *bufp = pic32_uart_get_char(s, 2); + break; + STORAGE(U3BRG); break; // Baud rate + STORAGE(U3MODE); break; // Mode + STORAGE(U3STA); // Status and control + pic32_uart_poll_status(s, 2); + break; + STORAGE(U3TXREG); *bufp = 0; break; // Transmit + STORAGE(U3MODECLR); *bufp = 0; break; + STORAGE(U3MODESET); *bufp = 0; break; + STORAGE(U3MODEINV); *bufp = 0; break; + STORAGE(U3STACLR); *bufp = 0; break; + STORAGE(U3STASET); *bufp = 0; break; + STORAGE(U3STAINV); *bufp = 0; break; + STORAGE(U3BRGCLR); *bufp = 0; break; + STORAGE(U3BRGSET); *bufp = 0; break; + STORAGE(U3BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * UART 4. + */ + STORAGE(U4RXREG); // Receive data + *bufp = pic32_uart_get_char(s, 3); + break; + STORAGE(U4BRG); break; // Baud rate + STORAGE(U4MODE); break; // Mode + STORAGE(U4STA); // Status and control + pic32_uart_poll_status(s, 3); + break; + STORAGE(U4TXREG); *bufp = 0; break; // Transmit + STORAGE(U4MODECLR); *bufp = 0; break; + STORAGE(U4MODESET); *bufp = 0; break; + STORAGE(U4MODEINV); *bufp = 0; break; + STORAGE(U4STACLR); *bufp = 0; break; + STORAGE(U4STASET); *bufp = 0; break; + STORAGE(U4STAINV); *bufp = 0; break; + STORAGE(U4BRGCLR); *bufp = 0; break; + STORAGE(U4BRGSET); *bufp = 0; break; + STORAGE(U4BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * UART 5. + */ + STORAGE(U5RXREG); // Receive data + *bufp = pic32_uart_get_char(s, 4); + break; + STORAGE(U5BRG); break; // Baud rate + STORAGE(U5MODE); break; // Mode + STORAGE(U5STA); // Status and control + pic32_uart_poll_status(s, 4); + break; + STORAGE(U5TXREG); *bufp = 0; break; // Transmit + STORAGE(U5MODECLR); *bufp = 0; break; + STORAGE(U5MODESET); *bufp = 0; break; + STORAGE(U5MODEINV); *bufp = 0; break; + STORAGE(U5STACLR); *bufp = 0; break; + STORAGE(U5STASET); *bufp = 0; break; + STORAGE(U5STAINV); *bufp = 0; break; + STORAGE(U5BRGCLR); *bufp = 0; break; + STORAGE(U5BRGSET); *bufp = 0; break; + STORAGE(U5BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * UART 6. + */ + STORAGE(U6RXREG); // Receive data + *bufp = pic32_uart_get_char(s, 5); + break; + STORAGE(U6BRG); break; // Baud rate + STORAGE(U6MODE); break; // Mode + STORAGE(U6STA); // Status and control + pic32_uart_poll_status(s, 5); + break; + STORAGE(U6TXREG); *bufp = 0; break; // Transmit + STORAGE(U6MODECLR); *bufp = 0; break; + STORAGE(U6MODESET); *bufp = 0; break; + STORAGE(U6MODEINV); *bufp = 0; break; + STORAGE(U6STACLR); *bufp = 0; break; + STORAGE(U6STASET); *bufp = 0; break; + STORAGE(U6STAINV); *bufp = 0; break; + STORAGE(U6BRGCLR); *bufp = 0; break; + STORAGE(U6BRGSET); *bufp = 0; break; + STORAGE(U6BRGINV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * SPI 1. + */ + STORAGE(SPI1CON); break; // Control + STORAGE(SPI1CONCLR); *bufp = 0; break; + STORAGE(SPI1CONSET); *bufp = 0; break; + STORAGE(SPI1CONINV); *bufp = 0; break; + STORAGE(SPI1STAT); break; // Status + STORAGE(SPI1STATCLR); *bufp = 0; break; + STORAGE(SPI1STATSET); *bufp = 0; break; + STORAGE(SPI1STATINV); *bufp = 0; break; + STORAGE(SPI1BUF); // Buffer + *bufp = pic32_spi_readbuf(s, 0); + break; + STORAGE(SPI1BRG); break; // Baud rate + STORAGE(SPI1BRGCLR); *bufp = 0; break; + STORAGE(SPI1BRGSET); *bufp = 0; break; + STORAGE(SPI1BRGINV); *bufp = 0; break; + STORAGE(SPI1CON2); break; // Control 2 + STORAGE(SPI1CON2CLR); *bufp = 0; break; + STORAGE(SPI1CON2SET); *bufp = 0; break; + STORAGE(SPI1CON2INV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * SPI 2. + */ + STORAGE(SPI2CON); break; // Control + STORAGE(SPI2CONCLR); *bufp = 0; break; + STORAGE(SPI2CONSET); *bufp = 0; break; + STORAGE(SPI2CONINV); *bufp = 0; break; + STORAGE(SPI2STAT); break; // Status + STORAGE(SPI2STATCLR); *bufp = 0; break; + STORAGE(SPI2STATSET); *bufp = 0; break; + STORAGE(SPI2STATINV); *bufp = 0; break; + STORAGE(SPI2BUF); // Buffer + *bufp = pic32_spi_readbuf(s, 1); + break; + STORAGE(SPI2BRG); break; // Baud rate + STORAGE(SPI2BRGCLR); *bufp = 0; break; + STORAGE(SPI2BRGSET); *bufp = 0; break; + STORAGE(SPI2BRGINV); *bufp = 0; break; + STORAGE(SPI2CON2); break; // Control 2 + STORAGE(SPI2CON2CLR); *bufp = 0; break; + STORAGE(SPI2CON2SET); *bufp = 0; break; + STORAGE(SPI2CON2INV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * SPI 3. + */ + STORAGE(SPI3CON); break; // Control + STORAGE(SPI3CONCLR); *bufp = 0; break; + STORAGE(SPI3CONSET); *bufp = 0; break; + STORAGE(SPI3CONINV); *bufp = 0; break; + STORAGE(SPI3STAT); break; // Status + STORAGE(SPI3STATCLR); *bufp = 0; break; + STORAGE(SPI3STATSET); *bufp = 0; break; + STORAGE(SPI3STATINV); *bufp = 0; break; + STORAGE(SPI3BUF); // SPIx Buffer + *bufp = pic32_spi_readbuf(s, 2); + break; + STORAGE(SPI3BRG); break; // Baud rate + STORAGE(SPI3BRGCLR); *bufp = 0; break; + STORAGE(SPI3BRGSET); *bufp = 0; break; + STORAGE(SPI3BRGINV); *bufp = 0; break; + STORAGE(SPI3CON2); break; // Control 2 + STORAGE(SPI3CON2CLR); *bufp = 0; break; + STORAGE(SPI3CON2SET); *bufp = 0; break; + STORAGE(SPI3CON2INV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * SPI 4. + */ + STORAGE(SPI4CON); break; // Control + STORAGE(SPI4CONCLR); *bufp = 0; break; + STORAGE(SPI4CONSET); *bufp = 0; break; + STORAGE(SPI4CONINV); *bufp = 0; break; + STORAGE(SPI4STAT); break; // Status + STORAGE(SPI4STATCLR); *bufp = 0; break; + STORAGE(SPI4STATSET); *bufp = 0; break; + STORAGE(SPI4STATINV); *bufp = 0; break; + STORAGE(SPI4BUF); // Buffer + *bufp = pic32_spi_readbuf(s, 3); + break; + STORAGE(SPI4BRG); break; // Baud rate + STORAGE(SPI4BRGCLR); *bufp = 0; break; + STORAGE(SPI4BRGSET); *bufp = 0; break; + STORAGE(SPI4BRGINV); *bufp = 0; break; + STORAGE(SPI4CON2); break; // Control 2 + STORAGE(SPI4CON2CLR); *bufp = 0; break; + STORAGE(SPI4CON2SET); *bufp = 0; break; + STORAGE(SPI4CON2INV); *bufp = 0; break; + + /*------------------------------------------------------------------------- + * Ethernet. + */ + STORAGE(ETHCON1); break; // Control 1 + STORAGE(ETHCON2); break; // Control 2: RX data buffer size + STORAGE(ETHTXST); break; // Tx descriptor start address + STORAGE(ETHRXST); break; // Rx descriptor start address + STORAGE(ETHHT0); break; // Hash tasble 0 + STORAGE(ETHHT1); break; // Hash tasble 1 + STORAGE(ETHPMM0); break; // Pattern match mask 0 + STORAGE(ETHPMM1); break; // Pattern match mask 1 + STORAGE(ETHPMCS); break; // Pattern match checksum + STORAGE(ETHPMO); break; // Pattern match offset + STORAGE(ETHRXFC); break; // Receive filter configuration + STORAGE(ETHRXWM); break; // Receive watermarks + STORAGE(ETHIEN); break; // Interrupt enable + STORAGE(ETHIRQ); break; // Interrupt request + STORAGE(ETHSTAT); break; // Status + STORAGE(ETHRXOVFLOW); break; // Receive overflow statistics + STORAGE(ETHFRMTXOK); break; // Frames transmitted OK statistics + STORAGE(ETHSCOLFRM); break; // Single collision frames statistics + STORAGE(ETHMCOLFRM); break; // Multiple collision frames statistics + STORAGE(ETHFRMRXOK); break; // Frames received OK statistics + STORAGE(ETHFCSERR); break; // Frame check sequence error statistics + STORAGE(ETHALGNERR); break; // Alignment errors statistics + STORAGE(EMAC1CFG1); break; // MAC configuration 1 + STORAGE(EMAC1CFG2); break; // MAC configuration 2 + STORAGE(EMAC1IPGT); break; // MAC back-to-back interpacket gap + STORAGE(EMAC1IPGR); break; // MAC non-back-to-back interpacket gap + STORAGE(EMAC1CLRT); break; // MAC collision window/retry limit + STORAGE(EMAC1MAXF); break; // MAC maximum frame length + STORAGE(EMAC1SUPP); break; // MAC PHY support + STORAGE(EMAC1TEST); break; // MAC test + STORAGE(EMAC1MCFG); break; // MII configuration + STORAGE(EMAC1MCMD); break; // MII command + STORAGE(EMAC1MADR); break; // MII address + STORAGE(EMAC1MWTD); break; // MII write data + STORAGE(EMAC1MRDD); break; // MII read data + STORAGE(EMAC1MIND); break; // MII indicators + STORAGE(EMAC1SA0); break; // MAC station address 0 + STORAGE(EMAC1SA1); break; // MAC station address 1 + STORAGE(EMAC1SA2); break; // MAC station address 2 + + default: + printf("--- Read 1f8%05x: peripheral register not supported\n", + offset); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Read 1f8%05x: peripheral register not supported\n", + offset); + exit(1); + } + return *bufp; +} + +static void pps_input_group1(unsigned address, unsigned data) +{ + // 0000 = RPD1 + // 0001 = RPG9 + // 0010 = RPB14 + // 0011 = RPD0 + // 0101 = RPB6 + // 0110 = RPD5 + // 0111 = RPB2 + // 1000 = RPF3 + // 1001 = RPF13 + // 1011 = RPF2 + // 1100 = RPC2 + // 1101 = RPE8 +} + +static void pps_input_group2(unsigned address, unsigned data) +{ + // 0000 = RPD9 + // 0001 = RPG6 + // 0010 = RPB8 + // 0011 = RPB15 + // 0100 = RPD4 + // 0101 = RPB0 + // 0110 = RPE3 + // 0111 = RPB7 + // 1001 = RPF12 + // 1010 = RPD12 + // 1011 = RPF8 + // 1100 = RPC3 + // 1101 = RPE9 +} + +static void pps_input_group3(unsigned address, unsigned data) +{ + // 0000 = RPD2 + // 0001 = RPG8 + // 0010 = RPF4 + // 0011 = RPD10 + // 0100 = RPF1 + // 0101 = RPB9 + // 0110 = RPB10 + // 0111 = RPC14 + // 1000 = RPB5 + // 1010 = RPC1 + // 1011 = RPD14 + // 1100 = RPG1 + // 1101 = RPA14 + // 1110 = RPD6 +} + +static void pps_input_group4(unsigned address, unsigned data) +{ + // 0000 = RPD3 + // 0001 = RPG7 + // 0010 = RPF5 + // 0011 = RPD11 + // 0100 = RPF0 + // 0101 = RPB1 + // 0110 = RPE5 + // 0111 = RPC13 + // 1000 = RPB3 + // 1010 = RPC4 + // 1011 = RPD15 + // 1100 = RPG0 + // 1101 = RPA15 + // 1110 = RPD7 +} + +static void pps_output_group1(unsigned address, unsigned data) +{ + // 0000 = No Connect + // 0001 = U1TX + // 0010 = U2RTS + // 0011 = U5TX + // 0100 = U6RTS + // 0101 = SDO1 + // 0110 = SDO2 + // 0111 = SDO3 + // 1000 = SDO4 + // 1001 = SDO5 + // 1011 = OC4 + // 1100 = OC7 + // 1111 = REFCLKO1 +} + +static void pps_output_group2(unsigned address, unsigned data) +{ + // 0000 = No Connect + // 0001 = U1RTS + // 0010 = U2TX + // 0011 = U5RTS + // 0100 = U6TX + // 0110 = SS2 + // 1000 = SDO4 + // 1010 = SDO6 + // 1011 = OC2 + // 1100 = OC1 + // 1101 = OC9 + // 1111 = C2TX +} + +static void pps_output_group3(unsigned address, unsigned data) +{ + // 0000 = No Connect + // 0001 = U3TX + // 0010 = U4RTS + // 0101 = SDO1 + // 0110 = SDO2 + // 0111 = SDO3 + // 1001 = SDO5 + // 1010 = SS6 + // 1011 = OC3 + // 1100 = OC6 + // 1101 = REFCLKO4 + // 1110 = C2OUT + // 1111 = C1TX +} + +static void pps_output_group4(unsigned address, unsigned data) +{ + // 0000 = No Connect + // 0001 = U3RTS + // 0010 = U4TX + // 0100 = U6TX + // 0101 = SS1 + // 0111 = SS3 + // 1000 = SS4 + // 1001 = SS5 + // 1010 = SDO6 + // 1011 = OC5 + // 1100 = OC8 + // 1110 = C1OUT + // 1111 = REFCLKO3 +} + +static void io_write32(pic32_t *s, unsigned offset, unsigned data, const char **namep) +{ + unsigned *bufp = &VALUE(offset); + unsigned mask; + + switch (offset) { + /*------------------------------------------------------------------------- + * Interrupt controller registers. + */ + WRITEOP(INTCON); return; // Interrupt Control + READONLY(INTSTAT); // Interrupt Status + WRITEOP(IPTMR); return; // Temporal Proximity Timer + WRITEOP(IFS0); goto irq; // IFS(0..2) - Interrupt Flag Status + WRITEOP(IFS1); goto irq; + WRITEOP(IFS2); goto irq; + WRITEOP(IFS3); goto irq; + WRITEOP(IFS4); goto irq; + WRITEOP(IFS5); goto irq; + WRITEOP(IEC0); goto irq; // IEC(0..2) - Interrupt Enable Control + WRITEOP(IEC1); goto irq; + WRITEOP(IEC2); goto irq; + WRITEOP(IEC3); goto irq; + WRITEOP(IEC4); goto irq; + WRITEOP(IEC5); goto irq; + WRITEOP(IPC0); goto irq; // IPC(0..11) - Interrupt Priority Control + WRITEOP(IPC1); goto irq; + WRITEOP(IPC2); goto irq; + WRITEOP(IPC3); goto irq; + WRITEOP(IPC4); goto irq; + WRITEOP(IPC5); goto irq; + WRITEOP(IPC6); goto irq; + WRITEOP(IPC7); goto irq; + WRITEOP(IPC8); goto irq; + WRITEOP(IPC9); goto irq; + WRITEOP(IPC10); goto irq; + WRITEOP(IPC11); goto irq; + WRITEOP(IPC12); goto irq; + WRITEOP(IPC13); goto irq; + WRITEOP(IPC14); goto irq; + WRITEOP(IPC15); goto irq; + WRITEOP(IPC16); goto irq; + WRITEOP(IPC17); goto irq; + WRITEOP(IPC18); goto irq; + WRITEOP(IPC19); goto irq; + WRITEOP(IPC20); goto irq; + WRITEOP(IPC21); goto irq; + WRITEOP(IPC22); goto irq; + WRITEOP(IPC23); goto irq; + WRITEOP(IPC24); goto irq; + WRITEOP(IPC25); goto irq; + WRITEOP(IPC26); goto irq; + WRITEOP(IPC27); goto irq; + WRITEOP(IPC28); goto irq; + WRITEOP(IPC29); goto irq; + WRITEOP(IPC30); goto irq; + WRITEOP(IPC31); goto irq; + WRITEOP(IPC32); goto irq; + WRITEOP(IPC33); goto irq; + WRITEOP(IPC34); goto irq; + WRITEOP(IPC35); goto irq; + WRITEOP(IPC36); goto irq; + WRITEOP(IPC37); goto irq; + WRITEOP(IPC38); goto irq; + WRITEOP(IPC39); goto irq; + WRITEOP(IPC40); goto irq; + WRITEOP(IPC41); goto irq; + WRITEOP(IPC42); goto irq; + WRITEOP(IPC43); goto irq; + WRITEOP(IPC44); goto irq; + WRITEOP(IPC45); goto irq; + WRITEOP(IPC46); goto irq; + WRITEOP(IPC47); +irq: update_irq_status(s); + return; + + /*------------------------------------------------------------------------- + * Prefetch controller. + */ + WRITEOP(PRECON); return; // Prefetch Control + WRITEOP(PRESTAT); return; // Prefetch Status + + /*------------------------------------------------------------------------- + * System controller. + */ + STORAGE(CFGCON); // Configuration Control + // TODO: use unlock sequence + mask = PIC32_CFGCON_DMAPRI | PIC32_CFGCON_CPUPRI | + PIC32_CFGCON_ICACLK | PIC32_CFGCON_OCACLK | + PIC32_CFGCON_IOLOCK | PIC32_CFGCON_PMDLOCK | + PIC32_CFGCON_PGLOCK | PIC32_CFGCON_USBSSEN | + PIC32_CFGCON_ECC_MASK | PIC32_CFGCON_JTAGEN | + PIC32_CFGCON_TROEN | PIC32_CFGCON_TDOEN; + data = (data & mask) | (*bufp & ~mask); + break; + READONLY(DEVID); // Device Identifier + STORAGE(SYSKEY); // System Key + /* Unlock state machine. */ + if (s->syskey_unlock == 0 && VALUE(SYSKEY) == 0xaa996655) + s->syskey_unlock = 1; + if (s->syskey_unlock == 1 && VALUE(SYSKEY) == 0x556699aa) + s->syskey_unlock = 2; + else + s->syskey_unlock = 0; + break; + STORAGE(RCON); break; // Reset Control + WRITEOP(RSWRST); // Software Reset + if (s->syskey_unlock == 2 && (VALUE(RSWRST) & 1)) { + /* Reset CPU. */ + qemu_system_reset_request(); + + /* Reset all devices */ + io_reset(s); + pic32_sdcard_reset(s); + } + break; + STORAGE(OSCCON); break; // Oscillator Control + STORAGE(OSCTUN); break; // Oscillator Tuning + STORAGE(SPLLCON); break; // System PLL Control + STORAGE(PB1DIV); break; // Peripheral bus 1 divisor + STORAGE(PB2DIV); break; // Peripheral bus 2 divisor + STORAGE(PB3DIV); break; // Peripheral bus 3 divisor + STORAGE(PB4DIV); break; // Peripheral bus 4 divisor + STORAGE(PB5DIV); break; // Peripheral bus 5 divisor + STORAGE(PB7DIV); break; // Peripheral bus 7 divisor + STORAGE(PB8DIV); break; // Peripheral bus 8 divisor + + /*------------------------------------------------------------------------- + * Peripheral port select registers: input. + */ + STORAGE(INT1R); pps_input_group1(offset, data); break; + STORAGE(T4CKR); pps_input_group1(offset, data); break; + STORAGE(T9CKR); pps_input_group1(offset, data); break; + STORAGE(IC1R); pps_input_group1(offset, data); break; + STORAGE(IC6R); pps_input_group1(offset, data); break; + STORAGE(U3CTSR); pps_input_group1(offset, data); break; + STORAGE(U4RXR); pps_input_group1(offset, data); break; + STORAGE(U6RXR); pps_input_group1(offset, data); break; + STORAGE(SS2R); pps_input_group1(offset, data); break; + STORAGE(SDI6R); pps_input_group1(offset, data); break; + STORAGE(OCFAR); pps_input_group1(offset, data); break; + STORAGE(REFCLKI3R);pps_input_group1(offset, data); break; + + STORAGE(INT2R); pps_input_group2(offset, data); break; + STORAGE(T3CKR); pps_input_group2(offset, data); break; + STORAGE(T8CKR); pps_input_group2(offset, data); break; + STORAGE(IC2R); pps_input_group2(offset, data); break; + STORAGE(IC5R); pps_input_group2(offset, data); break; + STORAGE(IC9R); pps_input_group2(offset, data); break; + STORAGE(U1CTSR); pps_input_group2(offset, data); break; + STORAGE(U2RXR); pps_input_group2(offset, data); break; + STORAGE(U5CTSR); pps_input_group2(offset, data); break; + STORAGE(SS1R); pps_input_group2(offset, data); break; + STORAGE(SS3R); pps_input_group2(offset, data); break; + STORAGE(SS4R); pps_input_group2(offset, data); break; + STORAGE(SS5R); pps_input_group2(offset, data); break; + STORAGE(C2RXR); pps_input_group2(offset, data); break; + + STORAGE(INT3R); pps_input_group3(offset, data); break; + STORAGE(T2CKR); pps_input_group3(offset, data); break; + STORAGE(T6CKR); pps_input_group3(offset, data); break; + STORAGE(IC3R); pps_input_group3(offset, data); break; + STORAGE(IC7R); pps_input_group3(offset, data); break; + STORAGE(U1RXR); pps_input_group3(offset, data); break; + STORAGE(U2CTSR); pps_input_group3(offset, data); break; + STORAGE(U5RXR); pps_input_group3(offset, data); break; + STORAGE(U6CTSR); pps_input_group3(offset, data); break; + STORAGE(SDI1R); pps_input_group3(offset, data); break; + STORAGE(SDI3R); pps_input_group3(offset, data); break; + STORAGE(SDI5R); pps_input_group3(offset, data); break; + STORAGE(SS6R); pps_input_group3(offset, data); break; + STORAGE(REFCLKI1R);pps_input_group3(offset, data); break; + + STORAGE(INT4R); pps_input_group4(offset, data); break; + STORAGE(T5CKR); pps_input_group4(offset, data); break; + STORAGE(T7CKR); pps_input_group4(offset, data); break; + STORAGE(IC4R); pps_input_group4(offset, data); break; + STORAGE(IC8R); pps_input_group4(offset, data); break; + STORAGE(U3RXR); pps_input_group4(offset, data); break; + STORAGE(U4CTSR); pps_input_group4(offset, data); break; + STORAGE(SDI2R); pps_input_group4(offset, data); break; + STORAGE(SDI4R); pps_input_group4(offset, data); break; + STORAGE(C1RXR); pps_input_group4(offset, data); break; + STORAGE(REFCLKI4R);pps_input_group4(offset, data); break; + + /*------------------------------------------------------------------------- + * Peripheral port select registers: output. + */ + STORAGE(RPA15R); pps_output_group1(offset, data); break; + STORAGE(RPB1R); pps_output_group1(offset, data); break; + STORAGE(RPB3R); pps_output_group1(offset, data); break; + STORAGE(RPC4R); pps_output_group1(offset, data); break; + STORAGE(RPC13R); pps_output_group1(offset, data); break; + STORAGE(RPD3R); pps_output_group1(offset, data); break; + STORAGE(RPD7R); pps_output_group1(offset, data); break; + STORAGE(RPD11R); pps_output_group1(offset, data); break; + STORAGE(RPD15R); pps_output_group1(offset, data); break; + STORAGE(RPE5R); pps_output_group1(offset, data); break; + STORAGE(RPF0R); pps_output_group1(offset, data); break; + STORAGE(RPF5R); pps_output_group1(offset, data); break; + STORAGE(RPG0R); pps_output_group1(offset, data); break; + STORAGE(RPG7R); pps_output_group1(offset, data); break; + + STORAGE(RPB2R); pps_output_group2(offset, data); break; + STORAGE(RPB6R); pps_output_group2(offset, data); break; + STORAGE(RPB14R); pps_output_group2(offset, data); break; + STORAGE(RPC2R); pps_output_group2(offset, data); break; + STORAGE(RPD0R); pps_output_group2(offset, data); break; + STORAGE(RPD1R); pps_output_group2(offset, data); break; + STORAGE(RPD5R); pps_output_group2(offset, data); break; + STORAGE(RPE8R); pps_output_group2(offset, data); break; + STORAGE(RPF2R); pps_output_group2(offset, data); break; + STORAGE(RPF3R); pps_output_group2(offset, data); break; + STORAGE(RPF13R); pps_output_group2(offset, data); break; + STORAGE(RPG9R); pps_output_group2(offset, data); break; + + STORAGE(RPA14R); pps_output_group3(offset, data); break; + STORAGE(RPB5R); pps_output_group3(offset, data); break; + STORAGE(RPB9R); pps_output_group3(offset, data); break; + STORAGE(RPB10R); pps_output_group3(offset, data); break; + STORAGE(RPC1R); pps_output_group3(offset, data); break; + STORAGE(RPC14R); pps_output_group3(offset, data); break; + STORAGE(RPD2R); pps_output_group3(offset, data); break; + STORAGE(RPD6R); pps_output_group3(offset, data); break; + STORAGE(RPD10R); pps_output_group3(offset, data); break; + STORAGE(RPD14R); pps_output_group3(offset, data); break; + STORAGE(RPF1R); pps_output_group3(offset, data); break; + STORAGE(RPF4R); pps_output_group3(offset, data); break; + STORAGE(RPG1R); pps_output_group3(offset, data); break; + STORAGE(RPG8R); pps_output_group3(offset, data); break; + + STORAGE(RPB0R); pps_output_group4(offset, data); break; + STORAGE(RPB7R); pps_output_group4(offset, data); break; + STORAGE(RPB8R); pps_output_group4(offset, data); break; + STORAGE(RPB15R); pps_output_group4(offset, data); break; + STORAGE(RPC3R); pps_output_group4(offset, data); break; + STORAGE(RPD4R); pps_output_group4(offset, data); break; + STORAGE(RPD9R); pps_output_group4(offset, data); break; + STORAGE(RPD12R); pps_output_group4(offset, data); break; + STORAGE(RPE3R); pps_output_group4(offset, data); break; + STORAGE(RPE9R); pps_output_group4(offset, data); break; + STORAGE(RPF8R); pps_output_group4(offset, data); break; + STORAGE(RPF12R); pps_output_group4(offset, data); break; + STORAGE(RPG6R); pps_output_group4(offset, data); break; + + /*------------------------------------------------------------------------- + * General purpose IO signals. + */ + WRITEOP(ANSELA); return; // Port A: analog select + WRITEOP(TRISA); return; // Port A: mask of inputs + WRITEOPX(PORTA, LATA); // Port A: write outputs + WRITEOP(LATA); // Port A: write outputs + pic32_gpio_write(s, 0, VALUE(LATA)); + return; + WRITEOP(ODCA); return; // Port A: open drain configuration + WRITEOP(CNPUA); return; // Input pin pull-up + WRITEOP(CNPDA); return; // Input pin pull-down + WRITEOP(CNCONA); return; // Interrupt-on-change control + WRITEOP(CNENA); return; // Input change interrupt enable + WRITEOP(CNSTATA); return; // Input change status + + WRITEOP(ANSELB); return; // Port B: analog select + WRITEOP(TRISB); return; // Port B: mask of inputs + WRITEOPX(PORTB, LATB); // Port B: write outputs + WRITEOP(LATB); // Port B: write outputs + pic32_gpio_write(s, 1, VALUE(LATB)); + return; + WRITEOP(ODCB); return; // Port B: open drain configuration + WRITEOP(CNPUB); return; // Input pin pull-up + WRITEOP(CNPDB); return; // Input pin pull-down + WRITEOP(CNCONB); return; // Interrupt-on-change control + WRITEOP(CNENB); return; // Input change interrupt enable + WRITEOP(CNSTATB); return; // Input change status + + WRITEOP(ANSELC); return; // Port C: analog select + WRITEOP(TRISC); return; // Port C: mask of inputs + WRITEOPX(PORTC, LATC); // Port C: write outputs + WRITEOP(LATC); // Port C: write outputs + pic32_gpio_write(s, 2, VALUE(LATC)); + return; + WRITEOP(ODCC); return; // Port C: open drain configuration + WRITEOP(CNPUC); return; // Input pin pull-up + WRITEOP(CNPDC); return; // Input pin pull-down + WRITEOP(CNCONC); return; // Interrupt-on-change control + WRITEOP(CNENC); return; // Input change interrupt enable + WRITEOP(CNSTATC); return; // Input change status + + WRITEOP(ANSELD); return; // Port D: analog select + WRITEOP(TRISD); return; // Port D: mask of inputs + WRITEOPX(PORTD, LATD); // Port D: write outputs + WRITEOP(LATD); // Port D: write outputs + pic32_gpio_write(s, 3, VALUE(LATD)); + return; + WRITEOP(ODCD); return; // Port D: open drain configuration + WRITEOP(CNPUD); return; // Input pin pull-up + WRITEOP(CNPDD); return; // Input pin pull-down + WRITEOP(CNCOND); return; // Interrupt-on-change control + WRITEOP(CNEND); return; // Input change interrupt enable + WRITEOP(CNSTATD); return; // Input change status + + WRITEOP(ANSELE); return; // Port E: analog select + WRITEOP(TRISE); return; // Port E: mask of inputs + WRITEOPX(PORTE, LATE); // Port E: write outputs + WRITEOP(LATE); // Port E: write outputs + pic32_gpio_write(s, 4, VALUE(LATE)); + return; + WRITEOP(ODCE); return; // Port E: open drain configuration + WRITEOP(CNPUE); return; // Input pin pull-up + WRITEOP(CNPDE); return; // Input pin pull-down + WRITEOP(CNCONE); return; // Interrupt-on-change control + WRITEOP(CNENE); return; // Input change interrupt enable + WRITEOP(CNSTATE); return; // Input change status + + WRITEOP(ANSELF); return; // Port F: analog select + WRITEOP(TRISF); return; // Port F: mask of inputs + WRITEOPX(PORTF, LATF); // Port F: write outputs + WRITEOP(LATF); // Port F: write outputs + pic32_gpio_write(s, 5, VALUE(LATF)); + return; + WRITEOP(ODCF); return; // Port F: open drain configuration + WRITEOP(CNPUF); return; // Input pin pull-up + WRITEOP(CNPDF); return; // Input pin pull-down + WRITEOP(CNCONF); return; // Interrupt-on-change control + WRITEOP(CNENF); return; // Input change interrupt enable + WRITEOP(CNSTATF); return; // Input change status + + WRITEOP(ANSELG); return; // Port G: analog select + WRITEOP(TRISG); return; // Port G: mask of inputs + WRITEOPX(PORTG, LATG); // Port G: write outputs + WRITEOP(LATG); // Port G: write outputs + pic32_gpio_write(s, 6, VALUE(LATG)); + return; + WRITEOP(ODCG); return; // Port G: open drain configuration + WRITEOP(CNPUG); return; // Input pin pull-up + WRITEOP(CNPDG); return; // Input pin pull-down + WRITEOP(CNCONG); return; // Interrupt-on-change control + WRITEOP(CNENG); return; // Input change interrupt enable + WRITEOP(CNSTATG); return; // Input change status + + WRITEOP(ANSELH); return; // Port H: analog select + WRITEOP(TRISH); return; // Port H: mask of inputs + WRITEOPX(PORTH, LATH); // Port H: write outputs + WRITEOP(LATH); // Port H: write outputs + pic32_gpio_write(s, 7, VALUE(LATH)); + return; + WRITEOP(ODCH); return; // Port H: open drain configuration + WRITEOP(CNPUH); return; // Input pin pull-up + WRITEOP(CNPDH); return; // Input pin pull-down + WRITEOP(CNCONH); return; // Interrupt-on-change control + WRITEOP(CNENH); return; // Input change interrupt enable + WRITEOP(CNSTATH); return; // Input change status + + WRITEOP(ANSELJ); return; // Port J: analog select + WRITEOP(TRISJ); return; // Port J: mask of inputs + WRITEOPX(PORTJ, LATJ); // Port J: write outputs + WRITEOP(LATJ); // Port J: write outputs + pic32_gpio_write(s, 8, VALUE(LATJ)); + return; + WRITEOP(ODCJ); return; // Port J: open drain configuration + WRITEOP(CNPUJ); return; // Input pin pull-up + WRITEOP(CNPDJ); return; // Input pin pull-down + WRITEOP(CNCONJ); return; // Interrupt-on-change control + WRITEOP(CNENJ); return; // Input change interrupt enable + WRITEOP(CNSTATJ); return; // Input change status + + WRITEOP(TRISK); return; // Port K: mask of inputs + WRITEOPX(PORTK, LATK); // Port K: write outputs + WRITEOP(LATK); // Port K: write outputs + pic32_gpio_write(s, 9, VALUE(LATK)); + return; + WRITEOP(ODCK); return; // Port K: open drain configuration + WRITEOP(CNPUK); return; // Input pin pull-up + WRITEOP(CNPDK); return; // Input pin pull-down + WRITEOP(CNCONK); return; // Interrupt-on-change control + WRITEOP(CNENK); return; // Input change interrupt enable + WRITEOP(CNSTATK); return; // Input change status + + /*------------------------------------------------------------------------- + * UART 1. + */ + STORAGE(U1TXREG); // Transmit + pic32_uart_put_char(s, 0, data); + break; + WRITEOP(U1MODE); // Mode + pic32_uart_update_mode(s, 0); + return; + WRITEOPR(U1STA, // Status and control + PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR | + PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF); + pic32_uart_update_status(s, 0); + return; + WRITEOP(U1BRG); return; // Baud rate + READONLY(U1RXREG); // Receive + + /*------------------------------------------------------------------------- + * UART 2. + */ + STORAGE(U2TXREG); // Transmit + pic32_uart_put_char(s, 1, data); + break; + WRITEOP(U2MODE); // Mode + pic32_uart_update_mode(s, 1); + return; + WRITEOPR(U2STA, // Status and control + PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR | + PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF); + pic32_uart_update_status(s, 1); + return; + WRITEOP(U2BRG); return; // Baud rate + READONLY(U2RXREG); // Receive + + /*------------------------------------------------------------------------- + * UART 3. + */ + STORAGE(U3TXREG); // Transmit + pic32_uart_put_char(s, 2, data); + break; + WRITEOP(U3MODE); // Mode + pic32_uart_update_mode(s, 2); + return; + WRITEOPR(U3STA, // Status and control + PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR | + PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF); + pic32_uart_update_status(s, 2); + return; + WRITEOP(U3BRG); return; // Baud rate + READONLY(U3RXREG); // Receive + + /*------------------------------------------------------------------------- + * UART 4. + */ + STORAGE(U4TXREG); // Transmit + pic32_uart_put_char(s, 3, data); + break; + WRITEOP(U4MODE); // Mode + pic32_uart_update_mode(s, 3); + return; + WRITEOPR(U4STA, // Status and control + PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR | + PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF); + pic32_uart_update_status(s, 3); + return; + WRITEOP(U4BRG); return; // Baud rate + READONLY(U4RXREG); // Receive + + /*------------------------------------------------------------------------- + * UART 5. + */ + STORAGE(U5TXREG); // Transmit + pic32_uart_put_char(s, 4, data); + break; + WRITEOP(U5MODE); // Mode + pic32_uart_update_mode(s, 4); + return; + WRITEOPR(U5STA, // Status and control + PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR | + PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF); + pic32_uart_update_status(s, 4); + return; + WRITEOP(U5BRG); return; // Baud rate + READONLY(U5RXREG); // Receive + + /*------------------------------------------------------------------------- + * UART 6. + */ + STORAGE(U6TXREG); // Transmit + pic32_uart_put_char(s, 5, data); + break; + WRITEOP(U6MODE); // Mode + pic32_uart_update_mode(s, 5); + return; + WRITEOPR(U6STA, // Status and control + PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR | + PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF); + pic32_uart_update_status(s, 5); + return; + WRITEOP(U6BRG); return; // Baud rate + READONLY(U6RXREG); // Receive + + /*------------------------------------------------------------------------- + * SPI. + */ + WRITEOP(SPI1CON); // Control + pic32_spi_control(s, 0); + return; + WRITEOPR(SPI1STAT, ~PIC32_SPISTAT_SPIROV); // Status + return; // Only ROV bit is writable + STORAGE(SPI1BUF); // Buffer + pic32_spi_writebuf(s, 0, data); + return; + WRITEOP(SPI1BRG); return; // Baud rate + WRITEOP(SPI1CON2); return; // Control 2 + + WRITEOP(SPI2CON); // Control + pic32_spi_control(s, 1); + return; + WRITEOPR(SPI2STAT, ~PIC32_SPISTAT_SPIROV); // Status + return; // Only ROV bit is writable + STORAGE(SPI2BUF); // Buffer + pic32_spi_writebuf(s, 1, data); + return; + WRITEOP(SPI2BRG); return; // Baud rate + WRITEOP(SPI2CON2); return; // Control 2 + + WRITEOP(SPI3CON); // Control + pic32_spi_control(s, 2); + return; + WRITEOPR(SPI3STAT, ~PIC32_SPISTAT_SPIROV); // Status + return; // Only ROV bit is writable + STORAGE(SPI3BUF); // Buffer + pic32_spi_writebuf(s, 2, data); + return; + WRITEOP(SPI3BRG); return; // Baud rate + WRITEOP(SPI3CON2); return; // Control 2 + + WRITEOP(SPI4CON); // Control + pic32_spi_control(s, 3); + return; + WRITEOPR(SPI4STAT, ~PIC32_SPISTAT_SPIROV); // Status + return; // Only ROV bit is writable + STORAGE(SPI4BUF); // Buffer + pic32_spi_writebuf(s, 3, data); + return; + WRITEOP(SPI4BRG); return; // Baud rate + WRITEOP(SPI4CON2); return; // Control 2 + + /*------------------------------------------------------------------------- + * Ethernet. + */ + WRITEOP(ETHCON1); return; // Control 1 + WRITEOP(ETHCON2); return; // Control 2: RX data buffer size + WRITEOP(ETHTXST); return; // Tx descriptor start address + WRITEOP(ETHRXST); return; // Rx descriptor start address + WRITEOP(ETHHT0); return; // Hash tasble 0 + WRITEOP(ETHHT1); return; // Hash tasble 1 + WRITEOP(ETHPMM0); return; // Pattern match mask 0 + WRITEOP(ETHPMM1); return; // Pattern match mask 1 + WRITEOP(ETHPMCS); return; // Pattern match checksum + WRITEOP(ETHPMO); return; // Pattern match offset + WRITEOP(ETHRXFC); return; // Receive filter configuration + WRITEOP(ETHRXWM); return; // Receive watermarks + WRITEOP(ETHIEN); return; // Interrupt enable + WRITEOP(ETHIRQ); return; // Interrupt request + STORAGE(ETHSTAT); break; // Status + WRITEOP(ETHRXOVFLOW); return; // Receive overflow statistics + WRITEOP(ETHFRMTXOK); return; // Frames transmitted OK statistics + WRITEOP(ETHSCOLFRM); return; // Single collision frames statistics + WRITEOP(ETHMCOLFRM); return; // Multiple collision frames statistics + WRITEOP(ETHFRMRXOK); return; // Frames received OK statistics + WRITEOP(ETHFCSERR); return; // Frame check sequence error statistics + WRITEOP(ETHALGNERR); return; // Alignment errors statistics + WRITEOP(EMAC1CFG1); return; // MAC configuration 1 + WRITEOP(EMAC1CFG2); return; // MAC configuration 2 + WRITEOP(EMAC1IPGT); return; // MAC back-to-back interpacket gap + WRITEOP(EMAC1IPGR); return; // MAC non-back-to-back interpacket gap + WRITEOP(EMAC1CLRT); return; // MAC collision window/retry limit + WRITEOP(EMAC1MAXF); return; // MAC maximum frame length + WRITEOP(EMAC1SUPP); return; // MAC PHY support + WRITEOP(EMAC1TEST); return; // MAC test + WRITEOP(EMAC1MCFG); return; // MII configuration + WRITEOP(EMAC1MCMD); return; // MII command + WRITEOP(EMAC1MADR); return; // MII address + WRITEOP(EMAC1MWTD); return; // MII write data + WRITEOP(EMAC1MRDD); return; // MII read data + WRITEOP(EMAC1MIND); return; // MII indicators + WRITEOP(EMAC1SA0); return; // MAC station address 0 + WRITEOP(EMAC1SA1); return; // MAC station address 1 + WRITEOP(EMAC1SA2); return; // MAC station address 2 + + default: + printf("--- Write %08x to 1f8%05x: peripheral register not supported\n", + data, offset); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Write %08x to 1f8%05x: peripheral register not supported\n", + data, offset); + exit(1); +readonly: + printf("--- Write %08x to %s: readonly register\n", + data, *namep); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Write %08x to %s: readonly register\n", + data, *namep); + *namep = 0; + return; + } + *bufp = data; +} + +static uint64_t pic32_io_read(void *opaque, hwaddr addr, unsigned bytes) +{ + pic32_t *s = opaque; + uint32_t offset = addr & 0xfffff; + const char *name = "???"; + uint32_t data = 0; + + data = io_read32(s, offset & ~3, &name); + switch (bytes) { + case 1: + if ((offset &= 3) != 0) { + // Unaligned read. + data >>= offset * 8; + } + data = (uint8_t) data; + if (qemu_loglevel_mask(CPU_LOG_INSTR)) { + fprintf(qemu_logfile, "--- I/O Read %02x from %s\n", data, name); + } + break; + case 2: + if (offset & 2) { + // Unaligned read. + data >>= 16; + } + data = (uint16_t) data; + if (qemu_loglevel_mask(CPU_LOG_INSTR)) { + fprintf(qemu_logfile, "--- I/O Read %04x from %s\n", data, name); + } + break; + default: + if (qemu_loglevel_mask(CPU_LOG_INSTR)) { + fprintf(qemu_logfile, "--- I/O Read %08x from %s\n", data, name); + } + break; + } + return data; +} + +static void pic32_io_write(void *opaque, hwaddr addr, uint64_t data, unsigned bytes) +{ + pic32_t *s = opaque; + uint32_t offset = addr & 0xfffff; + const char *name = "???"; + + // Fetch data and align to word format. + switch (bytes) { + case 1: + data = (uint8_t) data; + data <<= (offset & 3) * 8; + break; + case 2: + data = (uint16_t) data; + data <<= (offset & 2) * 8; + break; + } + io_write32(s, offset & ~3, data, &name); + + if (qemu_loglevel_mask(CPU_LOG_INSTR) && name != 0) { + fprintf(qemu_logfile, "--- I/O Write %08x to %s\n", + (uint32_t) data, name); + } +} + +static const MemoryRegionOps pic32_io_ops = { + .read = pic32_io_read, + .write = pic32_io_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + +static void main_cpu_reset(void *opaque) +{ + MIPSCPU *cpu = opaque; + CPUMIPSState *env = &cpu->env; + int i; + + cpu_reset(CPU(cpu)); + + /* Adjust the initial configuration for microAptivP core. */ + env->CP0_IntCtl = 0x00030000; + env->CP0_Debug = (1 << CP0DB_CNT) | (5 << CP0DB_VER); + env->CP0_Performance0 = 0x80000000; + for (i=0; i<7; i++) + env->CP0_WatchHi[i] = (i < 3) ? 0x80000000 : 0; +} + +static void store_byte(unsigned address, unsigned char byte) +{ + if (address >= PROGRAM_FLASH_START && + address < PROGRAM_FLASH_START + PROGRAM_FLASH_SIZE) + { + //printf("Store %02x to program memory %08x\n", byte, address); + prog_ptr[address & 0xfffff] = byte; + } + else if (address >= BOOT_FLASH_START && + address < BOOT_FLASH_START + BOOT_FLASH_SIZE) + { + //printf("Store %02x to boot memory %08x\n", byte, address); + boot_ptr[address & 0xffff] = byte; + } + else { + printf("Bad hex file: incorrect address %08X, must be %08X-%08X or %08X-%08X\n", + address, PROGRAM_FLASH_START, + PROGRAM_FLASH_START + PROGRAM_FLASH_SIZE - 1, + BOOT_FLASH_START, BOOT_FLASH_START + BOOT_FLASH_SIZE - 1); + exit(1); + } +} + +/* + * Ignore ^C and ^\ signals and pass these characters to the target. + */ +static void pic32_pass_signal_chars(void) +{ + struct termios tty; + + tcgetattr(0, &tty); + tty.c_lflag &= ~ISIG; + tcsetattr(0, TCSANOW, &tty); +} + +static void pic32_init(MachineState *machine, int board_type) +{ + const char *cpu_model = machine->cpu_model; + unsigned ram_size = DATA_MEM_SIZE; + MemoryRegion *system_memory = get_system_memory(); + MemoryRegion *ram_main = g_new(MemoryRegion, 1); + MemoryRegion *prog_mem = g_new(MemoryRegion, 1); + MemoryRegion *boot_mem = g_new(MemoryRegion, 1); + MemoryRegion *io_mem = g_new(MemoryRegion, 1); + MIPSCPU *cpu; + CPUMIPSState *env; + + DeviceState *dev = qdev_create(NULL, TYPE_MIPS_PIC32); + pic32_t *s = OBJECT_CHECK(pic32_t, dev, TYPE_MIPS_PIC32); + s->board_type = board_type; + s->stop_on_reset = 1; /* halt simulation on soft reset */ + s->iomem = g_malloc0(IO_MEM_SIZE); /* backing storage for I/O area */ + + qdev_init_nofail(dev); + + /* Init CPU. */ + if (! cpu_model) { + cpu_model = "microAptivP"; + } + printf("Board: %s\n", board_name[board_type]); + if (qemu_logfile) + fprintf(qemu_logfile, "Board: %s\n", board_name[board_type]); + + printf("Processor: %s\n", cpu_model); + if (qemu_logfile) + fprintf(qemu_logfile, "Processor: %s\n", cpu_model); + + cpu = cpu_mips_init(cpu_model); + if (! cpu) { + fprintf(stderr, "Unable to find CPU definition\n"); + exit(1); + } + s->cpu = cpu; + env = &cpu->env; + + /* Register RAM */ + printf("RAM size: %u kbytes\n", ram_size / 1024); + if (qemu_logfile) + fprintf(qemu_logfile, "RAM size: %u kbytes\n", ram_size / 1024); + + memory_region_init_ram(ram_main, NULL, "kernel.ram", + ram_size, &error_abort); + vmstate_register_ram_global(ram_main); + memory_region_add_subregion(system_memory, DATA_MEM_START, ram_main); + + /* Special function registers. */ + memory_region_init_io(io_mem, NULL, &pic32_io_ops, s, + "io", IO_MEM_SIZE); + memory_region_add_subregion(system_memory, IO_MEM_START, io_mem); + + /* + * Map the flash memory. + */ + memory_region_init_ram(boot_mem, NULL, "boot.flash", BOOT_FLASH_SIZE, &error_abort); + memory_region_init_ram(prog_mem, NULL, "prog.flash", PROGRAM_FLASH_SIZE, &error_abort); + + /* Load a Flash memory image. */ + if (! machine->kernel_filename) { + error_report("No -kernel argument was specified."); + exit(1); + } + prog_ptr = memory_region_get_ram_ptr(prog_mem); + boot_ptr = memory_region_get_ram_ptr(boot_mem); + if (bios_name) + pic32_load_hex_file(bios_name, store_byte); + pic32_load_hex_file(machine->kernel_filename, store_byte); + + memory_region_set_readonly(boot_mem, true); + memory_region_set_readonly(prog_mem, true); + memory_region_add_subregion(system_memory, BOOT_FLASH_START, boot_mem); + memory_region_add_subregion(system_memory, PROGRAM_FLASH_START, prog_mem); + + /* Init internal devices */ + s->irq_raise = irq_raise; + s->irq_clear = irq_clear; + qemu_register_reset(main_cpu_reset, cpu); + + /* Setup interrupt controller in EIC mode. */ + env->CP0_Config3 |= 1 << CP0C3_VEIC; + cpu_mips_irq_init_cpu(env); + env->eic_timer_irq = pic32_timer_irq; + env->eic_soft_irq = pic32_soft_irq; + env->eic_context = s; + + /* CPU runs at 200MHz. + * Count register increases at half this rate. */ + cpu_mips_clock_init(env, 100*1000*1000); + + /* + * Initialize board-specific parameters. + */ + int cs0_port, cs0_pin, cs1_port, cs1_pin; + switch (board_type) { + default: + case BOARD_WIFIRE: // console on UART4 + BOOTMEM(DEVCFG0) = 0xfffffff7; + BOOTMEM(DEVCFG1) = 0x7f743cb9; + BOOTMEM(DEVCFG2) = 0xfff9b11a; + BOOTMEM(DEVCFG3) = 0xbeffffff; + VALUE(DEVID) = 0x4510e053; // MZ2048ECG100 rev A4 + VALUE(OSCCON) = 0x00001120; // external oscillator 24MHz + s->sdcard_spi_port = 2; // SD card at SPI3, + cs0_port = 2; cs0_pin = 3; // select0 at C3, + cs1_port = -1; cs1_pin = -1; // select1 not available + break; + case BOARD_MEBII: // console on UART1 + BOOTMEM(DEVCFG0) = 0x7fffffdb; + BOOTMEM(DEVCFG1) = 0x0000fc81; + BOOTMEM(DEVCFG2) = 0x3ff8b11a; + BOOTMEM(DEVCFG3) = 0x86ffffff; + VALUE(DEVID) = 0x45127053; // MZ2048ECH144 rev A4 + VALUE(OSCCON) = 0x00001120; // external oscillator 24MHz + s->sdcard_spi_port = 1; // SD card at SPI2, + cs0_port = 1; cs0_pin = 14; // select0 at B14, + cs1_port = -1; cs1_pin = -1; // select1 not available + break; + case BOARD_EXPLORER16: // console on UART1 + BOOTMEM(DEVCFG0) = 0x7fffffdb; + BOOTMEM(DEVCFG1) = 0x0000fc81; + BOOTMEM(DEVCFG2) = 0x3ff8b11a; + BOOTMEM(DEVCFG3) = 0x86ffffff; + VALUE(DEVID) = 0x35113053; // MZ2048ECH100 rev A3 + VALUE(OSCCON) = 0x00001120; // external oscillator 24MHz + s->sdcard_spi_port = 0; // SD card at SPI1, + cs0_port = 1; cs0_pin = 1; // select0 at B1, + cs1_port = 1; cs1_pin = 2; // select1 at B2 + break; + } + + /* UARTs */ + pic32_uart_init(s, 0, PIC32_IRQ_U1E, U1STA, U1MODE); + pic32_uart_init(s, 1, PIC32_IRQ_U2E, U2STA, U2MODE); + pic32_uart_init(s, 2, PIC32_IRQ_U3E, U3STA, U3MODE); + pic32_uart_init(s, 3, PIC32_IRQ_U4E, U4STA, U4MODE); + pic32_uart_init(s, 4, PIC32_IRQ_U5E, U5STA, U5MODE); + pic32_uart_init(s, 5, PIC32_IRQ_U6E, U6STA, U6MODE); + + /* SPIs */ + pic32_spi_init(s, 0, PIC32_IRQ_SPI1E, SPI1CON, SPI1STAT); + pic32_spi_init(s, 1, PIC32_IRQ_SPI2E, SPI2CON, SPI2STAT); + pic32_spi_init(s, 2, PIC32_IRQ_SPI3E, SPI3CON, SPI3STAT); + pic32_spi_init(s, 3, PIC32_IRQ_SPI4E, SPI4CON, SPI4STAT); + pic32_spi_init(s, 4, PIC32_IRQ_SPI5E, SPI5CON, SPI5STAT); + pic32_spi_init(s, 5, PIC32_IRQ_SPI6E, SPI6CON, SPI6STAT); + + /* + * Load SD card images. + * Use options: + * -sd filename + * or -hda filename + * and -hdb filename + */ + const char *sd0_file = 0, *sd1_file = 0; + DriveInfo *dinfo = drive_get(IF_IDE, 0, 0); + if (dinfo) { + sd0_file = qemu_opt_get(dinfo->opts, "file"); + dinfo->is_default = 1; + + dinfo = drive_get(IF_IDE, 0, 1); + if (dinfo) { + sd1_file = qemu_opt_get(dinfo->opts, "file"); + dinfo->is_default = 1; + } + } + if (! sd0_file) { + dinfo = drive_get(IF_SD, 0, 0); + if (dinfo) { + sd0_file = qemu_opt_get(dinfo->opts, "file"); + dinfo->is_default = 1; + } + } + pic32_sdcard_init(s, 0, "sd0", sd0_file, cs0_port, cs0_pin); + pic32_sdcard_init(s, 1, "sd1", sd1_file, cs1_port, cs1_pin); + + io_reset(s); + pic32_sdcard_reset(s); + pic32_pass_signal_chars(); +} + +static void pic32_init_wifire(MachineState *machine) +{ + pic32_init(machine, BOARD_WIFIRE); +} + +static void pic32_init_meb2(MachineState *machine) +{ + pic32_init(machine, BOARD_MEBII); +} + +static void pic32_init_explorer16(MachineState *machine) +{ + pic32_init(machine, BOARD_EXPLORER16); +} + +static int pic32_sysbus_device_init(SysBusDevice *sysbusdev) +{ + return 0; +} + +static void pic32_class_init(ObjectClass *klass, void *data) +{ + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = pic32_sysbus_device_init; +} + +static const TypeInfo pic32_device = { + .name = TYPE_MIPS_PIC32, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(pic32_t), + .class_init = pic32_class_init, +}; + +static void pic32_register_types(void) +{ + type_register_static(&pic32_device); +} + +static QEMUMachine pic32_board[3] = { + { + .name = "pic32mz-wifire", + .desc = "PIC32MZ microcontroller on chipKIT WiFire board", + .init = pic32_init_wifire, + .max_cpus = 1, + }, + { + .name = "pic32mz-meb2", + .desc = "PIC32MZ microcontroller on Microchip MEB-II board", + .init = pic32_init_meb2, + .max_cpus = 1, + }, + { + .name = "pic32mz-explorer16", + .desc = "PIC32MZ microcontroller on Microchip Explorer-16 board", + .init = pic32_init_explorer16, + .max_cpus = 1, + }, +}; + +static void pic32_machine_init(void) +{ + qemu_register_machine(&pic32_board[0]); + qemu_register_machine(&pic32_board[1]); + qemu_register_machine(&pic32_board[2]); +} + +type_init(pic32_register_types) +machine_init(pic32_machine_init); + +#endif /* !TARGET_MIPS64 && !TARGET_WORDS_BIGENDIAN */ diff --git a/hw/mips/pic32_gpio.c b/hw/mips/pic32_gpio.c new file mode 100644 index 0000000000000..d39299b656171 --- /dev/null +++ b/hw/mips/pic32_gpio.c @@ -0,0 +1,39 @@ +/* + * GPIO ports. + * + * Copyright (C) 2015 Serge Vakulenko + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ +#include "hw/hw.h" +#include "pic32_peripherals.h" + +#include "pic32mz.h" + +void pic32_gpio_write(pic32_t *s, int gpio_port, unsigned lat_value) +{ + /* Control SD card 0 */ + if (gpio_port == s->sdcard[0].gpio_port && s->sdcard[0].gpio_cs) { + pic32_sdcard_select(s, 0, ! (lat_value & s->sdcard[0].gpio_cs)); + } + /* Control SD card 1 */ + if (gpio_port == s->sdcard[1].gpio_port && s->sdcard[0].gpio_cs) { + pic32_sdcard_select(s, 1, ! (lat_value & s->sdcard[1].gpio_cs)); + } +} diff --git a/hw/mips/pic32_load_hex.c b/hw/mips/pic32_load_hex.c new file mode 100644 index 0000000000000..a85f5da7d8c90 --- /dev/null +++ b/hw/mips/pic32_load_hex.c @@ -0,0 +1,230 @@ +#include +#include +#include +#include + +#include "pic32_peripherals.h" + +/* Macros for converting between hex and binary. */ +#define NIBBLE(x) (isdigit(x) ? (x)-'0' : tolower(x)+10-'a') +#define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1])) + +static unsigned virt_to_phys(unsigned address) +{ + if (address >= 0xa0000000 && address <= 0xbfffffff) + return address - 0xa0000000; + if (address >= 0x80000000 && address <= 0x9fffffff) + return address - 0x80000000; + return address; +} + +/* + * Read the S record file. + */ +static int load_srec(const char *filename, + void (*store_byte)(unsigned address, unsigned char byte)) +{ + FILE *fd; + unsigned char buf [256]; + unsigned char *data; + unsigned address; + int bytes, output_len; + + fd = fopen(filename, "r"); + if (! fd) { + perror(filename); + exit(1); + } + output_len = 0; + while (fgets((char*) buf, sizeof(buf), fd)) { + if (buf[0] == '\n') + continue; + if (buf[0] != 'S') { + if (output_len == 0) + break; + printf("%s: bad file format\n", filename); + exit(1); + } + + /* Starting an S-record. */ + if (! isxdigit(buf[2]) || ! isxdigit(buf[3])) { + printf("%s: bad record: %s\n", filename, buf); + exit(1); + } + bytes = HEX(buf + 2); + + /* Ignore the checksum byte. */ + --bytes; + + address = 0; + data = buf + 4; + switch (buf[1]) { + case '7': + address = HEX(data); + data += 2; + --bytes; + /* Fall through. */ + case '8': + address = (address << 8) | HEX(data); + data += 2; + --bytes; + /* Fall through. */ + case '9': + address = (address << 8) | HEX(data); + data += 2; + address = (address << 8) | HEX(data); + data += 2; + bytes -= 2; + if (bytes == 0) { + //printf("%s: start address = %08x\n", filename, address); + //TODO: set start address + } + goto done; + + case '3': + address = HEX(data); + data += 2; + --bytes; + /* Fall through. */ + case '2': + address = (address << 8) | HEX(data); + data += 2; + --bytes; + /* Fall through. */ + case '1': + address = (address << 8) | HEX(data); + data += 2; + address = (address << 8) | HEX(data); + data += 2; + bytes -= 2; + + address = virt_to_phys(address); + output_len += bytes; + while (bytes-- > 0) { + store_byte(address++, HEX(data)); + data += 2; + } + break; + } + } +done: + fclose(fd); + return output_len; +} + +/* + * Read HEX file. + */ +static int load_hex(const char *filename, + void (*store_byte)(unsigned address, unsigned char byte)) +{ + FILE *fd; + unsigned char buf [256], data[16], record_type, sum; + unsigned address, high; + int bytes, output_len, i; + + fd = fopen(filename, "r"); + if (! fd) { + perror(filename); + exit(1); + } + output_len = 0; + high = 0; + while (fgets((char*) buf, sizeof(buf), fd)) { + if (buf[0] == '\n') + continue; + if (buf[0] != ':') { + if (output_len == 0) + break; + printf("%s: bad HEX file format\n", filename); + exit(1); + } + if (! isxdigit(buf[1]) || ! isxdigit(buf[2]) || + ! isxdigit(buf[3]) || ! isxdigit(buf[4]) || + ! isxdigit(buf[5]) || ! isxdigit(buf[6]) || + ! isxdigit(buf[7]) || ! isxdigit(buf[8])) { + printf("%s: bad record: %s\n", filename, buf); + exit(1); + } + record_type = HEX(buf+7); + if (record_type == 1) { + /* End of file. */ + break; + } + bytes = HEX(buf+1); + if (strlen((char*) buf) < bytes * 2 + 11) { + printf("%s: too short hex line\n", filename); + exit(1); + } + address = high << 16 | HEX(buf+3) << 8 | HEX(buf+5); + if (address & 3) { + printf("%s: odd address\n", filename); + exit(1); + } + + sum = 0; + for (i=0; i> 8 & 0xff); + if (sum != (unsigned char) - HEX(buf+9 + bytes + bytes)) { + printf("%s: bad hex checksum\n", filename); + printf("Line %s", buf); + exit(1); + } + + if (record_type == 5) { + /* Start address. */ + if (bytes != 4) { + printf("%s: invalid length of hex start address record: %d bytes\n", + filename, bytes); + exit(1); + } + address = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; + //printf("%s: start address = %08x\n", filename, address); + //TODO: set start address + continue; + } + if (record_type == 4) { + /* Extended address. */ + if (bytes != 2) { + printf("%s: invalid length of hex linear address record: %d bytes\n", + filename, bytes); + exit(1); + } + high = data[0] << 8 | data[1]; + continue; + } + if (record_type != 0) { + printf("%s: unknown hex record type: %d\n", + filename, record_type); + exit(1); + } + + /* Data record found. */ + address = virt_to_phys(address); + output_len += bytes; + for (i=0; iiomem[(name & 0xfffff) >> 2] +#define STORAGE(name) case name: *namep = #name; +#define READONLY(name) case name: *namep = #name; goto readonly +#define WRITEOP(name) case name: *namep = #name; goto op_##name;\ + case name+4: *namep = #name"CLR"; goto op_##name;\ + case name+8: *namep = #name"SET"; goto op_##name;\ + case name+12: *namep = #name"INV"; op_##name: \ + VALUE(name) = write_op(VALUE(name), data, offset) +#define WRITEOPX(name,label) \ + case name: *namep = #name; goto op_##label;\ + case name+4: *namep = #name"CLR"; goto op_##label;\ + case name+8: *namep = #name"SET"; goto op_##label;\ + case name+12: *namep = #name"INV"; goto op_##label +#define WRITEOPR(name,romask) \ + case name: *namep = #name; goto op_##name;\ + case name+4: *namep = #name"CLR"; goto op_##name;\ + case name+8: *namep = #name"SET"; goto op_##name;\ + case name+12: *namep = #name"INV"; op_##name: \ + VALUE(name) &= romask; \ + VALUE(name) |= write_op(VALUE(name), data, offset) & ~(romask) diff --git a/hw/mips/pic32_sdcard.c b/hw/mips/pic32_sdcard.c new file mode 100644 index 0000000000000..821d23a5c0176 --- /dev/null +++ b/hw/mips/pic32_sdcard.c @@ -0,0 +1,388 @@ +/* + * SD/MMC card emulation. + * + * Copyright (C) 2011-2015 Serge Vakulenko + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ +#include "hw/hw.h" +#include "pic32_peripherals.h" + +//#define TRACE printf +#ifndef TRACE +#define TRACE(...) /*empty*/ +#endif + +/* + * Definitions for MMC/SDC commands. + */ +#define CMD_GO_IDLE (0x40+0) /* CMD0 */ +#define CMD_SEND_OP_SDC (0x40+41) /* ACMD41 (SDC) */ +#define CMD_SET_BLEN (0x40+16) +#define CMD_SEND_IF_COND (0x40+8) +#define CMD_SEND_CSD (0x40+9) +#define CMD_STOP (0x40+12) +#define CMD_READ_SINGLE (0x40+17) +#define CMD_READ_MULTIPLE (0x40+18) +#define CMD_SET_WBECNT (0x40+23) /* ACMD23 */ +#define CMD_WRITE_SINGLE (0x40+24) +#define CMD_WRITE_MULTIPLE (0x40+25) +#define CMD_APP (0x40+55) /* CMD55 */ + +#define DATA_START_BLOCK 0xFE /* start data for single block */ +#define STOP_TRAN_TOKEN 0xFD /* stop token for write multiple */ +#define WRITE_MULTIPLE_TOKEN 0xFC /* start data for write multiple */ + +static void read_data(int fd, unsigned offset, + unsigned char *buf, unsigned blen) +{ + /* Fill uninitialized blocks by FF: simulate real flash media. */ + memset(buf, 0xFF, blen); + + if (pread(fd, buf, blen, offset) != blen) { + printf("sdcard: pread failed, offset %#x\n", offset); + return; + } +#if 0 + printf("(%#x)\n", offset); + int i, k; + for (i=0; iselect = 0; + d->blen = 512; + d->count = 0; +} + +/* + * Reset sdcard. + */ +void pic32_sdcard_reset(pic32_t *s) +{ + card_reset(&s->sdcard[0]); + card_reset(&s->sdcard[1]); +} + +/* + * Initialize SD card. + */ +void pic32_sdcard_init(pic32_t *s, int unit, const char *name, + const char *filename, int cs_port, int cs_pin) +{ + sdcard_t *d = &s->sdcard[unit]; + struct stat st; + + memset(d, 0, sizeof(*d)); + d->name = name; + if (! filename) { + /* No SD card installed. */ + return; + } + d->gpio_port = cs_port; + d->gpio_cs = (cs_pin >= 0) ? (1 << cs_pin) : 0; + + d->fd = open(filename, O_RDWR); + if (d->fd < 0) { + /* Fatal: no image available. */ + perror(filename); + exit(1); + } + fstat(d->fd, &st); + d->kbytes = st.st_size / 1024; + printf("Card%u image '%s', %d kbytes\n", unit, filename, d->kbytes); + if (qemu_logfile) + fprintf(qemu_logfile, "Card%u image '%s', %d kbytes\n", + unit, filename, d->kbytes); +} + +void pic32_sdcard_select(pic32_t *s, int unit, int on) +{ + sdcard_t *d = &s->sdcard[unit]; + + if (on) { + //TRACE("sdcard%d: +++\n", unit); + d->select = 1; + d->count = 0; + } else { + //TRACE("sdcard%d: ---\n", unit); + d->select = 0; + } +} + +/* + * Data i/o: send byte to device. + * Return received byte. + */ +unsigned pic32_sdcard_io(pic32_t *s, unsigned data) +{ + sdcard_t *d = s->sdcard[0].select ? &s->sdcard[0] : + s->sdcard[1].select ? &s->sdcard[1] : 0; + unsigned reply; + + if (! d || ! d->fd) { + //TRACE("sdcard: unselected i/o\n"); + return 0xFF; + } + data = (unsigned char) data; + reply = 0xFF; + if (d->count == 0) { + d->buf[0] = data; + if (data != 0xFF) + d->count++; + } else { + switch (d->buf[0]) { + case CMD_GO_IDLE: /* CMD0: reset */ + if (d->count >= 7) + break; + d->buf [d->count++] = data; + if (d->count == 7) + reply = 0x01; + break; + case CMD_APP: /* CMD55: application prefix */ + if (d->count >= 7) + break; + d->buf [d->count++] = data; + if (d->count == 7) { + reply = 0; + d->count = 0; + } + break; + case CMD_SEND_OP_SDC: /* ACMD41: initialization */ + if (d->count >= 7) + break; + d->buf [d->count++] = data; + if (d->count == 7) + reply = 0; + break; + case CMD_SET_BLEN: /* Set block length */ + if (d->count >= 7) + break; + d->buf [d->count++] = data; + if (d->count == 7) { + d->blen = d->buf[1] << 24 | d->buf[2] << 16 | + d->buf[3] << 8 | d->buf[4]; + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- SD card %d: set block length %u bytes\n", + d->unit, d->blen); + reply = (d->blen > 0 && d->blen <= 1024) ? 0 : 4; + } + break; + case CMD_SET_WBECNT: /* Set write block erase count */ + if (d->count >= 7) + break; + d->buf [d->count++] = data; + if (d->count == 7) { + d->wbecnt = d->buf[1] << 24 | d->buf[2] << 16 | + d->buf[3] << 8 | d->buf[4]; + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- SD card %d: set write block erase count %u\n", + d->unit, d->wbecnt); + reply = 0; + d->count = 0; + } + break; + case CMD_SEND_CSD: /* Get card data */ + if (d->count >= 7) + break; + d->buf [d->count++] = data; + if (d->count == 7) { + /* Send reply */ + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- SD card %d: send media size %u sectors\n", + d->unit, d->kbytes * 2); + reply = 0; + d->limit = 16 + 3; + d->count = 1; + d->buf[0] = 0; + d->buf[1] = DATA_START_BLOCK; + d->buf[2+0] = 1 << 6; /* SDC ver 2.00 */ + d->buf[2+1] = 0; + d->buf[2+2] = 0; + d->buf[2+3] = 0; + d->buf[2+4] = 0; + d->buf[2+5] = 0; + d->buf[2+6] = 0; + d->buf[2+7] = 0; + d->buf[2+8] = (d->kbytes / 512 - 1) >> 8; + d->buf[2+9] = d->kbytes / 512 - 1; + d->buf[2+10] = 0; + d->buf[2+11] = 0; + d->buf[2+12] = 0; + d->buf[2+13] = 0; + d->buf[2+14] = 0; + d->buf[2+15] = 0; + d->buf[d->limit - 1] = 0xFF; + d->buf[d->limit] = 0xFF; + } + break; + case CMD_READ_SINGLE: /* Read block */ + if (d->count >= 7) + break; + d->buf [d->count++] = data; + if (d->count == 7) { + /* Send reply */ + reply = 0; + d->offset = d->buf[1] << 24 | d->buf[2] << 16 | + d->buf[3] << 8 | d->buf[4]; + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- SD card %d: read offset %#x, length %u bytes\n", + d->unit, d->offset, d->blen); + d->limit = d->blen + 3; + d->count = 1; + d->buf[0] = 0; + d->buf[1] = DATA_START_BLOCK; + read_data(d->fd, d->offset, &d->buf[2], d->blen); + d->buf[d->limit - 1] = 0xFF; + d->buf[d->limit] = 0xFF; + } + break; + case CMD_READ_MULTIPLE: /* Read multiple blocks */ + if (d->count >= 7) + break; + d->buf [d->count++] = data; + if (d->count == 7) { + /* Send reply */ + reply = 0; + d->read_multiple = 1; + d->offset = d->buf[1] << 24 | d->buf[2] << 16 | + d->buf[3] << 8 | d->buf[4]; + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- SD card %d: read offset %#x, length %u bytes\n", + d->unit, d->offset, d->blen); + d->limit = d->blen + 3; + d->count = 1; + d->buf[0] = 0; + d->buf[1] = DATA_START_BLOCK; + read_data(d->fd, d->offset, &d->buf[2], d->blen); + d->buf[d->limit - 1] = 0xFF; + d->buf[d->limit] = 0xFF; + } + break; + case CMD_WRITE_SINGLE: /* Write block */ + if (d->count >= sizeof(d->buf)) + break; + d->buf [d->count++] = data; + if (d->count == 7) { + /* Accept command */ + reply = 0; + d->offset = d->buf[1] << 24 | d->buf[2] << 16 | + d->buf[3] << 8 | d->buf[4]; + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- SD card %d: write offset %#x\n", + d->unit, d->offset); + } else if (d->count == 7 + d->blen + 2 + 2) { + if (d->buf[7] == DATA_START_BLOCK) { + /* Accept data */ + reply = 0x05; + d->offset = d->buf[1] << 24 | d->buf[2] << 16 | + d->buf[3] << 8 | d->buf[4]; + write_data(d->fd, d->offset, &d->buf[8], d->blen); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- SD card %d: write data, length %u bytes\n", + d->unit, d->blen); + } else { + /* Reject data */ + reply = 4; + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- SD card %d: reject write data, tag=%02x\n", + d->unit, d->buf[7]); + } + } + break; + case CMD_WRITE_MULTIPLE: /* Write multiple blocks */ + if (d->count >= 7) + break; + d->buf [d->count++] = data; + if (d->count == 7) { + /* Accept command */ + reply = 0; + d->offset = d->buf[1] << 24 | d->buf[2] << 16 | + d->buf[3] << 8 | d->buf[4]; + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- SD card %d: write multiple offset %#x\n", + d->unit, d->offset); + d->count = 0; + } + break; + case WRITE_MULTIPLE_TOKEN: /* Data for write-miltiple */ + if (d->count >= sizeof(d->buf)) + break; + d->buf [d->count++] = data; + if (d->count == 2 + d->blen + 2) { + /* Accept data */ + reply = 0x05; + write_data(d->fd, d->offset, &d->buf[1], d->blen); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- SD card %d: write sector %u, length %u bytes\n", + d->unit, d->offset / 512, d->blen); + d->offset += 512; + d->count = 0; + } + break; + case CMD_STOP: /* Stop read-multiple sequence */ + if (d->count > 1) + break; + d->read_multiple = 0; + reply = 0; + break; + case CMD_SEND_IF_COND: /* Stop read-multiple sequence */ + if (d->count > 1) + break; + d->read_multiple = 0; + reply = 4; /* Unknown command */ + break; + case 0: /* Reply */ + if (d->count <= d->limit) { + reply = d->buf [d->count++]; + break; + } + if (d->read_multiple) { + /* Next read-multiple block. */ + d->offset += d->blen; + d->count = 1; + read_data(d->fd, d->offset, &d->buf[2], d->blen); + reply = 0; + } + break; + default: /* Ignore */ + break; + } + } + if (qemu_loglevel_mask(CPU_LOG_INSTR)) { + TRACE("sdcard%d: send %02x, reply %02x\n", d->unit, data, reply); + } + return reply; +} diff --git a/hw/mips/pic32_spi.c b/hw/mips/pic32_spi.c new file mode 100644 index 0000000000000..985fd0c720002 --- /dev/null +++ b/hw/mips/pic32_spi.c @@ -0,0 +1,121 @@ +/* + * SPI ports. + * + * Copyright (C) 2014-2015 Serge Vakulenko + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ +#include "hw/hw.h" +#include "pic32_peripherals.h" + +#include "pic32mz.h" + +#define SPI_IRQ_FAULT 0 // error irq offset +#define SPI_IRQ_TX 1 // transmitter irq offset +#define SPI_IRQ_RX 2 // receiver irq offset + +unsigned pic32_spi_readbuf(pic32_t *s, int unit) +{ + spi_t *p = &s->spi[unit]; + unsigned result = p->buf[p->rfifo]; + + if (VALUE(p->con) & PIC32_SPICON_ENHBUF) { + p->rfifo++; + p->rfifo &= 3; + } + if (VALUE(p->stat) & PIC32_SPISTAT_SPIRBF) { + VALUE(p->stat) &= ~PIC32_SPISTAT_SPIRBF; + //s->irq_clear(s, p->irq + SPI_IRQ_RX); + } + return result; +} + +void pic32_spi_writebuf(pic32_t *s, int unit, unsigned val) +{ + spi_t *p = &s->spi[unit]; + + /* Perform SD card i/o on configured SPI port. */ + if (unit == s->sdcard_spi_port) { + unsigned result = 0; + + if (VALUE(p->con) & PIC32_SPICON_MODE32) { + /* 32-bit data width */ + result = (unsigned char) pic32_sdcard_io(s, val >> 24) << 24; + result |= (unsigned char) pic32_sdcard_io(s, val >> 16) << 16; + result |= (unsigned char) pic32_sdcard_io(s, val >> 8) << 8; + result |= (unsigned char) pic32_sdcard_io(s, val); + + } else if (VALUE(p->con) & PIC32_SPICON_MODE16) { + /* 16-bit data width */ + result = (unsigned char) pic32_sdcard_io(s, val >> 8) << 8; + result |= (unsigned char) pic32_sdcard_io(s, val); + + } else { + /* 8-bit data width */ + result = (unsigned char) pic32_sdcard_io(s, val); + } + p->buf[p->wfifo] = result; + } else { + /* No device */ + p->buf[p->wfifo] = ~0; + } + if (VALUE(p->stat) & PIC32_SPISTAT_SPIRBF) { + VALUE(p->stat) |= PIC32_SPISTAT_SPIROV; + //s->irq_raise(s, p->irq + SPI_IRQ_FAULT); + } else if (VALUE(p->con) & PIC32_SPICON_ENHBUF) { + p->wfifo++; + p->wfifo &= 3; + if (p->wfifo == p->rfifo) { + VALUE(p->stat) |= PIC32_SPISTAT_SPIRBF; + //s->irq_raise(s, p->irq + SPI_IRQ_RX); + } + } else { + VALUE(p->stat) |= PIC32_SPISTAT_SPIRBF; + //s->irq_raise(s, p->irq + SPI_IRQ_RX); + } +} + +void pic32_spi_control(pic32_t *s, int unit) +{ + spi_t *p = &s->spi[unit]; + + if (! (VALUE(p->con) & PIC32_SPICON_ON)) { + s->irq_clear(s, p->irq + SPI_IRQ_FAULT); + s->irq_clear(s, p->irq + SPI_IRQ_RX); + s->irq_clear(s, p->irq + SPI_IRQ_TX); + VALUE(p->stat) = PIC32_SPISTAT_SPITBE; + } else if (! (VALUE(p->con) & PIC32_SPICON_ENHBUF)) { + p->rfifo = 0; + p->wfifo = 0; + } +} + +/* + * Initialize the SPI data structure. + */ +void pic32_spi_init(pic32_t *s, int unit, int irq, int con, int stat) +{ + spi_t *p = &s->spi[unit]; + + p->irq = irq; + p->con = con; + p->stat = stat; + p->rfifo = 0; + p->wfifo = 0; +} diff --git a/hw/mips/pic32_uart.c b/hw/mips/pic32_uart.c new file mode 100644 index 0000000000000..2b21f1b7808ff --- /dev/null +++ b/hw/mips/pic32_uart.c @@ -0,0 +1,226 @@ +/* + * UART ports. + * + * Copyright (C) 2014-2015 Serge Vakulenko + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ +#include "hw/hw.h" +#include "hw/char/serial.h" +#include "sysemu/char.h" +#include "pic32_peripherals.h" + +#include "pic32mz.h" + +#define UART_IRQ_ERR 0 // error irq offset +#define UART_IRQ_RX 1 // receiver irq offset +#define UART_IRQ_TX 2 // transmitter irq offset + +/* + * Read of UxRXREG register. + */ +unsigned pic32_uart_get_char(pic32_t *s, int unit) +{ + uart_t *u = &s->uart[unit]; + unsigned value; + + /* Read a byte from input queue. */ + value = u->rxbyte; + VALUE(u->sta) &= ~PIC32_USTA_URXDA; + + s->irq_clear(s, u->irq + UART_IRQ_RX); + return value; +} + +/* + * Write to UxTXREG register. + */ +void pic32_uart_put_char(pic32_t *s, int unit, unsigned char byte) +{ + uart_t *u = &s->uart[unit]; + + if (! u->chr) { + printf("--- %s(unit = %u) serial port not configured\n", + __func__, unit); + return; + } + + /* Send the byte. */ + if (qemu_chr_fe_write(u->chr, &byte, 1) != 1) { + //TODO: suspend simulation until serial port ready + printf("--- %s(unit = %u) failed\n", __func__, unit); + return; + } + + if ((VALUE(u->mode) & PIC32_UMODE_ON) && + (VALUE(u->sta) & PIC32_USTA_UTXEN)) + { + VALUE(u->sta) |= PIC32_USTA_UTXBF; + VALUE(u->sta) &= ~PIC32_USTA_TRMT; + + /* Generate TX interrupt with some delay. */ + timer_mod(u->transmit_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + get_ticks_per_sec() / 5000); + u->oactive = 1; + } +} + +/* + * Called before reading a value of UxBRG, UxMODE or UxSTA registers. + */ +void pic32_uart_poll_status(pic32_t *s, int unit) +{ + uart_t *u = &s->uart[unit]; + + // Keep receiver idle, transmit shift register always empty + VALUE(u->sta) |= PIC32_USTA_RIDLE; + + //printf("<%x>", VALUE(u->sta)); fflush(stdout); +} + +/* + * Write to UxMODE register. + */ +void pic32_uart_update_mode(pic32_t *s, int unit) +{ + uart_t *u = &s->uart[unit]; + + if (! (VALUE(u->mode) & PIC32_UMODE_ON)) { + s->irq_clear(s, u->irq + UART_IRQ_RX); + s->irq_clear(s, u->irq + UART_IRQ_TX); + VALUE(u->sta) &= ~(PIC32_USTA_URXDA | PIC32_USTA_FERR | + PIC32_USTA_PERR | PIC32_USTA_UTXBF); + VALUE(u->sta) |= PIC32_USTA_RIDLE | PIC32_USTA_TRMT; + } +} + +/* + * Write to UxSTA register. + */ +void pic32_uart_update_status(pic32_t *s, int unit) +{ + uart_t *u = &s->uart[unit]; + + if (! (VALUE(u->sta) & PIC32_USTA_URXEN)) { + s->irq_clear(s, u->irq + UART_IRQ_RX); + VALUE(u->sta) &= ~(PIC32_USTA_URXDA | PIC32_USTA_FERR | + PIC32_USTA_PERR); + } + if (! (VALUE(u->sta) & PIC32_USTA_UTXEN)) { + s->irq_clear(s, u->irq + UART_IRQ_TX); + VALUE(u->sta) &= ~PIC32_USTA_UTXBF; + VALUE(u->sta) |= PIC32_USTA_TRMT; + } +} + +/* + * Return a number of free bytes in the receive FIFO. + */ +static int uart_can_receive(void *opaque) +{ + uart_t *u = opaque; + pic32_t *s = u->mcu; /* used in VALUE() */ + +//printf("--- %s(%p) called\n", __func__, u); + + if (! (VALUE(u->mode) & PIC32_UMODE_ON) || + ! (VALUE(u->sta) & PIC32_USTA_URXEN)) { + /* UART disabled. */ + return 0; + } + + if (VALUE(u->sta) & PIC32_USTA_URXDA) { + /* Receive buffer full. */ + return 0; + } + return 1; +} + +/* + * Process the received data. + */ +static void uart_receive(void *opaque, const uint8_t *buf, int size) +{ + uart_t *u = opaque; + pic32_t *s = u->mcu; /* used in VALUE() */ + +//printf("--- %s(%p) called\n", __func__, u); + if (! (VALUE(u->mode) & PIC32_UMODE_ON) || + ! (VALUE(u->sta) & PIC32_USTA_URXEN)) { + /* UART disabled. */ + return; + } + + if (VALUE(u->sta) & PIC32_USTA_URXDA) { + /* Receive buffer full. */ + return; + } + + u->rxbyte = buf[0]; + VALUE(u->sta) |= PIC32_USTA_URXDA; + + /* Activate receive interrupt. */ + s->irq_raise(s, u->irq + UART_IRQ_RX); +} + +/* + * Activate the transmit interrupt. + */ +static void uart_timeout(void *opaque) +{ + uart_t *u = opaque; + pic32_t *s = u->mcu; /* used in VALUE() */ + +//printf("--- %s() called\n", __func__); + if (u->oactive) { + /* Activate transmit interrupt. */ +//printf("uart%u: raise tx irq %u\n", unit, u->irq + UART_IRQ_TX); + if ((VALUE(u->mode) & PIC32_UMODE_ON) && + (VALUE(u->sta) & PIC32_USTA_UTXEN)) + s->irq_raise(s, u->irq + UART_IRQ_TX); + VALUE(u->sta) &= ~PIC32_USTA_UTXBF; + VALUE(u->sta) |= PIC32_USTA_TRMT; + u->oactive = 0; + } +} + +/* + * Initialize the UART data structure. + */ +void pic32_uart_init(pic32_t *s, int unit, int irq, int sta, int mode) +{ + uart_t *u = &s->uart[unit]; + + u->mcu = s; + u->irq = irq; + u->sta = sta; + u->mode = mode; + u->transmit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, uart_timeout, u); + + if (unit >= MAX_SERIAL_PORTS) { + /* Cannot instantiate so many serial ports. */ + u->chr = 0; + return; + } + u->chr = serial_hds[unit]; + + /* Setup callback functions. */ + if (u->chr) + qemu_chr_add_handlers(u->chr, uart_can_receive, uart_receive, NULL, u); +} diff --git a/hw/mips/pic32mx.h b/hw/mips/pic32mx.h new file mode 100644 index 0000000000000..ebb929286c948 --- /dev/null +++ b/hw/mips/pic32mx.h @@ -0,0 +1,1255 @@ +/* + * Hardware register defines for Microchip PIC32MX microcontrollers. + * + * Copyright (C) 2010 Serge Vakulenko + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ +#ifndef _IO_PIC32MX_H +#define _IO_PIC32MX_H + +/*-------------------------------------- + * Peripheral registers. + */ +#define PIC32_R(a) (a) + +/*-------------------------------------- + * UART registers. + */ +#define U1MODE PIC32_R (0x6000) /* Mode */ +#define U1MODECLR PIC32_R (0x6004) +#define U1MODESET PIC32_R (0x6008) +#define U1MODEINV PIC32_R (0x600C) +#define U1STA PIC32_R (0x6010) /* Status and control */ +#define U1STACLR PIC32_R (0x6014) +#define U1STASET PIC32_R (0x6018) +#define U1STAINV PIC32_R (0x601C) +#define U1TXREG PIC32_R (0x6020) /* Transmit */ +#define U1RXREG PIC32_R (0x6030) /* Receive */ +#define U1BRG PIC32_R (0x6040) /* Baud rate */ +#define U1BRGCLR PIC32_R (0x6044) +#define U1BRGSET PIC32_R (0x6048) +#define U1BRGINV PIC32_R (0x604C) + +#ifdef PIC32MX4 +#define U2MODE PIC32_R (0x6200) /* Mode */ +#define U2MODECLR PIC32_R (0x6204) +#define U2MODESET PIC32_R (0x6208) +#define U2MODEINV PIC32_R (0x620C) +#define U2STA PIC32_R (0x6210) /* Status and control */ +#define U2STACLR PIC32_R (0x6214) +#define U2STASET PIC32_R (0x6218) +#define U2STAINV PIC32_R (0x621C) +#define U2TXREG PIC32_R (0x6220) /* Transmit */ +#define U2RXREG PIC32_R (0x6230) /* Receive */ +#define U2BRG PIC32_R (0x6240) /* Baud rate */ +#define U2BRGCLR PIC32_R (0x6244) +#define U2BRGSET PIC32_R (0x6248) +#define U2BRGINV PIC32_R (0x624C) +#endif +#ifdef PIC32MX7 +#define U4MODE PIC32_R (0x6200) /* Mode */ +#define U4MODECLR PIC32_R (0x6204) +#define U4MODESET PIC32_R (0x6208) +#define U4MODEINV PIC32_R (0x620C) +#define U4STA PIC32_R (0x6210) /* Status and control */ +#define U4STACLR PIC32_R (0x6214) +#define U4STASET PIC32_R (0x6218) +#define U4STAINV PIC32_R (0x621C) +#define U4TXREG PIC32_R (0x6220) /* Transmit */ +#define U4RXREG PIC32_R (0x6230) /* Receive */ +#define U4BRG PIC32_R (0x6240) /* Baud rate */ +#define U4BRGCLR PIC32_R (0x6244) +#define U4BRGSET PIC32_R (0x6248) +#define U4BRGINV PIC32_R (0x624C) + +#define U3MODE PIC32_R (0x6400) /* Mode */ +#define U3MODECLR PIC32_R (0x6404) +#define U3MODESET PIC32_R (0x6408) +#define U3MODEINV PIC32_R (0x640C) +#define U3STA PIC32_R (0x6410) /* Status and control */ +#define U3STACLR PIC32_R (0x6414) +#define U3STASET PIC32_R (0x6418) +#define U3STAINV PIC32_R (0x641C) +#define U3TXREG PIC32_R (0x6420) /* Transmit */ +#define U3RXREG PIC32_R (0x6430) /* Receive */ +#define U3BRG PIC32_R (0x6440) /* Baud rate */ +#define U3BRGCLR PIC32_R (0x6444) +#define U3BRGSET PIC32_R (0x6448) +#define U3BRGINV PIC32_R (0x644C) + +#define U6MODE PIC32_R (0x6600) /* Mode */ +#define U6MODECLR PIC32_R (0x6604) +#define U6MODESET PIC32_R (0x6608) +#define U6MODEINV PIC32_R (0x660C) +#define U6STA PIC32_R (0x6610) /* Status and control */ +#define U6STACLR PIC32_R (0x6614) +#define U6STASET PIC32_R (0x6618) +#define U6STAINV PIC32_R (0x661C) +#define U6TXREG PIC32_R (0x6620) /* Transmit */ +#define U6RXREG PIC32_R (0x6630) /* Receive */ +#define U6BRG PIC32_R (0x6640) /* Baud rate */ +#define U6BRGCLR PIC32_R (0x6644) +#define U6BRGSET PIC32_R (0x6648) +#define U6BRGINV PIC32_R (0x664C) + +#define U2MODE PIC32_R (0x6800) /* Mode */ +#define U2MODECLR PIC32_R (0x6804) +#define U2MODESET PIC32_R (0x6808) +#define U2MODEINV PIC32_R (0x680C) +#define U2STA PIC32_R (0x6810) /* Status and control */ +#define U2STACLR PIC32_R (0x6814) +#define U2STASET PIC32_R (0x6818) +#define U2STAINV PIC32_R (0x681C) +#define U2TXREG PIC32_R (0x6820) /* Transmit */ +#define U2RXREG PIC32_R (0x6830) /* Receive */ +#define U2BRG PIC32_R (0x6840) /* Baud rate */ +#define U2BRGCLR PIC32_R (0x6844) +#define U2BRGSET PIC32_R (0x6848) +#define U2BRGINV PIC32_R (0x684C) + +#define U5MODE PIC32_R (0x6A00) /* Mode */ +#define U5MODECLR PIC32_R (0x6A04) +#define U5MODESET PIC32_R (0x6A08) +#define U5MODEINV PIC32_R (0x6A0C) +#define U5STA PIC32_R (0x6A10) /* Status and control */ +#define U5STACLR PIC32_R (0x6A14) +#define U5STASET PIC32_R (0x6A18) +#define U5STAINV PIC32_R (0x6A1C) +#define U5TXREG PIC32_R (0x6A20) /* Transmit */ +#define U5RXREG PIC32_R (0x6A30) /* Receive */ +#define U5BRG PIC32_R (0x6A40) /* Baud rate */ +#define U5BRGCLR PIC32_R (0x6A44) +#define U5BRGSET PIC32_R (0x6A48) +#define U5BRGINV PIC32_R (0x6A4C) +#endif + +/* + * UART Mode register. + */ +#define PIC32_UMODE_STSEL 0x0001 /* 2 Stop bits */ +#define PIC32_UMODE_PDSEL 0x0006 /* Bitmask: */ +#define PIC32_UMODE_PDSEL_8NPAR 0x0000 /* 8-bit data, no parity */ +#define PIC32_UMODE_PDSEL_8EVEN 0x0002 /* 8-bit data, even parity */ +#define PIC32_UMODE_PDSEL_8ODD 0x0004 /* 8-bit data, odd parity */ +#define PIC32_UMODE_PDSEL_9NPAR 0x0006 /* 9-bit data, no parity */ +#define PIC32_UMODE_BRGH 0x0008 /* High Baud Rate Enable */ +#define PIC32_UMODE_RXINV 0x0010 /* Receive Polarity Inversion */ +#define PIC32_UMODE_ABAUD 0x0020 /* Auto-Baud Enable */ +#define PIC32_UMODE_LPBACK 0x0040 /* UARTx Loopback Mode */ +#define PIC32_UMODE_WAKE 0x0080 /* Wake-up on start bit during Sleep Mode */ +#define PIC32_UMODE_UEN 0x0300 /* Bitmask: */ +#define PIC32_UMODE_UEN_RTS 0x0100 /* Using UxRTS pin */ +#define PIC32_UMODE_UEN_RTSCTS 0x0200 /* Using UxCTS and UxRTS pins */ +#define PIC32_UMODE_UEN_BCLK 0x0300 /* Using UxBCLK pin */ +#define PIC32_UMODE_RTSMD 0x0800 /* UxRTS Pin Simplex mode */ +#define PIC32_UMODE_IREN 0x1000 /* IrDA Encoder and Decoder Enable bit */ +#define PIC32_UMODE_SIDL 0x2000 /* Stop in Idle Mode */ +#define PIC32_UMODE_FRZ 0x4000 /* Freeze in Debug Exception Mode */ +#define PIC32_UMODE_ON 0x8000 /* UART Enable */ + +/* + * UART Control and status register. + */ +#define PIC32_USTA_URXDA 0x00000001 /* Receive Data Available (read-only) */ +#define PIC32_USTA_OERR 0x00000002 /* Receive Buffer Overrun */ +#define PIC32_USTA_FERR 0x00000004 /* Framing error detected (read-only) */ +#define PIC32_USTA_PERR 0x00000008 /* Parity error detected (read-only) */ +#define PIC32_USTA_RIDLE 0x00000010 /* Receiver is idle (read-only) */ +#define PIC32_USTA_ADDEN 0x00000020 /* Address Detect mode */ +#define PIC32_USTA_URXISEL 0x000000C0 /* Bitmask: receive interrupt is set when... */ +#define PIC32_USTA_URXISEL_NEMP 0x00000000 /* ...receive buffer is not empty */ +#define PIC32_USTA_URXISEL_HALF 0x00000040 /* ...receive buffer becomes 1/2 full */ +#define PIC32_USTA_URXISEL_3_4 0x00000080 /* ...receive buffer becomes 3/4 full */ +#define PIC32_USTA_TRMT 0x00000100 /* Transmit shift register is empty (read-only) */ +#define PIC32_USTA_UTXBF 0x00000200 /* Transmit buffer is full (read-only) */ +#define PIC32_USTA_UTXEN 0x00000400 /* Transmit Enable */ +#define PIC32_USTA_UTXBRK 0x00000800 /* Transmit Break */ +#define PIC32_USTA_URXEN 0x00001000 /* Receiver Enable */ +#define PIC32_USTA_UTXINV 0x00002000 /* Transmit Polarity Inversion */ +#define PIC32_USTA_UTXISEL 0x0000C000 /* Bitmask: TX interrupt is generated when... */ +#define PIC32_USTA_UTXISEL_1 0x00000000 /* ...the transmit buffer contains at least one empty space */ +#define PIC32_USTA_UTXISEL_ALL 0x00004000 /* ...all characters have been transmitted */ +#define PIC32_USTA_UTXISEL_EMP 0x00008000 /* ...the transmit buffer becomes empty */ +#define PIC32_USTA_ADDR 0x00FF0000 /* Automatic Address Mask */ +#define PIC32_USTA_ADM_EN 0x01000000 /* Automatic Address Detect */ + +/* + * Compute the 16-bit baud rate divisor, given + * the bus frequency and baud rate. + * Round to the nearest integer. + */ +#define PIC32_BRG_BAUD(fr,bd) ((((fr)/8 + (bd)) / (bd) / 2) - 1) + +/*-------------------------------------- + * Port A-G registers. + */ +#define TRISA PIC32_R (0x86000) /* Port A: mask of inputs */ +#define TRISACLR PIC32_R (0x86004) +#define TRISASET PIC32_R (0x86008) +#define TRISAINV PIC32_R (0x8600C) +#define PORTA PIC32_R (0x86010) /* Port A: read inputs, write outputs */ +#define PORTACLR PIC32_R (0x86014) +#define PORTASET PIC32_R (0x86018) +#define PORTAINV PIC32_R (0x8601C) +#define LATA PIC32_R (0x86020) /* Port A: read/write outputs */ +#define LATACLR PIC32_R (0x86024) +#define LATASET PIC32_R (0x86028) +#define LATAINV PIC32_R (0x8602C) +#define ODCA PIC32_R (0x86030) /* Port A: open drain configuration */ +#define ODCACLR PIC32_R (0x86034) +#define ODCASET PIC32_R (0x86038) +#define ODCAINV PIC32_R (0x8603C) + +#define TRISB PIC32_R (0x86040) /* Port B: mask of inputs */ +#define TRISBCLR PIC32_R (0x86044) +#define TRISBSET PIC32_R (0x86048) +#define TRISBINV PIC32_R (0x8604C) +#define PORTB PIC32_R (0x86050) /* Port B: read inputs, write outputs */ +#define PORTBCLR PIC32_R (0x86054) +#define PORTBSET PIC32_R (0x86058) +#define PORTBINV PIC32_R (0x8605C) +#define LATB PIC32_R (0x86060) /* Port B: read/write outputs */ +#define LATBCLR PIC32_R (0x86064) +#define LATBSET PIC32_R (0x86068) +#define LATBINV PIC32_R (0x8606C) +#define ODCB PIC32_R (0x86070) /* Port B: open drain configuration */ +#define ODCBCLR PIC32_R (0x86074) +#define ODCBSET PIC32_R (0x86078) +#define ODCBINV PIC32_R (0x8607C) + +#define TRISC PIC32_R (0x86080) /* Port C: mask of inputs */ +#define TRISCCLR PIC32_R (0x86084) +#define TRISCSET PIC32_R (0x86088) +#define TRISCINV PIC32_R (0x8608C) +#define PORTC PIC32_R (0x86090) /* Port C: read inputs, write outputs */ +#define PORTCCLR PIC32_R (0x86094) +#define PORTCSET PIC32_R (0x86098) +#define PORTCINV PIC32_R (0x8609C) +#define LATC PIC32_R (0x860A0) /* Port C: read/write outputs */ +#define LATCCLR PIC32_R (0x860A4) +#define LATCSET PIC32_R (0x860A8) +#define LATCINV PIC32_R (0x860AC) +#define ODCC PIC32_R (0x860B0) /* Port C: open drain configuration */ +#define ODCCCLR PIC32_R (0x860B4) +#define ODCCSET PIC32_R (0x860B8) +#define ODCCINV PIC32_R (0x860BC) + +#define TRISD PIC32_R (0x860C0) /* Port D: mask of inputs */ +#define TRISDCLR PIC32_R (0x860C4) +#define TRISDSET PIC32_R (0x860C8) +#define TRISDINV PIC32_R (0x860CC) +#define PORTD PIC32_R (0x860D0) /* Port D: read inputs, write outputs */ +#define PORTDCLR PIC32_R (0x860D4) +#define PORTDSET PIC32_R (0x860D8) +#define PORTDINV PIC32_R (0x860DC) +#define LATD PIC32_R (0x860E0) /* Port D: read/write outputs */ +#define LATDCLR PIC32_R (0x860E4) +#define LATDSET PIC32_R (0x860E8) +#define LATDINV PIC32_R (0x860EC) +#define ODCD PIC32_R (0x860F0) /* Port D: open drain configuration */ +#define ODCDCLR PIC32_R (0x860F4) +#define ODCDSET PIC32_R (0x860F8) +#define ODCDINV PIC32_R (0x860FC) + +#define TRISE PIC32_R (0x86100) /* Port E: mask of inputs */ +#define TRISECLR PIC32_R (0x86104) +#define TRISESET PIC32_R (0x86108) +#define TRISEINV PIC32_R (0x8610C) +#define PORTE PIC32_R (0x86110) /* Port E: read inputs, write outputs */ +#define PORTECLR PIC32_R (0x86114) +#define PORTESET PIC32_R (0x86118) +#define PORTEINV PIC32_R (0x8611C) +#define LATE PIC32_R (0x86120) /* Port E: read/write outputs */ +#define LATECLR PIC32_R (0x86124) +#define LATESET PIC32_R (0x86128) +#define LATEINV PIC32_R (0x8612C) +#define ODCE PIC32_R (0x86130) /* Port E: open drain configuration */ +#define ODCECLR PIC32_R (0x86134) +#define ODCESET PIC32_R (0x86138) +#define ODCEINV PIC32_R (0x8613C) + +#define TRISF PIC32_R (0x86140) /* Port F: mask of inputs */ +#define TRISFCLR PIC32_R (0x86144) +#define TRISFSET PIC32_R (0x86148) +#define TRISFINV PIC32_R (0x8614C) +#define PORTF PIC32_R (0x86150) /* Port F: read inputs, write outputs */ +#define PORTFCLR PIC32_R (0x86154) +#define PORTFSET PIC32_R (0x86158) +#define PORTFINV PIC32_R (0x8615C) +#define LATF PIC32_R (0x86160) /* Port F: read/write outputs */ +#define LATFCLR PIC32_R (0x86164) +#define LATFSET PIC32_R (0x86168) +#define LATFINV PIC32_R (0x8616C) +#define ODCF PIC32_R (0x86170) /* Port F: open drain configuration */ +#define ODCFCLR PIC32_R (0x86174) +#define ODCFSET PIC32_R (0x86178) +#define ODCFINV PIC32_R (0x8617C) + +#define TRISG PIC32_R (0x86180) /* Port G: mask of inputs */ +#define TRISGCLR PIC32_R (0x86184) +#define TRISGSET PIC32_R (0x86188) +#define TRISGINV PIC32_R (0x8618C) +#define PORTG PIC32_R (0x86190) /* Port G: read inputs, write outputs */ +#define PORTGCLR PIC32_R (0x86194) +#define PORTGSET PIC32_R (0x86198) +#define PORTGINV PIC32_R (0x8619C) +#define LATG PIC32_R (0x861A0) /* Port G: read/write outputs */ +#define LATGCLR PIC32_R (0x861A4) +#define LATGSET PIC32_R (0x861A8) +#define LATGINV PIC32_R (0x861AC) +#define ODCG PIC32_R (0x861B0) /* Port G: open drain configuration */ +#define ODCGCLR PIC32_R (0x861B4) +#define ODCGSET PIC32_R (0x861B8) +#define ODCGINV PIC32_R (0x861BC) + +#define CNCON PIC32_R (0x861C0) /* Interrupt-on-change control */ +#define CNCONCLR PIC32_R (0x861C4) +#define CNCONSET PIC32_R (0x861C8) +#define CNCONINV PIC32_R (0x861CC) +#define CNEN PIC32_R (0x861D0) /* Input change interrupt enable */ +#define CNENCLR PIC32_R (0x861D4) +#define CNENSET PIC32_R (0x861D8) +#define CNENINV PIC32_R (0x861DC) +#define CNPUE PIC32_R (0x861E0) /* Input pin pull-up enable */ +#define CNPUECLR PIC32_R (0x861E4) +#define CNPUESET PIC32_R (0x861E8) +#define CNPUEINV PIC32_R (0x861EC) + +/*-------------------------------------- + * A/D Converter registers. + */ +#define AD1CON1 PIC32_R (0x9000) /* Control register 1 */ +#define AD1CON1CLR PIC32_R (0x9004) +#define AD1CON1SET PIC32_R (0x9008) +#define AD1CON1INV PIC32_R (0x900C) +#define AD1CON2 PIC32_R (0x9010) /* Control register 2 */ +#define AD1CON2CLR PIC32_R (0x9014) +#define AD1CON2SET PIC32_R (0x9018) +#define AD1CON2INV PIC32_R (0x901C) +#define AD1CON3 PIC32_R (0x9020) /* Control register 3 */ +#define AD1CON3CLR PIC32_R (0x9024) +#define AD1CON3SET PIC32_R (0x9028) +#define AD1CON3INV PIC32_R (0x902C) +#define AD1CHS PIC32_R (0x9040) /* Channel select */ +#define AD1CHSCLR PIC32_R (0x9044) +#define AD1CHSSET PIC32_R (0x9048) +#define AD1CHSINV PIC32_R (0x904C) +#define AD1CSSL PIC32_R (0x9050) /* Input scan selection */ +#define AD1CSSLCLR PIC32_R (0x9054) +#define AD1CSSLSET PIC32_R (0x9058) +#define AD1CSSLINV PIC32_R (0x905C) +#define AD1PCFG PIC32_R (0x9060) /* Port configuration */ +#define AD1PCFGCLR PIC32_R (0x9064) +#define AD1PCFGSET PIC32_R (0x9068) +#define AD1PCFGINV PIC32_R (0x906C) +#define ADC1BUF0 PIC32_R (0x9070) /* Result words */ +#define ADC1BUF1 PIC32_R (0x9080) +#define ADC1BUF2 PIC32_R (0x9090) +#define ADC1BUF3 PIC32_R (0x90A0) +#define ADC1BUF4 PIC32_R (0x90B0) +#define ADC1BUF5 PIC32_R (0x90C0) +#define ADC1BUF6 PIC32_R (0x90D0) +#define ADC1BUF7 PIC32_R (0x90E0) +#define ADC1BUF8 PIC32_R (0x90F0) +#define ADC1BUF9 PIC32_R (0x9100) +#define ADC1BUFA PIC32_R (0x9110) +#define ADC1BUFB PIC32_R (0x9120) +#define ADC1BUFC PIC32_R (0x9130) +#define ADC1BUFD PIC32_R (0x9140) +#define ADC1BUFE PIC32_R (0x9150) +#define ADC1BUFF PIC32_R (0x9160) + +/*-------------------------------------- + * Parallel master port registers. + */ +#define PMCON PIC32_R (0x7000) /* Control */ +#define PMCONCLR PIC32_R (0x7004) +#define PMCONSET PIC32_R (0x7008) +#define PMCONINV PIC32_R (0x700C) +#define PMMODE PIC32_R (0x7010) /* Mode */ +#define PMMODECLR PIC32_R (0x7014) +#define PMMODESET PIC32_R (0x7018) +#define PMMODEINV PIC32_R (0x701C) +#define PMADDR PIC32_R (0x7020) /* Address */ +#define PMADDRCLR PIC32_R (0x7024) +#define PMADDRSET PIC32_R (0x7028) +#define PMADDRINV PIC32_R (0x702C) +#define PMDOUT PIC32_R (0x7030) /* Data output */ +#define PMDOUTCLR PIC32_R (0x7034) +#define PMDOUTSET PIC32_R (0x7038) +#define PMDOUTINV PIC32_R (0x703C) +#define PMDIN PIC32_R (0x7040) /* Data input */ +#define PMDINCLR PIC32_R (0x7044) +#define PMDINSET PIC32_R (0x7048) +#define PMDININV PIC32_R (0x704C) +#define PMAEN PIC32_R (0x7050) /* Pin enable */ +#define PMAENCLR PIC32_R (0x7054) +#define PMAENSET PIC32_R (0x7058) +#define PMAENINV PIC32_R (0x705C) +#define PMSTAT PIC32_R (0x7060) /* Status (slave only) */ +#define PMSTATCLR PIC32_R (0x7064) +#define PMSTATSET PIC32_R (0x7068) +#define PMSTATINV PIC32_R (0x706C) + +/* + * PMP Control register. + */ +#define PIC32_PMCON_RDSP 0x0001 /* Read strobe polarity active-high */ +#define PIC32_PMCON_WRSP 0x0002 /* Write strobe polarity active-high */ +#define PIC32_PMCON_CS1P 0x0008 /* Chip select 0 polarity active-high */ +#define PIC32_PMCON_CS2P 0x0010 /* Chip select 1 polarity active-high */ +#define PIC32_PMCON_ALP 0x0020 /* Address latch polarity active-high */ +#define PIC32_PMCON_CSF 0x00C0 /* Chip select function bitmask: */ +#define PIC32_PMCON_CSF_NONE 0x0000 /* PMCS2 and PMCS1 as A[15:14] */ +#define PIC32_PMCON_CSF_CS2 0x0040 /* PMCS2 as chip select */ +#define PIC32_PMCON_CSF_CS21 0x0080 /* PMCS2 and PMCS1 as chip select */ +#define PIC32_PMCON_PTRDEN 0x0100 /* Read/write strobe port enable */ +#define PIC32_PMCON_PTWREN 0x0200 /* Write enable strobe port enable */ +#define PIC32_PMCON_PMPTTL 0x0400 /* TTL input buffer select */ +#define PIC32_PMCON_ADRMUX 0x1800 /* Address/data mux selection bitmask: */ +#define PIC32_PMCON_ADRMUX_NONE 0x0000 /* Address and data separate */ +#define PIC32_PMCON_ADRMUX_AD 0x0800 /* Lower address on PMD[7:0], high on PMA[15:8] */ +#define PIC32_PMCON_ADRMUX_D8 0x1000 /* All address on PMD[7:0] */ +#define PIC32_PMCON_ADRMUX_D16 0x1800 /* All address on PMD[15:0] */ +#define PIC32_PMCON_SIDL 0x2000 /* Stop in idle */ +#define PIC32_PMCON_FRZ 0x4000 /* Freeze in debug exception */ +#define PIC32_PMCON_ON 0x8000 /* Parallel master port enable */ + +/* + * PMP Mode register. + */ +#define PIC32_PMMODE_WAITE(x) ((x)<<0) /* Wait states: data hold after RW strobe */ +#define PIC32_PMMODE_WAITM(x) ((x)<<2) /* Wait states: data RW strobe */ +#define PIC32_PMMODE_WAITB(x) ((x)<<6) /* Wait states: data setup to RW strobe */ +#define PIC32_PMMODE_MODE 0x0300 /* Mode select bitmask: */ +#define PIC32_PMMODE_MODE_SLAVE 0x0000 /* Legacy slave */ +#define PIC32_PMMODE_MODE_SLENH 0x0100 /* Enhanced slave */ +#define PIC32_PMMODE_MODE_MAST2 0x0200 /* Master mode 2 */ +#define PIC32_PMMODE_MODE_MAST1 0x0300 /* Master mode 1 */ +#define PIC32_PMMODE_MODE16 0x0400 /* 16-bit mode */ +#define PIC32_PMMODE_INCM 0x1800 /* Address increment mode bitmask: */ +#define PIC32_PMMODE_INCM_NONE 0x0000 /* No increment/decrement */ +#define PIC32_PMMODE_INCM_INC 0x0800 /* Increment address */ +#define PIC32_PMMODE_INCM_DEC 0x1000 /* Decrement address */ +#define PIC32_PMMODE_INCM_SLAVE 0x1800 /* Slave auto-increment */ +#define PIC32_PMMODE_IRQM 0x6000 /* Interrupt request bitmask: */ +#define PIC32_PMMODE_IRQM_DIS 0x0000 /* No interrupt generated */ +#define PIC32_PMMODE_IRQM_END 0x2000 /* Interrupt at end of read/write cycle */ +#define PIC32_PMMODE_IRQM_A3 0x4000 /* Interrupt on address 3 */ +#define PIC32_PMMODE_BUSY 0x8000 /* Port is busy */ + +/* + * PMP Address register. + */ +#define PIC32_PMADDR_PADDR 0x3FFF /* Destination address */ +#define PIC32_PMADDR_CS1 0x4000 /* Chip select 1 is active */ +#define PIC32_PMADDR_CS2 0x8000 /* Chip select 2 is active */ + +/* + * PMP status register (slave only). + */ +#define PIC32_PMSTAT_OB0E 0x0001 /* Output buffer 0 empty */ +#define PIC32_PMSTAT_OB1E 0x0002 /* Output buffer 1 empty */ +#define PIC32_PMSTAT_OB2E 0x0004 /* Output buffer 2 empty */ +#define PIC32_PMSTAT_OB3E 0x0008 /* Output buffer 3 empty */ +#define PIC32_PMSTAT_OBUF 0x0040 /* Output buffer underflow */ +#define PIC32_PMSTAT_OBE 0x0080 /* Output buffer empty */ +#define PIC32_PMSTAT_IB0F 0x0100 /* Input buffer 0 full */ +#define PIC32_PMSTAT_IB1F 0x0200 /* Input buffer 1 full */ +#define PIC32_PMSTAT_IB2F 0x0400 /* Input buffer 2 full */ +#define PIC32_PMSTAT_IB3F 0x0800 /* Input buffer 3 full */ +#define PIC32_PMSTAT_IBOV 0x4000 /* Input buffer overflow */ +#define PIC32_PMSTAT_IBF 0x8000 /* Input buffer full */ + +/*-------------------------------------- + * USB registers. + */ +#define U1OTGIR PIC32_R (0x85040) /* OTG interrupt flags */ +#define U1OTGIE PIC32_R (0x85050) /* OTG interrupt enable */ +#define U1OTGSTAT PIC32_R (0x85060) /* Comparator and pin status */ +#define U1OTGCON PIC32_R (0x85070) /* Resistor and pin control */ +#define U1PWRC PIC32_R (0x85080) /* Power control */ +#define U1IR PIC32_R (0x85200) /* Pending interrupt */ +#define U1IE PIC32_R (0x85210) /* Interrupt enable */ +#define U1EIR PIC32_R (0x85220) /* Pending error interrupt */ +#define U1EIE PIC32_R (0x85230) /* Error interrupt enable */ +#define U1STAT PIC32_R (0x85240) /* Status FIFO */ +#define U1CON PIC32_R (0x85250) /* Control */ +#define U1ADDR PIC32_R (0x85260) /* Address */ +#define U1BDTP1 PIC32_R (0x85270) /* Buffer descriptor table pointer 1 */ +#define U1FRML PIC32_R (0x85280) /* Frame counter low */ +#define U1FRMH PIC32_R (0x85290) /* Frame counter high */ +#define U1TOK PIC32_R (0x852A0) /* Host control */ +#define U1SOF PIC32_R (0x852B0) /* SOF counter */ +#define U1BDTP2 PIC32_R (0x852C0) /* Buffer descriptor table pointer 2 */ +#define U1BDTP3 PIC32_R (0x852D0) /* Buffer descriptor table pointer 3 */ +#define U1CNFG1 PIC32_R (0x852E0) /* Debug and idle */ +#define U1EP(n) PIC32_R (0x85300 + (n << 4)) /* Endpoint control */ + +/* + * USB Control register. + */ +#define PIC32_U1CON_USBEN 0x0001 /* USB module enable (device mode) */ +#define PIC32_U1CON_SOFEN 0x0001 /* SOF sent every 1 ms (host mode) */ +#define PIC32_U1CON_PPBRST 0x0002 /* Ping-pong buffers reset */ +#define PIC32_U1CON_RESUME 0x0004 /* Resume signaling enable */ +#define PIC32_U1CON_HOSTEN 0x0008 /* Host mode enable */ +#define PIC32_U1CON_USBRST 0x0010 /* USB reset */ +#define PIC32_U1CON_PKTDIS 0x0020 /* Packet transfer disable */ +#define PIC32_U1CON_TOKBUSY 0x0020 /* Token busy indicator */ +#define PIC32_U1CON_SE0 0x0040 /* Single ended zero detected */ +#define PIC32_U1CON_JSTATE 0x0080 /* Live differential receiver JSTATE flag */ + +/* + * USB Power control register. + */ +#define PIC32_U1PWRC_USBPWR 0x0001 /* USB operation enable */ +#define PIC32_U1PWRC_USUSPEND 0x0002 /* USB suspend mode */ +#define PIC32_U1PWRC_USLPGRD 0x0010 /* USB sleep entry guard */ +#define PIC32_U1PWRC_UACTPND 0x0080 /* UAB activity pending */ + +/* + * USB Pending interrupt register. + * USB Interrupt enable register. + */ +#define PIC32_U1I_DETACH 0x0001 /* Detach (host mode) */ +#define PIC32_U1I_URST 0x0001 /* USB reset (device mode) */ +#define PIC32_U1I_UERR 0x0002 /* USB error condition */ +#define PIC32_U1I_SOF 0x0004 /* SOF token */ +#define PIC32_U1I_TRN 0x0008 /* Token processing complete */ +#define PIC32_U1I_IDLE 0x0010 /* Idle detect */ +#define PIC32_U1I_RESUME 0x0020 /* Resume */ +#define PIC32_U1I_ATTACH 0x0040 /* Peripheral attach */ +#define PIC32_U1I_STALL 0x0080 /* STALL handshake */ + +/* + * USB OTG interrupt flags register. + * USB OTG interrupt enable register. + */ +#define PIC32_U1OTGI_VBUSVD 0x0001 /* A-device Vbus change */ +#define PIC32_U1OTGI_SESEND 0x0004 /* B-device Vbus change */ +#define PIC32_U1OTGI_SESVD 0x0008 /* Session valid change */ +#define PIC32_U1OTGI_ACTV 0x0010 /* Bus activity indicator */ +#define PIC32_U1OTGI_LSTATE 0x0020 /* Line state stable */ +#define PIC32_U1OTGI_T1MSEC 0x0040 /* 1 millisecond timer expired */ +#define PIC32_U1OTGI_ID 0x0080 /* ID state change */ + +#define PIC32_U1OTGSTAT_VBUSVD 0x0001 /* */ +#define PIC32_U1OTGSTAT_SESEND 0x0004 /* */ +#define PIC32_U1OTGSTAT_SESVD 0x0008 /* */ +#define PIC32_U1OTGSTAT_LSTATE 0x0020 /* */ +#define PIC32_U1OTGSTAT_ID 0x0080 /* */ + +#define PIC32_U1OTGCON_VBUSDIS 0x0001 /* */ +#define PIC32_U1OTGCON_VBUSCHG 0x0002 /* */ +#define PIC32_U1OTGCON_OTGEN 0x0004 /* */ +#define PIC32_U1OTGCON_VBUSON 0x0008 /* */ +#define PIC32_U1OTGCON_DMPULDWN 0x0010 /* */ +#define PIC32_U1OTGCON_DPPULDWN 0x0020 /* */ +#define PIC32_U1OTGCON_DMPULUP 0x0040 /* */ +#define PIC32_U1OTGCON_DPPULUP 0x0080 /* */ + +#define PIC32_U1EI_PID 0x0001 /* */ +#define PIC32_U1EI_CRC5 0x0002 /* */ +#define PIC32_U1EI_EOF 0x0002 /* */ +#define PIC32_U1EI_CRC16 0x0004 /* */ +#define PIC32_U1EI_DFN8 0x0008 /* */ +#define PIC32_U1EI_BTO 0x0010 /* */ +#define PIC32_U1EI_DMA 0x0020 /* */ +#define PIC32_U1EI_BMX 0x0040 /* */ +#define PIC32_U1EI_BTS 0x0080 /* */ + +#define PIC32_U1STAT_PPBI 0x0004 /* */ +#define PIC32_U1STAT_DIR 0x0008 /* */ +#define PIC32_U1STAT_ENDPT(x) (((x) >> 4) & 0xF) /* */ + +#define PIC32_U1ADDR_DEVADDR 0x007F /* */ +#define PIC32_U1ADDR_USBADDR0 0x0001 /* */ +#define PIC32_U1ADDR_DEVADDR1 0x0002 /* */ +#define PIC32_U1ADDR_DEVADDR2 0x0004 /* */ +#define PIC32_U1ADDR_DEVADDR3 0x0008 /* */ +#define PIC32_U1ADDR_DEVADDR4 0x0010 /* */ +#define PIC32_U1ADDR_DEVADDR5 0x0020 /* */ +#define PIC32_U1ADDR_DEVADDR6 0x0040 /* */ +#define PIC32_U1ADDR_LSPDEN 0x0080 /* */ + +#define PIC32_U1FRML_FRM0 0x0001 /* */ +#define PIC32_U1FRML_FRM1 0x0002 /* */ +#define PIC32_U1FRML_FRM2 0x0004 /* */ +#define PIC32_U1FRML_FRM3 0x0008 /* */ +#define PIC32_U1FRML_FRM4 0x0010 /* */ +#define PIC32_U1FRML_FRM5 0x0020 /* */ +#define PIC32_U1FRML_FRM6 0x0040 /* */ +#define PIC32_U1FRML_FRM7 0x0080 /* */ + +#define PIC32_U1FRMH_FRM8 0x0001 /* */ +#define PIC32_U1FRMH_FRM9 0x0002 /* */ +#define PIC32_U1FRMH_FRM10 0x0004 /* */ + +#define PIC32_U1TOK_EP0 0x0001 /* */ +#define PIC32_U1TOK_EP 0x000F /* */ +#define PIC32_U1TOK_EP1 0x0002 /* */ +#define PIC32_U1TOK_EP2 0x0004 /* */ +#define PIC32_U1TOK_EP3 0x0008 /* */ +#define PIC32_U1TOK_PID0 0x0010 /* */ +#define PIC32_U1TOK_PID 0x00F0 /* */ +#define PIC32_U1TOK_PID1 0x0020 /* */ +#define PIC32_U1TOK_PID2 0x0040 /* */ +#define PIC32_U1TOK_PID3 0x0080 /* */ + +#define PIC32_U1CNFG1_USBSIDL 0x0010 /* */ +#define PIC32_U1CNFG1_USBFRZ 0x0020 /* */ +#define PIC32_U1CNFG1_UOEMON 0x0040 /* */ +#define PIC32_U1CNFG1_UTEYE 0x0080 /* */ + +#define PIC32_U1EP_EPHSHK 0x0001 /* */ +#define PIC32_U1EP_EPSTALL 0x0002 /* */ +#define PIC32_U1EP_EPTXEN 0x0004 /* */ +#define PIC32_U1EP_EPRXEN 0x0008 /* */ +#define PIC32_U1EP_EPCONDIS 0x0010 /* */ +#define PIC32_U1EP_RETRYDIS 0x0040 /* */ +#define PIC32_U1EP_LSPD 0x0080 /* */ + +/* DB status field values */ +#define PIC32_DB_BSTALL (1 << 2) +#define PIC32_DB_DTS (1 << 3) +#define PIC32_DB_NINC (1 << 4) +#define PIC32_DB_KEEP (1 << 5) +#define PIC32_DB_DATA1 (1 << 6) +#define PIC32_DB_UOWN (1 << 7) +#define PIC32_DB_GET_PID(x) (((x) >> 2) & 0xF) +#define PIC32_DB_SET_PID(x) (((x) & 0xF) << 2) +#define PIC32_DB_GET_COUNT(x) (((x) >> 16) & 0x3FF) +#define PIC32_DB_SET_COUNT(x) (((x) & 0x3FF) << 16) + +/*-------------------------------------- + * SPI registers. + */ +#ifdef PIC32MX4 +#define SPI1CON PIC32_R (0x5800) /* Control */ +#define SPI1CONCLR PIC32_R (0x5804) +#define SPI1CONSET PIC32_R (0x5808) +#define SPI1CONINV PIC32_R (0x580C) +#define SPI1STAT PIC32_R (0x5810) /* Status */ +#define SPI1STATCLR PIC32_R (0x5814) +#define SPI1STATSET PIC32_R (0x5818) +#define SPI1STATINV PIC32_R (0x581C) +#define SPI1BUF PIC32_R (0x5820) /* Transmit and receive buffer */ +#define SPI1BRG PIC32_R (0x5830) /* Baud rate generator */ +#define SPI1BRGCLR PIC32_R (0x5834) +#define SPI1BRGSET PIC32_R (0x5838) +#define SPI1BRGINV PIC32_R (0x583C) +#endif +#ifdef PIC32MX7 +#define SPI3CON PIC32_R (0x5800) /* Control */ +#define SPI3CONCLR PIC32_R (0x5804) +#define SPI3CONSET PIC32_R (0x5808) +#define SPI3CONINV PIC32_R (0x580C) +#define SPI3STAT PIC32_R (0x5810) /* Status */ +#define SPI3STATCLR PIC32_R (0x5814) +#define SPI3STATSET PIC32_R (0x5818) +#define SPI3STATINV PIC32_R (0x581C) +#define SPI3BUF PIC32_R (0x5820) /* Transmit and receive buffer */ +#define SPI3BRG PIC32_R (0x5830) /* Baud rate generator */ +#define SPI3BRGCLR PIC32_R (0x5834) +#define SPI3BRGSET PIC32_R (0x5838) +#define SPI3BRGINV PIC32_R (0x583C) + +#define SPI4CON PIC32_R (0x5C00) /* Control */ +#define SPI4CONCLR PIC32_R (0x5C04) +#define SPI4CONSET PIC32_R (0x5C08) +#define SPI4CONINV PIC32_R (0x5C0C) +#define SPI4STAT PIC32_R (0x5C10) /* Status */ +#define SPI4STATCLR PIC32_R (0x5C14) +#define SPI4STATSET PIC32_R (0x5C18) +#define SPI4STATINV PIC32_R (0x5C1C) +#define SPI4BUF PIC32_R (0x5C20) /* Transmit and receive buffer */ +#define SPI4BRG PIC32_R (0x5C30) /* Baud rate generator */ +#define SPI4BRGCLR PIC32_R (0x5C34) +#define SPI4BRGSET PIC32_R (0x5C38) +#define SPI4BRGINV PIC32_R (0x5C3C) + +#define SPI1CON PIC32_R (0x5E00) /* Control */ +#define SPI1CONCLR PIC32_R (0x5E04) +#define SPI1CONSET PIC32_R (0x5E08) +#define SPI1CONINV PIC32_R (0x5E0C) +#define SPI1STAT PIC32_R (0x5E10) /* Status */ +#define SPI1STATCLR PIC32_R (0x5E14) +#define SPI1STATSET PIC32_R (0x5E18) +#define SPI1STATINV PIC32_R (0x5E1C) +#define SPI1BUF PIC32_R (0x5E20) /* Transmit and receive buffer */ +#define SPI1BRG PIC32_R (0x5E30) /* Baud rate generator */ +#define SPI1BRGCLR PIC32_R (0x5E34) +#define SPI1BRGSET PIC32_R (0x5E38) +#define SPI1BRGINV PIC32_R (0x5E3C) +#endif + +#define SPI2CON PIC32_R (0x5A00) /* Control */ +#define SPI2CONCLR PIC32_R (0x5A04) +#define SPI2CONSET PIC32_R (0x5A08) +#define SPI2CONINV PIC32_R (0x5A0C) +#define SPI2STAT PIC32_R (0x5A10) /* Status */ +#define SPI2STATCLR PIC32_R (0x5A14) +#define SPI2STATSET PIC32_R (0x5A18) +#define SPI2STATINV PIC32_R (0x5A1C) +#define SPI2BUF PIC32_R (0x5A20) /* Transmit and receive buffer */ +#define SPI2BRG PIC32_R (0x5A30) /* Baud rate generator */ +#define SPI2BRGCLR PIC32_R (0x5A34) +#define SPI2BRGSET PIC32_R (0x5A38) +#define SPI2BRGINV PIC32_R (0x5A3C) + +/* + * SPI Control register. + */ +#define PIC32_SPICON_MSTEN 0x00000020 /* Master mode */ +#define PIC32_SPICON_CKP 0x00000040 /* Idle clock is high level */ +#define PIC32_SPICON_SSEN 0x00000080 /* Slave mode: SSx pin enable */ +#define PIC32_SPICON_CKE 0x00000100 /* Output data changes on + * transition from active clock + * state to Idle clock state */ +#define PIC32_SPICON_SMP 0x00000200 /* Master mode: input data sampled + * at end of data output time. */ +#define PIC32_SPICON_MODE16 0x00000400 /* 16-bit data width */ +#define PIC32_SPICON_MODE32 0x00000800 /* 32-bit data width */ +#define PIC32_SPICON_DISSDO 0x00001000 /* SDOx pin is not used */ +#define PIC32_SPICON_SIDL 0x00002000 /* Stop in Idle mode */ +#define PIC32_SPICON_FRZ 0x00004000 /* Freeze in Debug mode */ +#define PIC32_SPICON_ON 0x00008000 /* SPI Peripheral is enabled */ +#define PIC32_SPICON_ENHBUF 0x00010000 /* Enhanced buffer enable */ +#define PIC32_SPICON_SPIFE 0x00020000 /* Frame synchronization pulse + * coincides with the first bit clock */ +#define PIC32_SPICON_FRMPOL 0x20000000 /* Frame pulse is active-high */ +#define PIC32_SPICON_FRMSYNC 0x40000000 /* Frame sync pulse input (Slave mode) */ +#define PIC32_SPICON_FRMEN 0x80000000 /* Framed SPI support */ + +/* + * SPI Status register. + */ +#define PIC32_SPISTAT_SPIRBF 0x00000001 /* Receive buffer is full */ +#define PIC32_SPISTAT_SPITBF 0x00000002 /* Transmit buffer is full */ +#define PIC32_SPISTAT_SPITBE 0x00000008 /* Transmit buffer is empty */ +#define PIC32_SPISTAT_SPIRBE 0x00000020 /* Receive buffer is empty */ +#define PIC32_SPISTAT_SPIROV 0x00000040 /* Receive overflow flag */ +#define PIC32_SPISTAT_SPIBUSY 0x00000800 /* SPI is busy */ + +/*-------------------------------------- + * DMA controller registers. + */ +#define DMACON PIC32_R (0x83000) /* DMA Control */ +#define DMACONCLR PIC32_R (0x83004) +#define DMACONSET PIC32_R (0x83008) +#define DMACONINV PIC32_R (0x8300C) +#define DMASTAT PIC32_R (0x83010) /* DMA Status */ +#define DMAADDR PIC32_R (0x83020) /* DMA Address */ +// TODO: other DMA registers. + +/*-------------------------------------- + * System controller registers. + */ +#define OSCCON PIC32_R (0xf000) +#define OSCTUN PIC32_R (0xf010) +#define DDPCON PIC32_R (0xf200) /* Debug Data Port Control */ +#define DEVID PIC32_R (0xf220) +#define SYSKEY PIC32_R (0xf230) +#define RCON PIC32_R (0xf600) +#define RCONCLR PIC32_R (0xf604) +#define RCONSET PIC32_R (0xf608) +#define RCONINV PIC32_R (0xf60C) +#define RSWRST PIC32_R (0xf610) +#define RSWRSTCLR PIC32_R (0xf614) +#define RSWRSTSET PIC32_R (0xf618) +#define RSWRSTINV PIC32_R (0xf61C) + +/* + * Reset control register. + */ +#define PIC32_RCON_POR 0x00000001 +#define PIC32_RCON_BOR 0x00000002 +#define PIC32_RCON_IDLE 0x00000004 +#define PIC32_RCON_SLEEP 0x00000008 +#define PIC32_RCON_WDTO 0x00000010 +#define PIC32_RCON_SWR 0x00000040 +#define PIC32_RCON_EXTR 0x00000080 +#define PIC32_RCON_VREGS 0x00000100 +#define PIC32_RCON_CMR 0x00000200 + +/*-------------------------------------- + * Prefetch cache controller registers. + */ +#define CHECON PIC32_R (0x84000) /* Prefetch cache control */ +#define CHECONCLR PIC32_R (0x84004) +#define CHECONSET PIC32_R (0x84008) +#define CHECONINV PIC32_R (0x8400C) +// TODO: other prefetch registers + +/*-------------------------------------- + * Bus matrix control registers. + */ +#define BMXCON PIC32_R (0x82000) /* Memory configuration */ +#define BMXCONCLR PIC32_R (0x82004) +#define BMXCONSET PIC32_R (0x82008) +#define BMXCONINV PIC32_R (0x8200C) +#define BMXDKPBA PIC32_R (0x82010) /* Data RAM kernel program base address */ +#define BMXDUDBA PIC32_R (0x82020) /* Data RAM user data base address */ +#define BMXDUPBA PIC32_R (0x82030) /* Data RAM user program base address */ +#define BMXDRMSZ PIC32_R (0x82040) /* Data RAM size */ +#define BMXPUPBA PIC32_R (0x82050) /* Program Flash user program base address */ +#define BMXPFMSZ PIC32_R (0x82060) /* Program Flash size */ +#define BMXBOOTSZ PIC32_R (0x82070) /* Boot Flash size */ + +/*-------------------------------------- + * Non-volatile memory control registers. + */ +#define NVMCON PIC32_R (0x0F400) +#define NVMCONCLR PIC32_R (0x0F404) +#define NVMCONSET PIC32_R (0x0F408) +#define NVMCONINV PIC32_R (0x0F40C) +#define NVMKEY PIC32_R (0x0F410) +#define NVMADDR PIC32_R (0x0F420) +#define NVMADDRCLR PIC32_R (0x0F424) +#define NVMADDRSET PIC32_R (0x0F428) +#define NVMADDRINV PIC32_R (0x0F42C) +#define NVMDATA PIC32_R (0x0F430) +#define NVMSRCADDR PIC32_R (0x0F440) + +#define PIC32_NVMCON_NVMOP 0x0000000F +#define PIC32_NVMCON_NOP 0 /* No operation */ +#define PIC32_NVMCON_WORD_PGM 1 /* Word program */ +#define PIC32_NVMCON_ROW_PGM 3 /* Row program */ +#define PIC32_NVMCON_PAGE_ERASE 4 /* Page erase */ + +#define PIC32_NVMCON_LVDSTAT 0x00000800 +#define PIC32_NVMCON_LVDERR 0x00001000 +#define PIC32_NVMCON_WRERR 0x00002000 +#define PIC32_NVMCON_WREN 0x00004000 +#define PIC32_NVMCON_WR 0x00008000 + +/* + * Timer2 registers + */ +#define T2CON PIC32_R (0x0800) +#define T2CONSET PIC32_R (0x0808) +#define TMR2 PIC32_R (0x0810) +#define PR2 PIC32_R (0x0820) + +/* + * Output compare registers + */ +#define OC1CON PIC32_R (0x3000) +#define OC1R PIC32_R (0x3010) +#define OC1RS PIC32_R (0x3020) +#define OC4CON PIC32_R (0x3600) +#define OC4R PIC32_R (0x3610) +#define OC4RS PIC32_R (0x3620) + +/* + * Watchdog registers + */ +#define WDTCON PIC32_R (0x0000) /* Watchdog timer control */ +#define WDTCONCLR PIC32_R (0x0004) +#define WDTCONSET PIC32_R (0x0008) + +/*-------------------------------------- + * Configuration registers. + */ +#define DEVCFG0 0x9fc02ffc +#define DEVCFG1 0x9fc02ff8 +#define DEVCFG2 0x9fc02ff4 +#define DEVCFG3 0x9fc02ff0 + +#define PIC32_DEVCFG(cfg0, cfg1, cfg2, cfg3) \ + asm (".section .config"); \ + unsigned __DEVCFG0 __attribute__ ((section(".config0"))) = (cfg0) ^ 0x7fffffff; \ + unsigned __DEVCFG1 __attribute__ ((section(".config1"))) = (cfg1) | DEVCFG1_UNUSED; \ + unsigned __DEVCFG2 __attribute__ ((section(".config2"))) = (cfg2) | DEVCFG2_UNUSED; \ + unsigned __DEVCFG3 __attribute__ ((section(".config3"))) = (cfg3) | DEVCFG3_UNUSED + +/* + * Config0 register at 1fc02ffc, inverted. + */ +#define DEVCFG0_DEBUG_MASK 0x00000003 /* Debugger enable bits */ +#define DEVCFG0_DEBUG_DISABLED 0x00000000 /* Debugger disabled */ +#define DEVCFG0_DEBUG_ENABLED 0x00000002 /* Debugger enabled */ +#define DEVCFG0_ICESEL 0x00000008 /* Use PGC1/PGD1 (default PGC2/PGD2) */ +#define DEVCFG0_PWP_MASK 0x000ff000 /* Program flash write protect */ +#define DEVCFG0_BWP 0x01000000 /* Boot flash write protect */ +#define DEVCFG0_CP 0x10000000 /* Code protect */ + +/* + * Config1 register at 1fc02ff8. + */ +#define DEVCFG1_UNUSED 0xff600858 +#define DEVCFG1_FNOSC_MASK 0x00000007 /* Oscillator selection */ +#define DEVCFG1_FNOSC_FRC 0x00000000 /* Fast RC */ +#define DEVCFG1_FNOSC_FRCDIVPLL 0x00000001 /* Fast RC with divide-by-N and PLL */ +#define DEVCFG1_FNOSC_PRI 0x00000002 /* Primary oscillator XT, HS, EC */ +#define DEVCFG1_FNOSC_PRIPLL 0x00000003 /* Primary with PLL */ +#define DEVCFG1_FNOSC_SEC 0x00000004 /* Secondary oscillator */ +#define DEVCFG1_FNOSC_LPRC 0x00000005 /* Low-power RC */ +#define DEVCFG1_FNOSC_FRCDIV 0x00000007 /* Fast RC with divide-by-N */ +#define DEVCFG1_FSOSCEN 0x00000020 /* Secondary oscillator enable */ +#define DEVCFG1_IESO 0x00000080 /* Internal-external switch over */ +#define DEVCFG1_POSCMOD_MASK 0x00000300 /* Primary oscillator config */ +#define DEVCFG1_POSCMOD_EXT 0x00000000 /* External mode */ +#define DEVCFG1_POSCMOD_XT 0x00000100 /* XT oscillator */ +#define DEVCFG1_POSCMOD_HS 0x00000200 /* HS oscillator */ +#define DEVCFG1_POSCMOD_DISABLE 0x00000300 /* Disabled */ +#define DEVCFG1_OSCIOFNC 0x00000400 /* CLKO output active */ +#define DEVCFG1_FPBDIV_MASK 0x00003000 /* Peripheral bus clock divisor */ +#define DEVCFG1_FPBDIV_1 0x00000000 /* SYSCLK / 1 */ +#define DEVCFG1_FPBDIV_2 0x00001000 /* SYSCLK / 2 */ +#define DEVCFG1_FPBDIV_4 0x00002000 /* SYSCLK / 4 */ +#define DEVCFG1_FPBDIV_8 0x00003000 /* SYSCLK / 8 */ +#define DEVCFG1_FCKM_DISABLE 0x00004000 /* Fail-safe clock monitor disable */ +#define DEVCFG1_FCKS_DISABLE 0x00008000 /* Clock switching disable */ +#define DEVCFG1_WDTPS_MASK 0x001f0000 /* Watchdog postscale */ +#define DEVCFG1_WDTPS_1 0x00000000 /* 1:1 */ +#define DEVCFG1_WDTPS_2 0x00010000 /* 1:2 */ +#define DEVCFG1_WDTPS_4 0x00020000 /* 1:4 */ +#define DEVCFG1_WDTPS_8 0x00030000 /* 1:8 */ +#define DEVCFG1_WDTPS_16 0x00040000 /* 1:16 */ +#define DEVCFG1_WDTPS_32 0x00050000 /* 1:32 */ +#define DEVCFG1_WDTPS_64 0x00060000 /* 1:64 */ +#define DEVCFG1_WDTPS_128 0x00070000 /* 1:128 */ +#define DEVCFG1_WDTPS_256 0x00080000 /* 1:256 */ +#define DEVCFG1_WDTPS_512 0x00090000 /* 1:512 */ +#define DEVCFG1_WDTPS_1024 0x000a0000 /* 1:1024 */ +#define DEVCFG1_WDTPS_2048 0x000b0000 /* 1:2048 */ +#define DEVCFG1_WDTPS_4096 0x000c0000 /* 1:4096 */ +#define DEVCFG1_WDTPS_8192 0x000d0000 /* 1:8192 */ +#define DEVCFG1_WDTPS_16384 0x000e0000 /* 1:16384 */ +#define DEVCFG1_WDTPS_32768 0x000f0000 /* 1:32768 */ +#define DEVCFG1_WDTPS_65536 0x00100000 /* 1:65536 */ +#define DEVCFG1_WDTPS_131072 0x00110000 /* 1:131072 */ +#define DEVCFG1_WDTPS_262144 0x00120000 /* 1:262144 */ +#define DEVCFG1_WDTPS_524288 0x00130000 /* 1:524288 */ +#define DEVCFG1_WDTPS_1048576 0x00140000 /* 1:1048576 */ +#define DEVCFG1_FWDTEN 0x00800000 /* Watchdog enable */ + +/* + * Config2 register at 1fc02ff4. + */ +#define DEVCFG2_UNUSED 0xfff87888 +#define DEVCFG2_FPLLIDIV_MASK 0x00000007 /* PLL input divider */ +#define DEVCFG2_FPLLIDIV_1 0x00000000 /* 1x */ +#define DEVCFG2_FPLLIDIV_2 0x00000001 /* 2x */ +#define DEVCFG2_FPLLIDIV_3 0x00000002 /* 3x */ +#define DEVCFG2_FPLLIDIV_4 0x00000003 /* 4x */ +#define DEVCFG2_FPLLIDIV_5 0x00000004 /* 5x */ +#define DEVCFG2_FPLLIDIV_6 0x00000005 /* 6x */ +#define DEVCFG2_FPLLIDIV_10 0x00000006 /* 10x */ +#define DEVCFG2_FPLLIDIV_12 0x00000007 /* 12x */ +#define DEVCFG2_FPLLMUL_MASK 0x00000070 /* PLL multiplier */ +#define DEVCFG2_FPLLMUL_15 0x00000000 /* 15x */ +#define DEVCFG2_FPLLMUL_16 0x00000010 /* 16x */ +#define DEVCFG2_FPLLMUL_17 0x00000020 /* 17x */ +#define DEVCFG2_FPLLMUL_18 0x00000030 /* 18x */ +#define DEVCFG2_FPLLMUL_19 0x00000040 /* 19x */ +#define DEVCFG2_FPLLMUL_20 0x00000050 /* 20x */ +#define DEVCFG2_FPLLMUL_21 0x00000060 /* 21x */ +#define DEVCFG2_FPLLMUL_24 0x00000070 /* 24x */ +#define DEVCFG2_UPLLIDIV_MASK 0x00000700 /* USB PLL input divider */ +#define DEVCFG2_UPLLIDIV_1 0x00000000 /* 1x */ +#define DEVCFG2_UPLLIDIV_2 0x00000100 /* 2x */ +#define DEVCFG2_UPLLIDIV_3 0x00000200 /* 3x */ +#define DEVCFG2_UPLLIDIV_4 0x00000300 /* 4x */ +#define DEVCFG2_UPLLIDIV_5 0x00000400 /* 5x */ +#define DEVCFG2_UPLLIDIV_6 0x00000500 /* 6x */ +#define DEVCFG2_UPLLIDIV_10 0x00000600 /* 10x */ +#define DEVCFG2_UPLLIDIV_12 0x00000700 /* 12x */ +#define DEVCFG2_UPLLDIS 0x00008000 /* Disable USB PLL */ +#define DEVCFG2_FPLLODIV_MASK 0x00070000 /* Default postscaler for PLL */ +#define DEVCFG2_FPLLODIV_1 0x00000000 /* 1x */ +#define DEVCFG2_FPLLODIV_2 0x00010000 /* 2x */ +#define DEVCFG2_FPLLODIV_4 0x00020000 /* 4x */ +#define DEVCFG2_FPLLODIV_8 0x00030000 /* 8x */ +#define DEVCFG2_FPLLODIV_16 0x00040000 /* 16x */ +#define DEVCFG2_FPLLODIV_32 0x00050000 /* 32x */ +#define DEVCFG2_FPLLODIV_64 0x00060000 /* 64x */ +#define DEVCFG2_FPLLODIV_256 0x00070000 /* 256x */ + +/* + * Config3 register at 1fc02ff0. + */ +#define DEVCFG3_UNUSED 0x38f80000 +#define DEVCFG3_USERID_MASK 0x0000ffff /* User-defined ID */ +#define DEVCFG3_USERID(x) ((x) & 0xffff) +#define DEVCFG3_FSRSSEL_MASK 0x00070000 /* SRS select */ +#define DEVCFG3_FSRSSEL_ALL 0x00000000 /* All irqs assigned to shadow set */ +#define DEVCFG3_FSRSSEL_1 0x00010000 /* Assign irq priority 1 to shadow set */ +#define DEVCFG3_FSRSSEL_2 0x00020000 /* Assign irq priority 2 to shadow set */ +#define DEVCFG3_FSRSSEL_3 0x00030000 /* Assign irq priority 3 to shadow set */ +#define DEVCFG3_FSRSSEL_4 0x00040000 /* Assign irq priority 4 to shadow set */ +#define DEVCFG3_FSRSSEL_5 0x00050000 /* Assign irq priority 5 to shadow set */ +#define DEVCFG3_FSRSSEL_6 0x00060000 /* Assign irq priority 6 to shadow set */ +#define DEVCFG3_FSRSSEL_7 0x00070000 /* Assign irq priority 7 to shadow set */ +#define DEVCFG3_FMIIEN 0x01000000 /* Ethernet MII enable */ +#define DEVCFG3_FETHIO 0x02000000 /* Ethernet pins default */ +#define DEVCFG3_FCANIO 0x04000000 /* CAN pins default */ +#define DEVCFG3_FUSBIDIO 0x40000000 /* USBID pin: controlled by USB */ +#define DEVCFG3_FVBUSONIO 0x80000000 /* VBuson pin: controlled by USB */ + +/*-------------------------------------- + * Interrupt controller registers. + */ +#define INTCON PIC32_R (0x81000) /* Interrupt Control */ +#define INTCONCLR PIC32_R (0x81004) +#define INTCONSET PIC32_R (0x81008) +#define INTCONINV PIC32_R (0x8100C) +#define INTSTAT PIC32_R (0x81010) /* Interrupt Status */ +#define IPTMR PIC32_R (0x81020) /* Temporal Proximity Timer */ +#define IPTMRCLR PIC32_R (0x81024) +#define IPTMRSET PIC32_R (0x81028) +#define IPTMRINV PIC32_R (0x8102C) +#define IFS(n) PIC32_R (0x81030+((n)<<4)) /* IFS(0..2) - Interrupt Flag Status */ +#define IFSCLR(n) PIC32_R (0x81034+((n)<<4)) +#define IFSSET(n) PIC32_R (0x81038+((n)<<4)) +#define IFSINV(n) PIC32_R (0x8103C+((n)<<4)) +#define IFS0 IFS(0) +#define IFS1 IFS(1) +#define IFS2 IFS(2) +#define IEC(n) PIC32_R (0x81060+((n)<<4)) /* IEC(0..2) - Interrupt Enable Control */ +#define IECCLR(n) PIC32_R (0x81064+((n)<<4)) +#define IECSET(n) PIC32_R (0x81068+((n)<<4)) +#define IECINV(n) PIC32_R (0x8106C+((n)<<4)) +#define IEC0 IEC(0) +#define IEC1 IEC(1) +#define IEC2 IEC(2) +#define IPC(n) PIC32_R (0x81090+((n)<<4)) /* IPC(0..12) - Interrupt Priority Control */ +#define IPCCLR(n) PIC32_R (0x81094+((n)<<4)) +#define IPCSET(n) PIC32_R (0x81098+((n)<<4)) +#define IPCINV(n) PIC32_R (0x8109C+((n)<<4)) +#define IPC0 IPC(0) +#define IPC1 IPC(1) +#define IPC2 IPC(2) +#define IPC3 IPC(3) +#define IPC4 IPC(4) +#define IPC5 IPC(5) +#define IPC6 IPC(6) +#define IPC7 IPC(7) +#define IPC8 IPC(8) +#define IPC9 IPC(9) +#define IPC10 IPC(10) +#define IPC11 IPC(11) +#define IPC12 IPC(12) + +/* + * Interrupt Control register. + */ +#define PIC32_INTCON_INT0EP 0x0001 /* External interrupt 0 polarity rising edge */ +#define PIC32_INTCON_INT1EP 0x0002 /* External interrupt 1 polarity rising edge */ +#define PIC32_INTCON_INT2EP 0x0004 /* External interrupt 2 polarity rising edge */ +#define PIC32_INTCON_INT3EP 0x0008 /* External interrupt 3 polarity rising edge */ +#define PIC32_INTCON_INT4EP 0x0010 /* External interrupt 4 polarity rising edge */ +#define PIC32_INTCON_TPC(x) ((x)<<8) /* Temporal proximity group priority */ +#define PIC32_INTCON_MVEC 0x1000 /* Multi-vectored mode */ +#define PIC32_INTCON_FRZ 0x4000 /* Freeze in debug mode */ +#define PIC32_INTCON_SS0 0x8000 /* Single vector has a shadow register set */ + +/* + * Interrupt Status register. + */ +#define PIC32_INTSTAT_VEC(s) ((s) & 0xFF) /* Interrupt vector */ +#define PIC32_INTSTAT_SRIPL(s) ((s) >> 8 & 7) /* Requested priority level */ +#define PIC32_INTSTAT_SRIPL_MASK 0x0700 + +/* + * Interrupt Prority Control register. + */ +#define PIC32_IPC_IS0(x) (x) /* Interrupt 0 subpriority */ +#define PIC32_IPC_IP0(x) ((x)<<2) /* Interrupt 0 priority */ +#define PIC32_IPC_IS1(x) ((x)<<8) /* Interrupt 1 subpriority */ +#define PIC32_IPC_IP1(x) ((x)<<10) /* Interrupt 1 priority */ +#define PIC32_IPC_IS2(x) ((x)<<16) /* Interrupt 2 subpriority */ +#define PIC32_IPC_IP2(x) ((x)<<18) /* Interrupt 2 priority */ +#define PIC32_IPC_IS3(x) ((x)<<24) /* Interrupt 3 subpriority */ +#define PIC32_IPC_IP3(x) ((x)<<26) /* Interrupt 3 priority */ + +/* + * IRQ numbers for PIC32MX3xx/4xx/5xx/6xx/7xx + */ +#define PIC32_IRQ_CT 0 /* Core Timer Interrupt */ +#define PIC32_IRQ_CS0 1 /* Core Software Interrupt 0 */ +#define PIC32_IRQ_CS1 2 /* Core Software Interrupt 1 */ +#define PIC32_IRQ_INT0 3 /* External Interrupt 0 */ +#define PIC32_IRQ_T1 4 /* Timer1 */ +#define PIC32_IRQ_IC1 5 /* Input Capture 1 */ +#define PIC32_IRQ_OC1 6 /* Output Compare 1 */ +#define PIC32_IRQ_INT1 7 /* External Interrupt 1 */ +#define PIC32_IRQ_T2 8 /* Timer2 */ +#define PIC32_IRQ_IC2 9 /* Input Capture 2 */ +#define PIC32_IRQ_OC2 10 /* Output Compare 2 */ +#define PIC32_IRQ_INT2 11 /* External Interrupt 2 */ +#define PIC32_IRQ_T3 12 /* Timer3 */ +#define PIC32_IRQ_IC3 13 /* Input Capture 3 */ +#define PIC32_IRQ_OC3 14 /* Output Compare 3 */ +#define PIC32_IRQ_INT3 15 /* External Interrupt 3 */ +#define PIC32_IRQ_T4 16 /* Timer4 */ +#define PIC32_IRQ_IC4 17 /* Input Capture 4 */ +#define PIC32_IRQ_OC4 18 /* Output Compare 4 */ +#define PIC32_IRQ_INT4 19 /* External Interrupt 4 */ +#define PIC32_IRQ_T5 20 /* Timer5 */ +#define PIC32_IRQ_IC5 21 /* Input Capture 5 */ +#define PIC32_IRQ_OC5 22 /* Output Compare 5 */ +#define PIC32_IRQ_SPI1E 23 /* SPI1 Fault */ +#define PIC32_IRQ_SPI1TX 24 /* SPI1 Transfer Done */ +#define PIC32_IRQ_SPI1RX 25 /* SPI1 Receive Done */ + +#define PIC32_IRQ_SPI3E 26 /* SPI3 Fault */ +#define PIC32_IRQ_SPI3TX 27 /* SPI3 Transfer Done */ +#define PIC32_IRQ_SPI3RX 28 /* SPI3 Receive Done */ +#define PIC32_IRQ_U1E 26 /* UART1 Error */ +#define PIC32_IRQ_U1RX 27 /* UART1 Receiver */ +#define PIC32_IRQ_U1TX 28 /* UART1 Transmitter */ +#define PIC32_IRQ_I2C3B 26 /* I2C3 Bus Collision Event */ +#define PIC32_IRQ_I2C3S 27 /* I2C3 Slave Event */ +#define PIC32_IRQ_I2C3M 28 /* I2C3 Master Event */ + +#define PIC32_IRQ_I2C1B 29 /* I2C1 Bus Collision Event */ +#define PIC32_IRQ_I2C1S 30 /* I2C1 Slave Event */ +#define PIC32_IRQ_I2C1M 31 /* I2C1 Master Event */ +#define PIC32_IRQ_CN 32 /* Input Change Interrupt */ +#define PIC32_IRQ_AD1 33 /* ADC1 Convert Done */ +#define PIC32_IRQ_PMP 34 /* Parallel Master Port */ +#define PIC32_IRQ_CMP1 35 /* Comparator Interrupt */ +#define PIC32_IRQ_CMP2 36 /* Comparator Interrupt */ + +#define PIC32_IRQ_SPI2E 37 /* SPI2 Fault */ +#define PIC32_IRQ_SPI2TX 38 /* SPI2 Transfer Done */ +#define PIC32_IRQ_SPI2RX 39 /* SPI2 Receive Done */ +#define PIC32_IRQ_U3E 37 /* UART3 Error */ +#define PIC32_IRQ_U3RX 38 /* UART3 Receiver */ +#define PIC32_IRQ_U3TX 39 /* UART3 Transmitter */ +#define PIC32_IRQ_I2C4B 37 /* I2C4 Bus Collision Event */ +#define PIC32_IRQ_I2C4S 38 /* I2C4 Slave Event */ +#define PIC32_IRQ_I2C4M 39 /* I2C4 Master Event */ + +#define PIC32_IRQ_SPI4E 40 /* SPI4 Fault */ +#define PIC32_IRQ_SPI4TX 41 /* SPI4 Transfer Done */ +#define PIC32_IRQ_SPI4RX 42 /* SPI4 Receive Done */ +#define PIC32_IRQ_U2E 40 /* UART2 Error */ +#define PIC32_IRQ_U2RX 41 /* UART2 Receiver */ +#define PIC32_IRQ_U2TX 42 /* UART2 Transmitter */ +#define PIC32_IRQ_I2C5B 40 /* I2C5 Bus Collision Event */ +#define PIC32_IRQ_I2C5S 41 /* I2C5 Slave Event */ +#define PIC32_IRQ_I2C5M 42 /* I2C5 Master Event */ + +#define PIC32_IRQ_I2C2B 43 /* I2C2 Bus Collision Event */ +#define PIC32_IRQ_I2C2S 44 /* I2C2 Slave Event */ +#define PIC32_IRQ_I2C2M 45 /* I2C2 Master Event */ +#define PIC32_IRQ_FSCM 46 /* Fail-Safe Clock Monitor */ +#define PIC32_IRQ_RTCC 47 /* Real-Time Clock and Calendar */ +#define PIC32_IRQ_DMA0 48 /* DMA Channel 0 */ +#define PIC32_IRQ_DMA1 49 /* DMA Channel 1 */ +#define PIC32_IRQ_DMA2 50 /* DMA Channel 2 */ +#define PIC32_IRQ_DMA3 51 /* DMA Channel 3 */ +#define PIC32_IRQ_DMA4 52 /* DMA Channel 4 */ +#define PIC32_IRQ_DMA5 53 /* DMA Channel 5 */ +#define PIC32_IRQ_DMA6 54 /* DMA Channel 6 */ +#define PIC32_IRQ_DMA7 55 /* DMA Channel 7 */ +#define PIC32_IRQ_FCE 56 /* Flash Control Event */ +#define PIC32_IRQ_USB 57 /* USB */ +#define PIC32_IRQ_CAN1 58 /* Control Area Network 1 */ +#define PIC32_IRQ_CAN2 59 /* Control Area Network 2 */ +#define PIC32_IRQ_ETH 60 /* Ethernet Interrupt */ +#define PIC32_IRQ_IC1E 61 /* Input Capture 1 Error */ +#define PIC32_IRQ_IC2E 62 /* Input Capture 2 Error */ +#define PIC32_IRQ_IC3E 63 /* Input Capture 3 Error */ +#define PIC32_IRQ_IC4E 64 /* Input Capture 4 Error */ +#define PIC32_IRQ_IC5E 65 /* Input Capture 5 Error */ +#define PIC32_IRQ_PMPE 66 /* Parallel Master Port Error */ +#define PIC32_IRQ_U4E 67 /* UART4 Error */ +#define PIC32_IRQ_U4RX 68 /* UART4 Receiver */ +#define PIC32_IRQ_U4TX 69 /* UART4 Transmitter */ +#define PIC32_IRQ_U6E 70 /* UART6 Error */ +#define PIC32_IRQ_U6RX 71 /* UART6 Receiver */ +#define PIC32_IRQ_U6TX 72 /* UART6 Transmitter */ +#define PIC32_IRQ_U5E 73 /* UART5 Error */ +#define PIC32_IRQ_U5RX 74 /* UART5 Receiver */ +#define PIC32_IRQ_U5TX 75 /* UART5 Transmitter */ + +/* + * Interrupt vector numbers for PIC32MX3xx/4xx/5xx/6xx/7xx + */ +#define PIC32_VECT_CT 0 /* Core Timer Interrupt */ +#define PIC32_VECT_CS0 1 /* Core Software Interrupt 0 */ +#define PIC32_VECT_CS1 2 /* Core Software Interrupt 1 */ +#define PIC32_VECT_INT0 3 /* External Interrupt 0 */ +#define PIC32_VECT_T1 4 /* Timer1 */ +#define PIC32_VECT_IC1 5 /* Input Capture 1 */ +#define PIC32_VECT_OC1 6 /* Output Compare 1 */ +#define PIC32_VECT_INT1 7 /* External Interrupt 1 */ +#define PIC32_VECT_T2 8 /* Timer2 */ +#define PIC32_VECT_IC2 9 /* Input Capture 2 */ +#define PIC32_VECT_OC2 10 /* Output Compare 2 */ +#define PIC32_VECT_INT2 11 /* External Interrupt 2 */ +#define PIC32_VECT_T3 12 /* Timer3 */ +#define PIC32_VECT_IC3 13 /* Input Capture 3 */ +#define PIC32_VECT_OC3 14 /* Output Compare 3 */ +#define PIC32_VECT_INT3 15 /* External Interrupt 3 */ +#define PIC32_VECT_T4 16 /* Timer4 */ +#define PIC32_VECT_IC4 17 /* Input Capture 4 */ +#define PIC32_VECT_OC4 18 /* Output Compare 4 */ +#define PIC32_VECT_INT4 19 /* External Interrupt 4 */ +#define PIC32_VECT_T5 20 /* Timer5 */ +#define PIC32_VECT_IC5 21 /* Input Capture 5 */ +#define PIC32_VECT_OC5 22 /* Output Compare 5 */ +#define PIC32_VECT_SPI1 23 /* SPI1 */ + +#define PIC32_VECT_SPI3 24 /* SPI3 */ +#define PIC32_VECT_U1 24 /* UART1 */ +#define PIC32_VECT_I2C3 24 /* I2C3 */ + +#define PIC32_VECT_I2C1 25 /* I2C1 */ +#define PIC32_VECT_CN 26 /* Input Change Interrupt */ +#define PIC32_VECT_AD1 27 /* ADC1 Convert Done */ +#define PIC32_VECT_PMP 28 /* Parallel Master Port */ +#define PIC32_VECT_CMP1 29 /* Comparator Interrupt */ +#define PIC32_VECT_CMP2 30 /* Comparator Interrupt */ + +#define PIC32_VECT_SPI2 31 /* SPI2 */ +#define PIC32_VECT_U3 31 /* UART3 */ +#define PIC32_VECT_I2C4 31 /* I2C4 */ + +#define PIC32_VECT_SPI4 32 /* SPI4 */ +#define PIC32_VECT_U2 32 /* UART2 */ +#define PIC32_VECT_I2C5 32 /* I2C5 */ + +#define PIC32_VECT_I2C2 33 /* I2C2 */ +#define PIC32_VECT_FSCM 34 /* Fail-Safe Clock Monitor */ +#define PIC32_VECT_RTCC 35 /* Real-Time Clock and Calendar */ +#define PIC32_VECT_DMA0 36 /* DMA Channel 0 */ +#define PIC32_VECT_DMA1 37 /* DMA Channel 1 */ +#define PIC32_VECT_DMA2 38 /* DMA Channel 2 */ +#define PIC32_VECT_DMA3 39 /* DMA Channel 3 */ +#define PIC32_VECT_DMA4 40 /* DMA Channel 4 */ +#define PIC32_VECT_DMA5 41 /* DMA Channel 5 */ +#define PIC32_VECT_DMA6 42 /* DMA Channel 6 */ +#define PIC32_VECT_DMA7 43 /* DMA Channel 7 */ +#define PIC32_VECT_FCE 44 /* Flash Control Event */ +#define PIC32_VECT_USB 45 /* USB */ +#define PIC32_VECT_CAN1 46 /* Control Area Network 1 */ +#define PIC32_VECT_CAN2 47 /* Control Area Network 2 */ +#define PIC32_VECT_ETH 48 /* Ethernet Interrupt */ +#define PIC32_VECT_U4 49 /* UART4 */ +#define PIC32_VECT_U6 50 /* UART6 */ +#define PIC32_VECT_U5 51 /* UART5 */ + +#endif /* _IO_PIC32MX_H */ diff --git a/hw/mips/pic32mz.h b/hw/mips/pic32mz.h new file mode 100644 index 0000000000000..f46e5e052a786 --- /dev/null +++ b/hw/mips/pic32mz.h @@ -0,0 +1,1778 @@ +/* + * Hardware register defines for Microchip PIC32MZ microcontroller. + * + * Copyright (C) 2013 Serge Vakulenko + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ +#ifndef _IO_PIC32MZ_H +#define _IO_PIC32MZ_H + +/*-------------------------------------- + * Configuration registers. + */ +#define DEVCFG0 0x9fc0fffc +#define DEVCFG1 0x9fc0fff8 +#define DEVCFG2 0x9fc0fff4 +#define DEVCFG3 0x9fc0fff0 + +#define PIC32_DEVCFG(cfg0, cfg1, cfg2, cfg3) \ + unsigned __DEVCFG0 __attribute__ ((section(".config0"))) = (cfg0) ^ 0x7fffffff; \ + unsigned __DEVCFG1 __attribute__ ((section(".config1"))) = (cfg1) | DEVCFG1_UNUSED; \ + unsigned __DEVCFG2 __attribute__ ((section(".config2"))) = (cfg2) | DEVCFG2_UNUSED; \ + unsigned __DEVCFG3 __attribute__ ((section(".config3"))) = (cfg3) | DEVCFG3_UNUSED + +/* + * Config0 register at 1fc0ffcc, inverted. + */ +#define DEVCFG0_DEBUG_ENABLE 0x00000002 /* Enable background debugger */ +#define DEVCFG0_JTAG_DISABLE 0x00000004 /* Disable JTAG port */ +#define DEVCFG0_ICESEL_PGE2 0x00000008 /* Use PGC2/PGD2 (default PGC1/PGD1) */ +#define DEVCFG0_TRC_DISABLE 0x00000020 /* Disable Trace port */ +#define DEVCFG0_MICROMIPS 0x00000040 /* Boot in microMIPS mode */ +#define DEVCFG0_ECC_MASK 0x00000300 /* Flash ECC mode mask */ +#define DEVCFG0_ECC_ENABLE 0x00000300 /* Enable Flash ECC */ +#define DEVCFG0_DECC_ENABLE 0x00000200 /* Enable Dynamic Flash ECC */ +#define DEVCFG0_ECC_DIS_LOCK 0x00000100 /* Disable ECC, lock ECCCON */ +#define DEVCFG0_FSLEEP 0x00000400 /* Flash power down controlled by VREGS bit */ +#define DEVCFG0_DBGPER0 0x00001000 /* In Debug mode, deny CPU access to + * Permission Group 0 permission regions */ +#define DEVCFG0_DBGPER1 0x00002000 /* In Debug mode, deny CPU access to + * Permission Group 1 permission regions */ +#define DEVCFG0_DBGPER2 0x00004000 /* In Debug mode, deny CPU access to + * Permission Group 2 permission regions */ +#define DEVCFG0_EJTAG_REDUCED 0x40000000 /* Reduced EJTAG functionality */ + +/* + * Config1 register at 1fc0ffc8. + */ +#define DEVCFG1_UNUSED 0x00003800 +#define DEVCFG1_FNOSC_MASK 0x00000007 /* Oscillator selection */ +#define DEVCFG1_FNOSC_SPLL 0x00000001 /* SPLL */ +#define DEVCFG1_FNOSC_POSC 0x00000002 /* Primary oscillator XT, HS, EC */ +#define DEVCFG1_FNOSC_SOSC 0x00000004 /* Secondary oscillator */ +#define DEVCFG1_FNOSC_LPRC 0x00000005 /* Low-power RC */ +#define DEVCFG1_FNOSC_FRCDIV 0x00000007 /* Fast RC with divide-by-N */ +#define DEVCFG1_DMTINV_MASK 0x00000038 /* Deadman Timer Count Window Interval */ +#define DEVCFG1_DMTINV_1_2 0x00000008 /* 1/2 of counter value */ +#define DEVCFG1_DMTINV_3_4 0x00000010 /* 3/4 of counter value */ +#define DEVCFG1_DMTINV_7_8 0x00000018 /* 7/8 of counter value */ +#define DEVCFG1_DMTINV_15_16 0x00000020 /* 15/16 of counter value */ +#define DEVCFG1_DMTINV_31_32 0x00000028 /* 31/32 of counter value */ +#define DEVCFG1_DMTINV_63_64 0x00000030 /* 63/64 of counter value */ +#define DEVCFG1_DMTINV_127_128 0x00000038 /* 127/128 of counter value */ +#define DEVCFG1_FSOSCEN 0x00000040 /* Secondary oscillator enable */ +#define DEVCFG1_IESO 0x00000080 /* Internal-external switch over */ +#define DEVCFG1_POSCMOD_MASK 0x00000300 /* Primary oscillator config */ +#define DEVCFG1_POSCMOD_EXT 0x00000000 /* External mode */ +#define DEVCFG1_POSCMOD_HS 0x00000200 /* HS oscillator */ +#define DEVCFG1_POSCMOD_DISABLE 0x00000300 /* Disabled */ +#define DEVCFG1_CLKO_DISABLE 0x00000400 /* Disable CLKO output */ +#define DEVCFG1_FCKS_ENABLE 0x00004000 /* Enable clock switching */ +#define DEVCFG1_FCKM_ENABLE 0x00008000 /* Enable fail-safe clock monitoring */ +#define DEVCFG1_WDTPS_MASK 0x001f0000 /* Watchdog postscale */ +#define DEVCFG1_WDTPS_1 0x00000000 /* 1:1 */ +#define DEVCFG1_WDTPS_2 0x00010000 /* 1:2 */ +#define DEVCFG1_WDTPS_4 0x00020000 /* 1:4 */ +#define DEVCFG1_WDTPS_8 0x00030000 /* 1:8 */ +#define DEVCFG1_WDTPS_16 0x00040000 /* 1:16 */ +#define DEVCFG1_WDTPS_32 0x00050000 /* 1:32 */ +#define DEVCFG1_WDTPS_64 0x00060000 /* 1:64 */ +#define DEVCFG1_WDTPS_128 0x00070000 /* 1:128 */ +#define DEVCFG1_WDTPS_256 0x00080000 /* 1:256 */ +#define DEVCFG1_WDTPS_512 0x00090000 /* 1:512 */ +#define DEVCFG1_WDTPS_1024 0x000a0000 /* 1:1024 */ +#define DEVCFG1_WDTPS_2048 0x000b0000 /* 1:2048 */ +#define DEVCFG1_WDTPS_4096 0x000c0000 /* 1:4096 */ +#define DEVCFG1_WDTPS_8192 0x000d0000 /* 1:8192 */ +#define DEVCFG1_WDTPS_16384 0x000e0000 /* 1:16384 */ +#define DEVCFG1_WDTPS_32768 0x000f0000 /* 1:32768 */ +#define DEVCFG1_WDTPS_65536 0x00100000 /* 1:65536 */ +#define DEVCFG1_WDTPS_131072 0x00110000 /* 1:131072 */ +#define DEVCFG1_WDTPS_262144 0x00120000 /* 1:262144 */ +#define DEVCFG1_WDTPS_524288 0x00130000 /* 1:524288 */ +#define DEVCFG1_WDTPS_1048576 0x00140000 /* 1:1048576 */ +#define DEVCFG1_WDTSPGM 0x00200000 /* Watchdog stops during Flash programming */ +#define DEVCFG1_WINDIS 0x00400000 /* Watchdog is in non-Window mode */ +#define DEVCFG1_FWDTEN 0x00800000 /* Watchdog enable */ +#define DEVCFG1_FWDTWINSZ_75 0x00000000 /* Watchdog window size is 75% */ +#define DEVCFG1_FWDTWINSZ_50 0x01000000 /* 50% */ +#define DEVCFG1_FWDTWINSZ_375 0x02000000 /* 37.5% */ +#define DEVCFG1_FWDTWINSZ_25 0x03000000 /* 25% */ +#define DEVCFG1_DMTCNT(n) ((n)<<26) /* Deadman Timer Count Select */ +#define DEVCFG1_FDMTEN 0x80000000 /* Deadman Timer enable */ + +/* + * Config2 register at 1fc0ffc4. + */ +#define DEVCFG2_UNUSED 0x3ff88008 +#define DEVCFG2_FPLLIDIV_MASK 0x00000007 /* PLL input divider */ +#define DEVCFG2_FPLLIDIV_1 0x00000000 /* 1x */ +#define DEVCFG2_FPLLIDIV_2 0x00000001 /* 2x */ +#define DEVCFG2_FPLLIDIV_3 0x00000002 /* 3x */ +#define DEVCFG2_FPLLIDIV_4 0x00000003 /* 4x */ +#define DEVCFG2_FPLLIDIV_5 0x00000004 /* 5x */ +#define DEVCFG2_FPLLIDIV_6 0x00000005 /* 6x */ +#define DEVCFG2_FPLLIDIV_7 0x00000006 /* 7x */ +#define DEVCFG2_FPLLIDIV_8 0x00000007 /* 8x */ +#define DEVCFG2_FPLLRNG_MASK 0x00000070 /* PLL input frequency range */ +#define DEVCFG2_FPLLRNG_BYPASS 0x00000000 /* Bypass */ +#define DEVCFG2_FPLLRNG_5_10 0x00000010 /* 5-10 MHz */ +#define DEVCFG2_FPLLRNG_8_16 0x00000020 /* 8-16 MHz */ +#define DEVCFG2_FPLLRNG_13_26 0x00000030 /* 13-26 MHz */ +#define DEVCFG2_FPLLRNG_21_42 0x00000040 /* 21-42 MHz */ +#define DEVCFG2_FPLLRNG_34_64 0x00000050 /* 34-64 MHz */ +#define DEVCFG2_FPLLICLK_FRC 0x00000080 /* Select FRC as input to PLL */ +#define DEVCFG2_FPLLMULT(n) (((n)-1)<<8) /* PLL Feedback Divider */ +#define DEVCFG2_FPLLODIV_MASK 0x00070000 /* Default PLL output divisor */ +#define DEVCFG2_FPLLODIV_2 0x00000000 /* 2x */ +#define DEVCFG2_FPLLODIV_4 0x00020000 /* 4x */ +#define DEVCFG2_FPLLODIV_8 0x00030000 /* 8x */ +#define DEVCFG2_FPLLODIV_16 0x00040000 /* 16x */ +#define DEVCFG2_FPLLODIV_32 0x00050000 /* 32x */ +#define DEVCFG2_UPLLFSEL_24 0x40000000 /* USB PLL input clock is 24 MHz (default 12 MHz) */ +#define DEVCFG2_UPLLEN 0x80000000 /* Enable USB PLL */ + +/* + * Config3 register at 1fc0ffc0. + */ +#define DEVCFG3_UNUSED 0x84ff0000 +#define DEVCFG3_USERID_MASK 0x0000ffff /* User-defined ID */ +#define DEVCFG3_USERID(x) ((x) & 0xffff) +#define DEVCFG3_FMIIEN 0x01000000 /* Ethernet MII enable */ +#define DEVCFG3_FETHIO 0x02000000 /* Default Ethernet pins */ +#define DEVCFG3_PGL1WAY 0x08000000 /* Permission Group Lock - only 1 reconfig */ +#define DEVCFG3_PMDL1WAY 0x10000000 /* Peripheral Module Disable - only 1 reconfig */ +#define DEVCFG3_IOL1WAY 0x20000000 /* Peripheral Pin Select - only 1 reconfig */ +#define DEVCFG3_FUSBIDIO 0x40000000 /* USBID pin: controlled by USB */ + +/*-------------------------------------- + * Peripheral registers. + */ +#define PIC32_R(a) (a) + +/*-------------------------------------- + * Port A-K registers. + */ +#define ANSELA PIC32_R (0x60000) /* Port A: analog select */ +#define ANSELACLR PIC32_R (0x60004) +#define ANSELASET PIC32_R (0x60008) +#define ANSELAINV PIC32_R (0x6000C) +#define TRISA PIC32_R (0x60010) /* Port A: mask of inputs */ +#define TRISACLR PIC32_R (0x60014) +#define TRISASET PIC32_R (0x60018) +#define TRISAINV PIC32_R (0x6001C) +#define PORTA PIC32_R (0x60020) /* Port A: read inputs, write outputs */ +#define PORTACLR PIC32_R (0x60024) +#define PORTASET PIC32_R (0x60028) +#define PORTAINV PIC32_R (0x6002C) +#define LATA PIC32_R (0x60030) /* Port A: read/write outputs */ +#define LATACLR PIC32_R (0x60034) +#define LATASET PIC32_R (0x60038) +#define LATAINV PIC32_R (0x6003C) +#define ODCA PIC32_R (0x60040) /* Port A: open drain configuration */ +#define ODCACLR PIC32_R (0x60044) +#define ODCASET PIC32_R (0x60048) +#define ODCAINV PIC32_R (0x6004C) +#define CNPUA PIC32_R (0x60050) /* Port A: input pin pull-up enable */ +#define CNPUACLR PIC32_R (0x60054) +#define CNPUASET PIC32_R (0x60058) +#define CNPUAINV PIC32_R (0x6005C) +#define CNPDA PIC32_R (0x60060) /* Port A: input pin pull-down enable */ +#define CNPDACLR PIC32_R (0x60064) +#define CNPDASET PIC32_R (0x60068) +#define CNPDAINV PIC32_R (0x6006C) +#define CNCONA PIC32_R (0x60070) /* Port A: interrupt-on-change control */ +#define CNCONACLR PIC32_R (0x60074) +#define CNCONASET PIC32_R (0x60078) +#define CNCONAINV PIC32_R (0x6007C) +#define CNENA PIC32_R (0x60080) /* Port A: input change interrupt enable */ +#define CNENACLR PIC32_R (0x60084) +#define CNENASET PIC32_R (0x60088) +#define CNENAINV PIC32_R (0x6008C) +#define CNSTATA PIC32_R (0x60090) /* Port A: status */ +#define CNSTATACLR PIC32_R (0x60094) +#define CNSTATASET PIC32_R (0x60098) +#define CNSTATAINV PIC32_R (0x6009C) + +#define ANSELB PIC32_R (0x60100) /* Port B: analog select */ +#define ANSELBCLR PIC32_R (0x60104) +#define ANSELBSET PIC32_R (0x60108) +#define ANSELBINV PIC32_R (0x6010C) +#define TRISB PIC32_R (0x60110) /* Port B: mask of inputs */ +#define TRISBCLR PIC32_R (0x60114) +#define TRISBSET PIC32_R (0x60118) +#define TRISBINV PIC32_R (0x6011C) +#define PORTB PIC32_R (0x60120) /* Port B: read inputs, write outputs */ +#define PORTBCLR PIC32_R (0x60124) +#define PORTBSET PIC32_R (0x60128) +#define PORTBINV PIC32_R (0x6012C) +#define LATB PIC32_R (0x60130) /* Port B: read/write outputs */ +#define LATBCLR PIC32_R (0x60134) +#define LATBSET PIC32_R (0x60138) +#define LATBINV PIC32_R (0x6013C) +#define ODCB PIC32_R (0x60140) /* Port B: open drain configuration */ +#define ODCBCLR PIC32_R (0x60144) +#define ODCBSET PIC32_R (0x60148) +#define ODCBINV PIC32_R (0x6014C) +#define CNPUB PIC32_R (0x60150) /* Port B: input pin pull-up enable */ +#define CNPUBCLR PIC32_R (0x60154) +#define CNPUBSET PIC32_R (0x60158) +#define CNPUBINV PIC32_R (0x6015C) +#define CNPDB PIC32_R (0x60160) /* Port B: input pin pull-down enable */ +#define CNPDBCLR PIC32_R (0x60164) +#define CNPDBSET PIC32_R (0x60168) +#define CNPDBINV PIC32_R (0x6016C) +#define CNCONB PIC32_R (0x60170) /* Port B: interrupt-on-change control */ +#define CNCONBCLR PIC32_R (0x60174) +#define CNCONBSET PIC32_R (0x60178) +#define CNCONBINV PIC32_R (0x6017C) +#define CNENB PIC32_R (0x60180) /* Port B: input change interrupt enable */ +#define CNENBCLR PIC32_R (0x60184) +#define CNENBSET PIC32_R (0x60188) +#define CNENBINV PIC32_R (0x6018C) +#define CNSTATB PIC32_R (0x60190) /* Port B: status */ +#define CNSTATBCLR PIC32_R (0x60194) +#define CNSTATBSET PIC32_R (0x60198) +#define CNSTATBINV PIC32_R (0x6019C) + +#define ANSELC PIC32_R (0x60200) /* Port C: analog select */ +#define ANSELCCLR PIC32_R (0x60204) +#define ANSELCSET PIC32_R (0x60208) +#define ANSELCINV PIC32_R (0x6020C) +#define TRISC PIC32_R (0x60210) /* Port C: mask of inputs */ +#define TRISCCLR PIC32_R (0x60214) +#define TRISCSET PIC32_R (0x60218) +#define TRISCINV PIC32_R (0x6021C) +#define PORTC PIC32_R (0x60220) /* Port C: read inputs, write outputs */ +#define PORTCCLR PIC32_R (0x60224) +#define PORTCSET PIC32_R (0x60228) +#define PORTCINV PIC32_R (0x6022C) +#define LATC PIC32_R (0x60230) /* Port C: read/write outputs */ +#define LATCCLR PIC32_R (0x60234) +#define LATCSET PIC32_R (0x60238) +#define LATCINV PIC32_R (0x6023C) +#define ODCC PIC32_R (0x60240) /* Port C: open drain configuration */ +#define ODCCCLR PIC32_R (0x60244) +#define ODCCSET PIC32_R (0x60248) +#define ODCCINV PIC32_R (0x6024C) +#define CNPUC PIC32_R (0x60250) /* Port C: input pin pull-up enable */ +#define CNPUCCLR PIC32_R (0x60254) +#define CNPUCSET PIC32_R (0x60258) +#define CNPUCINV PIC32_R (0x6025C) +#define CNPDC PIC32_R (0x60260) /* Port C: input pin pull-down enable */ +#define CNPDCCLR PIC32_R (0x60264) +#define CNPDCSET PIC32_R (0x60268) +#define CNPDCINV PIC32_R (0x6026C) +#define CNCONC PIC32_R (0x60270) /* Port C: interrupt-on-change control */ +#define CNCONCCLR PIC32_R (0x60274) +#define CNCONCSET PIC32_R (0x60278) +#define CNCONCINV PIC32_R (0x6027C) +#define CNENC PIC32_R (0x60280) /* Port C: input change interrupt enable */ +#define CNENCCLR PIC32_R (0x60284) +#define CNENCSET PIC32_R (0x60288) +#define CNENCINV PIC32_R (0x6028C) +#define CNSTATC PIC32_R (0x60290) /* Port C: status */ +#define CNSTATCCLR PIC32_R (0x60294) +#define CNSTATCSET PIC32_R (0x60298) +#define CNSTATCINV PIC32_R (0x6029C) + +#define ANSELD PIC32_R (0x60300) /* Port D: analog select */ +#define ANSELDCLR PIC32_R (0x60304) +#define ANSELDSET PIC32_R (0x60308) +#define ANSELDINV PIC32_R (0x6030C) +#define TRISD PIC32_R (0x60310) /* Port D: mask of inputs */ +#define TRISDCLR PIC32_R (0x60314) +#define TRISDSET PIC32_R (0x60318) +#define TRISDINV PIC32_R (0x6031C) +#define PORTD PIC32_R (0x60320) /* Port D: read inputs, write outputs */ +#define PORTDCLR PIC32_R (0x60324) +#define PORTDSET PIC32_R (0x60328) +#define PORTDINV PIC32_R (0x6032C) +#define LATD PIC32_R (0x60330) /* Port D: read/write outputs */ +#define LATDCLR PIC32_R (0x60334) +#define LATDSET PIC32_R (0x60338) +#define LATDINV PIC32_R (0x6033C) +#define ODCD PIC32_R (0x60340) /* Port D: open drain configuration */ +#define ODCDCLR PIC32_R (0x60344) +#define ODCDSET PIC32_R (0x60348) +#define ODCDINV PIC32_R (0x6034C) +#define CNPUD PIC32_R (0x60350) /* Port D: input pin pull-up enable */ +#define CNPUDCLR PIC32_R (0x60354) +#define CNPUDSET PIC32_R (0x60358) +#define CNPUDINV PIC32_R (0x6035C) +#define CNPDD PIC32_R (0x60360) /* Port D: input pin pull-down enable */ +#define CNPDDCLR PIC32_R (0x60364) +#define CNPDDSET PIC32_R (0x60368) +#define CNPDDINV PIC32_R (0x6036C) +#define CNCOND PIC32_R (0x60370) /* Port D: interrupt-on-change control */ +#define CNCONDCLR PIC32_R (0x60374) +#define CNCONDSET PIC32_R (0x60378) +#define CNCONDINV PIC32_R (0x6037C) +#define CNEND PIC32_R (0x60380) /* Port D: input change interrupt enable */ +#define CNENDCLR PIC32_R (0x60384) +#define CNENDSET PIC32_R (0x60388) +#define CNENDINV PIC32_R (0x6038C) +#define CNSTATD PIC32_R (0x60390) /* Port D: status */ +#define CNSTATDCLR PIC32_R (0x60394) +#define CNSTATDSET PIC32_R (0x60398) +#define CNSTATDINV PIC32_R (0x6039C) + +#define ANSELE PIC32_R (0x60400) /* Port E: analog select */ +#define ANSELECLR PIC32_R (0x60404) +#define ANSELESET PIC32_R (0x60408) +#define ANSELEINV PIC32_R (0x6040C) +#define TRISE PIC32_R (0x60410) /* Port E: mask of inputs */ +#define TRISECLR PIC32_R (0x60414) +#define TRISESET PIC32_R (0x60418) +#define TRISEINV PIC32_R (0x6041C) +#define PORTE PIC32_R (0x60420) /* Port E: read inputs, write outputs */ +#define PORTECLR PIC32_R (0x60424) +#define PORTESET PIC32_R (0x60428) +#define PORTEINV PIC32_R (0x6042C) +#define LATE PIC32_R (0x60430) /* Port E: read/write outputs */ +#define LATECLR PIC32_R (0x60434) +#define LATESET PIC32_R (0x60438) +#define LATEINV PIC32_R (0x6043C) +#define ODCE PIC32_R (0x60440) /* Port E: open drain configuration */ +#define ODCECLR PIC32_R (0x60444) +#define ODCESET PIC32_R (0x60448) +#define ODCEINV PIC32_R (0x6044C) +#define CNPUE PIC32_R (0x60450) /* Port E: input pin pull-up enable */ +#define CNPUECLR PIC32_R (0x60454) +#define CNPUESET PIC32_R (0x60458) +#define CNPUEINV PIC32_R (0x6045C) +#define CNPDE PIC32_R (0x60460) /* Port E: input pin pull-down enable */ +#define CNPDECLR PIC32_R (0x60464) +#define CNPDESET PIC32_R (0x60468) +#define CNPDEINV PIC32_R (0x6046C) +#define CNCONE PIC32_R (0x60470) /* Port E: interrupt-on-change control */ +#define CNCONECLR PIC32_R (0x60474) +#define CNCONESET PIC32_R (0x60478) +#define CNCONEINV PIC32_R (0x6047C) +#define CNENE PIC32_R (0x60480) /* Port E: input change interrupt enable */ +#define CNENECLR PIC32_R (0x60484) +#define CNENESET PIC32_R (0x60488) +#define CNENEINV PIC32_R (0x6048C) +#define CNSTATE PIC32_R (0x60490) /* Port E: status */ +#define CNSTATECLR PIC32_R (0x60494) +#define CNSTATESET PIC32_R (0x60498) +#define CNSTATEINV PIC32_R (0x6049C) + +#define ANSELF PIC32_R (0x60500) /* Port F: analog select */ +#define ANSELFCLR PIC32_R (0x60504) +#define ANSELFSET PIC32_R (0x60508) +#define ANSELFINV PIC32_R (0x6050C) +#define TRISF PIC32_R (0x60510) /* Port F: mask of inputs */ +#define TRISFCLR PIC32_R (0x60514) +#define TRISFSET PIC32_R (0x60518) +#define TRISFINV PIC32_R (0x6051C) +#define PORTF PIC32_R (0x60520) /* Port F: read inputs, write outputs */ +#define PORTFCLR PIC32_R (0x60524) +#define PORTFSET PIC32_R (0x60528) +#define PORTFINV PIC32_R (0x6052C) +#define LATF PIC32_R (0x60530) /* Port F: read/write outputs */ +#define LATFCLR PIC32_R (0x60534) +#define LATFSET PIC32_R (0x60538) +#define LATFINV PIC32_R (0x6053C) +#define ODCF PIC32_R (0x60540) /* Port F: open drain configuration */ +#define ODCFCLR PIC32_R (0x60544) +#define ODCFSET PIC32_R (0x60548) +#define ODCFINV PIC32_R (0x6054C) +#define CNPUF PIC32_R (0x60550) /* Port F: input pin pull-up enable */ +#define CNPUFCLR PIC32_R (0x60554) +#define CNPUFSET PIC32_R (0x60558) +#define CNPUFINV PIC32_R (0x6055C) +#define CNPDF PIC32_R (0x60560) /* Port F: input pin pull-down enable */ +#define CNPDFCLR PIC32_R (0x60564) +#define CNPDFSET PIC32_R (0x60568) +#define CNPDFINV PIC32_R (0x6056C) +#define CNCONF PIC32_R (0x60570) /* Port F: interrupt-on-change control */ +#define CNCONFCLR PIC32_R (0x60574) +#define CNCONFSET PIC32_R (0x60578) +#define CNCONFINV PIC32_R (0x6057C) +#define CNENF PIC32_R (0x60580) /* Port F: input change interrupt enable */ +#define CNENFCLR PIC32_R (0x60584) +#define CNENFSET PIC32_R (0x60588) +#define CNENFINV PIC32_R (0x6058C) +#define CNSTATF PIC32_R (0x60590) /* Port F: status */ +#define CNSTATFCLR PIC32_R (0x60594) +#define CNSTATFSET PIC32_R (0x60598) +#define CNSTATFINV PIC32_R (0x6059C) + +#define ANSELG PIC32_R (0x60600) /* Port G: analog select */ +#define ANSELGCLR PIC32_R (0x60604) +#define ANSELGSET PIC32_R (0x60608) +#define ANSELGINV PIC32_R (0x6060C) +#define TRISG PIC32_R (0x60610) /* Port G: mask of inputs */ +#define TRISGCLR PIC32_R (0x60614) +#define TRISGSET PIC32_R (0x60618) +#define TRISGINV PIC32_R (0x6061C) +#define PORTG PIC32_R (0x60620) /* Port G: read inputs, write outputs */ +#define PORTGCLR PIC32_R (0x60624) +#define PORTGSET PIC32_R (0x60628) +#define PORTGINV PIC32_R (0x6062C) +#define LATG PIC32_R (0x60630) /* Port G: read/write outputs */ +#define LATGCLR PIC32_R (0x60634) +#define LATGSET PIC32_R (0x60638) +#define LATGINV PIC32_R (0x6063C) +#define ODCG PIC32_R (0x60640) /* Port G: open drain configuration */ +#define ODCGCLR PIC32_R (0x60644) +#define ODCGSET PIC32_R (0x60648) +#define ODCGINV PIC32_R (0x6064C) +#define CNPUG PIC32_R (0x60650) /* Port G: input pin pull-up enable */ +#define CNPUGCLR PIC32_R (0x60654) +#define CNPUGSET PIC32_R (0x60658) +#define CNPUGINV PIC32_R (0x6065C) +#define CNPDG PIC32_R (0x60660) /* Port G: input pin pull-down enable */ +#define CNPDGCLR PIC32_R (0x60664) +#define CNPDGSET PIC32_R (0x60668) +#define CNPDGINV PIC32_R (0x6066C) +#define CNCONG PIC32_R (0x60670) /* Port G: interrupt-on-change control */ +#define CNCONGCLR PIC32_R (0x60674) +#define CNCONGSET PIC32_R (0x60678) +#define CNCONGINV PIC32_R (0x6067C) +#define CNENG PIC32_R (0x60680) /* Port G: input change interrupt enable */ +#define CNENGCLR PIC32_R (0x60684) +#define CNENGSET PIC32_R (0x60688) +#define CNENGINV PIC32_R (0x6068C) +#define CNSTATG PIC32_R (0x60690) /* Port G: status */ +#define CNSTATGCLR PIC32_R (0x60694) +#define CNSTATGSET PIC32_R (0x60698) +#define CNSTATGINV PIC32_R (0x6069C) + +#define ANSELH PIC32_R (0x60700) /* Port H: analog select */ +#define ANSELHCLR PIC32_R (0x60704) +#define ANSELHSET PIC32_R (0x60708) +#define ANSELHINV PIC32_R (0x6070C) +#define TRISH PIC32_R (0x60710) /* Port H: mask of inputs */ +#define TRISHCLR PIC32_R (0x60714) +#define TRISHSET PIC32_R (0x60718) +#define TRISHINV PIC32_R (0x6071C) +#define PORTH PIC32_R (0x60720) /* Port H: read inputs, write outputs */ +#define PORTHCLR PIC32_R (0x60724) +#define PORTHSET PIC32_R (0x60728) +#define PORTHINV PIC32_R (0x6072C) +#define LATH PIC32_R (0x60730) /* Port H: read/write outputs */ +#define LATHCLR PIC32_R (0x60734) +#define LATHSET PIC32_R (0x60738) +#define LATHINV PIC32_R (0x6073C) +#define ODCH PIC32_R (0x60740) /* Port H: open drain configuration */ +#define ODCHCLR PIC32_R (0x60744) +#define ODCHSET PIC32_R (0x60748) +#define ODCHINV PIC32_R (0x6074C) +#define CNPUH PIC32_R (0x60750) /* Port H: input pin pull-up enable */ +#define CNPUHCLR PIC32_R (0x60754) +#define CNPUHSET PIC32_R (0x60758) +#define CNPUHINV PIC32_R (0x6075C) +#define CNPDH PIC32_R (0x60760) /* Port H: input pin pull-down enable */ +#define CNPDHCLR PIC32_R (0x60764) +#define CNPDHSET PIC32_R (0x60768) +#define CNPDHINV PIC32_R (0x6076C) +#define CNCONH PIC32_R (0x60770) /* Port H: interrupt-on-change control */ +#define CNCONHCLR PIC32_R (0x60774) +#define CNCONHSET PIC32_R (0x60778) +#define CNCONHINV PIC32_R (0x6077C) +#define CNENH PIC32_R (0x60780) /* Port H: input change interrupt enable */ +#define CNENHCLR PIC32_R (0x60784) +#define CNENHSET PIC32_R (0x60788) +#define CNENHINV PIC32_R (0x6078C) +#define CNSTATH PIC32_R (0x60790) /* Port H: status */ +#define CNSTATHCLR PIC32_R (0x60794) +#define CNSTATHSET PIC32_R (0x60798) +#define CNSTATHINV PIC32_R (0x6079C) + +#define ANSELJ PIC32_R (0x60800) /* Port J: analog select */ +#define ANSELJCLR PIC32_R (0x60804) +#define ANSELJSET PIC32_R (0x60808) +#define ANSELJINV PIC32_R (0x6080C) +#define TRISJ PIC32_R (0x60810) /* Port J: mask of inputs */ +#define TRISJCLR PIC32_R (0x60814) +#define TRISJSET PIC32_R (0x60818) +#define TRISJINV PIC32_R (0x6081C) +#define PORTJ PIC32_R (0x60820) /* Port J: read inputs, write outputs */ +#define PORTJCLR PIC32_R (0x60824) +#define PORTJSET PIC32_R (0x60828) +#define PORTJINV PIC32_R (0x6082C) +#define LATJ PIC32_R (0x60830) /* Port J: read/write outputs */ +#define LATJCLR PIC32_R (0x60834) +#define LATJSET PIC32_R (0x60838) +#define LATJINV PIC32_R (0x6083C) +#define ODCJ PIC32_R (0x60840) /* Port J: open drain configuration */ +#define ODCJCLR PIC32_R (0x60844) +#define ODCJSET PIC32_R (0x60848) +#define ODCJINV PIC32_R (0x6084C) +#define CNPUJ PIC32_R (0x60850) /* Port J: input pin pull-up enable */ +#define CNPUJCLR PIC32_R (0x60854) +#define CNPUJSET PIC32_R (0x60858) +#define CNPUJINV PIC32_R (0x6085C) +#define CNPDJ PIC32_R (0x60860) /* Port J: input pin pull-down enable */ +#define CNPDJCLR PIC32_R (0x60864) +#define CNPDJSET PIC32_R (0x60868) +#define CNPDJINV PIC32_R (0x6086C) +#define CNCONJ PIC32_R (0x60870) /* Port J: interrupt-on-change control */ +#define CNCONJCLR PIC32_R (0x60874) +#define CNCONJSET PIC32_R (0x60878) +#define CNCONJINV PIC32_R (0x6087C) +#define CNENJ PIC32_R (0x60880) /* Port J: input change interrupt enable */ +#define CNENJCLR PIC32_R (0x60884) +#define CNENJSET PIC32_R (0x60888) +#define CNENJINV PIC32_R (0x6088C) +#define CNSTATJ PIC32_R (0x60890) /* Port J: status */ +#define CNSTATJCLR PIC32_R (0x60894) +#define CNSTATJSET PIC32_R (0x60898) +#define CNSTATJINV PIC32_R (0x6089C) + +#define TRISK PIC32_R (0x60910) /* Port K: mask of inputs */ +#define TRISKCLR PIC32_R (0x60914) +#define TRISKSET PIC32_R (0x60918) +#define TRISKINV PIC32_R (0x6091C) +#define PORTK PIC32_R (0x60920) /* Port K: read inputs, write outputs */ +#define PORTKCLR PIC32_R (0x60924) +#define PORTKSET PIC32_R (0x60928) +#define PORTKINV PIC32_R (0x6092C) +#define LATK PIC32_R (0x60930) /* Port K: read/write outputs */ +#define LATKCLR PIC32_R (0x60934) +#define LATKSET PIC32_R (0x60938) +#define LATKINV PIC32_R (0x6093C) +#define ODCK PIC32_R (0x60940) /* Port K: open drain configuration */ +#define ODCKCLR PIC32_R (0x60944) +#define ODCKSET PIC32_R (0x60948) +#define ODCKINV PIC32_R (0x6094C) +#define CNPUK PIC32_R (0x60950) /* Port K: input pin pull-up enable */ +#define CNPUKCLR PIC32_R (0x60954) +#define CNPUKSET PIC32_R (0x60958) +#define CNPUKINV PIC32_R (0x6095C) +#define CNPDK PIC32_R (0x60960) /* Port K: input pin pull-down enable */ +#define CNPDKCLR PIC32_R (0x60964) +#define CNPDKSET PIC32_R (0x60968) +#define CNPDKINV PIC32_R (0x6096C) +#define CNCONK PIC32_R (0x60970) /* Port K: interrupt-on-change control */ +#define CNCONKCLR PIC32_R (0x60974) +#define CNCONKSET PIC32_R (0x60978) +#define CNCONKINV PIC32_R (0x6097C) +#define CNENK PIC32_R (0x60980) /* Port K: input change interrupt enable */ +#define CNENKCLR PIC32_R (0x60984) +#define CNENKSET PIC32_R (0x60988) +#define CNENKINV PIC32_R (0x6098C) +#define CNSTATK PIC32_R (0x60990) /* Port K: status */ +#define CNSTATKCLR PIC32_R (0x60994) +#define CNSTATKSET PIC32_R (0x60998) +#define CNSTATKINV PIC32_R (0x6099C) + +/*-------------------------------------- + * Parallel master port registers. + */ +#define PMCON PIC32_R (0x2E000) /* Control */ +#define PMCONCLR PIC32_R (0x2E004) +#define PMCONSET PIC32_R (0x2E008) +#define PMCONINV PIC32_R (0x2E00C) +#define PMMODE PIC32_R (0x2E010) /* Mode */ +#define PMMODECLR PIC32_R (0x2E014) +#define PMMODESET PIC32_R (0x2E018) +#define PMMODEINV PIC32_R (0x2E01C) +#define PMADDR PIC32_R (0x2E020) /* Address */ +#define PMADDRCLR PIC32_R (0x2E024) +#define PMADDRSET PIC32_R (0x2E028) +#define PMADDRINV PIC32_R (0x2E02C) +#define PMDOUT PIC32_R (0x2E030) /* Data output */ +#define PMDOUTCLR PIC32_R (0x2E034) +#define PMDOUTSET PIC32_R (0x2E038) +#define PMDOUTINV PIC32_R (0x2E03C) +#define PMDIN PIC32_R (0x2E040) /* Data input */ +#define PMDINCLR PIC32_R (0x2E044) +#define PMDINSET PIC32_R (0x2E048) +#define PMDININV PIC32_R (0x2E04C) +#define PMAEN PIC32_R (0x2E050) /* Pin enable */ +#define PMAENCLR PIC32_R (0x2E054) +#define PMAENSET PIC32_R (0x2E058) +#define PMAENINV PIC32_R (0x2E05C) +#define PMSTAT PIC32_R (0x2E060) /* Status (slave only) */ +#define PMSTATCLR PIC32_R (0x2E064) +#define PMSTATSET PIC32_R (0x2E068) +#define PMSTATINV PIC32_R (0x2E06C) + +/* + * PMP Control register. + */ +#define PIC32_PMCON_RDSP 0x0001 /* Read strobe polarity active-high */ +#define PIC32_PMCON_WRSP 0x0002 /* Write strobe polarity active-high */ +#define PIC32_PMCON_CS1P 0x0008 /* Chip select 0 polarity active-high */ +#define PIC32_PMCON_CS2P 0x0010 /* Chip select 1 polarity active-high */ +#define PIC32_PMCON_ALP 0x0020 /* Address latch polarity active-high */ +#define PIC32_PMCON_CSF 0x00C0 /* Chip select function bitmask: */ +#define PIC32_PMCON_CSF_NONE 0x0000 /* PMCS2 and PMCS1 as A[15:14] */ +#define PIC32_PMCON_CSF_CS2 0x0040 /* PMCS2 as chip select */ +#define PIC32_PMCON_CSF_CS21 0x0080 /* PMCS2 and PMCS1 as chip select */ +#define PIC32_PMCON_PTRDEN 0x0100 /* Read/write strobe port enable */ +#define PIC32_PMCON_PTWREN 0x0200 /* Write enable strobe port enable */ +#define PIC32_PMCON_PMPTTL 0x0400 /* TTL input buffer select */ +#define PIC32_PMCON_ADRMUX 0x1800 /* Address/data mux selection bitmask: */ +#define PIC32_PMCON_ADRMUX_NONE 0x0000 /* Address and data separate */ +#define PIC32_PMCON_ADRMUX_AD 0x0800 /* Lower address on PMD[7:0], high on PMA[15:8] */ +#define PIC32_PMCON_ADRMUX_D8 0x1000 /* All address on PMD[7:0] */ +#define PIC32_PMCON_ADRMUX_D16 0x1800 /* All address on PMD[15:0] */ +#define PIC32_PMCON_SIDL 0x2000 /* Stop in idle */ +#define PIC32_PMCON_FRZ 0x4000 /* Freeze in debug exception */ +#define PIC32_PMCON_ON 0x8000 /* Parallel master port enable */ + +/* + * PMP Mode register. + */ +#define PIC32_PMMODE_WAITE(x) ((x)<<0) /* Wait states: data hold after RW strobe */ +#define PIC32_PMMODE_WAITM(x) ((x)<<2) /* Wait states: data RW strobe */ +#define PIC32_PMMODE_WAITB(x) ((x)<<6) /* Wait states: data setup to RW strobe */ +#define PIC32_PMMODE_MODE 0x0300 /* Mode select bitmask: */ +#define PIC32_PMMODE_MODE_SLAVE 0x0000 /* Legacy slave */ +#define PIC32_PMMODE_MODE_SLENH 0x0100 /* Enhanced slave */ +#define PIC32_PMMODE_MODE_MAST2 0x0200 /* Master mode 2 */ +#define PIC32_PMMODE_MODE_MAST1 0x0300 /* Master mode 1 */ +#define PIC32_PMMODE_MODE16 0x0400 /* 16-bit mode */ +#define PIC32_PMMODE_INCM 0x1800 /* Address increment mode bitmask: */ +#define PIC32_PMMODE_INCM_NONE 0x0000 /* No increment/decrement */ +#define PIC32_PMMODE_INCM_INC 0x0800 /* Increment address */ +#define PIC32_PMMODE_INCM_DEC 0x1000 /* Decrement address */ +#define PIC32_PMMODE_INCM_SLAVE 0x1800 /* Slave auto-increment */ +#define PIC32_PMMODE_IRQM 0x6000 /* Interrupt request bitmask: */ +#define PIC32_PMMODE_IRQM_DIS 0x0000 /* No interrupt generated */ +#define PIC32_PMMODE_IRQM_END 0x2000 /* Interrupt at end of read/write cycle */ +#define PIC32_PMMODE_IRQM_A3 0x4000 /* Interrupt on address 3 */ +#define PIC32_PMMODE_BUSY 0x8000 /* Port is busy */ + +/* + * PMP Address register. + */ +#define PIC32_PMADDR_PADDR 0x3FFF /* Destination address */ +#define PIC32_PMADDR_CS1 0x4000 /* Chip select 1 is active */ +#define PIC32_PMADDR_CS2 0x8000 /* Chip select 2 is active */ + +/* + * PMP status register (slave only). + */ +#define PIC32_PMSTAT_OB0E 0x0001 /* Output buffer 0 empty */ +#define PIC32_PMSTAT_OB1E 0x0002 /* Output buffer 1 empty */ +#define PIC32_PMSTAT_OB2E 0x0004 /* Output buffer 2 empty */ +#define PIC32_PMSTAT_OB3E 0x0008 /* Output buffer 3 empty */ +#define PIC32_PMSTAT_OBUF 0x0040 /* Output buffer underflow */ +#define PIC32_PMSTAT_OBE 0x0080 /* Output buffer empty */ +#define PIC32_PMSTAT_IB0F 0x0100 /* Input buffer 0 full */ +#define PIC32_PMSTAT_IB1F 0x0200 /* Input buffer 1 full */ +#define PIC32_PMSTAT_IB2F 0x0400 /* Input buffer 2 full */ +#define PIC32_PMSTAT_IB3F 0x0800 /* Input buffer 3 full */ +#define PIC32_PMSTAT_IBOV 0x4000 /* Input buffer overflow */ +#define PIC32_PMSTAT_IBF 0x8000 /* Input buffer full */ + +/*-------------------------------------- + * UART registers. + */ +#define U1MODE PIC32_R (0x22000) /* Mode */ +#define U1MODECLR PIC32_R (0x22004) +#define U1MODESET PIC32_R (0x22008) +#define U1MODEINV PIC32_R (0x2200C) +#define U1STA PIC32_R (0x22010) /* Status and control */ +#define U1STACLR PIC32_R (0x22014) +#define U1STASET PIC32_R (0x22018) +#define U1STAINV PIC32_R (0x2201C) +#define U1TXREG PIC32_R (0x22020) /* Transmit */ +#define U1RXREG PIC32_R (0x22030) /* Receive */ +#define U1BRG PIC32_R (0x22040) /* Baud rate */ +#define U1BRGCLR PIC32_R (0x22044) +#define U1BRGSET PIC32_R (0x22048) +#define U1BRGINV PIC32_R (0x2204C) + +#define U2MODE PIC32_R (0x22200) /* Mode */ +#define U2MODECLR PIC32_R (0x22204) +#define U2MODESET PIC32_R (0x22208) +#define U2MODEINV PIC32_R (0x2220C) +#define U2STA PIC32_R (0x22210) /* Status and control */ +#define U2STACLR PIC32_R (0x22214) +#define U2STASET PIC32_R (0x22218) +#define U2STAINV PIC32_R (0x2221C) +#define U2TXREG PIC32_R (0x22220) /* Transmit */ +#define U2RXREG PIC32_R (0x22230) /* Receive */ +#define U2BRG PIC32_R (0x22240) /* Baud rate */ +#define U2BRGCLR PIC32_R (0x22244) +#define U2BRGSET PIC32_R (0x22248) +#define U2BRGINV PIC32_R (0x2224C) + +#define U3MODE PIC32_R (0x22400) /* Mode */ +#define U3MODECLR PIC32_R (0x22404) +#define U3MODESET PIC32_R (0x22408) +#define U3MODEINV PIC32_R (0x2240C) +#define U3STA PIC32_R (0x22410) /* Status and control */ +#define U3STACLR PIC32_R (0x22414) +#define U3STASET PIC32_R (0x22418) +#define U3STAINV PIC32_R (0x2241C) +#define U3TXREG PIC32_R (0x22420) /* Transmit */ +#define U3RXREG PIC32_R (0x22430) /* Receive */ +#define U3BRG PIC32_R (0x22440) /* Baud rate */ +#define U3BRGCLR PIC32_R (0x22444) +#define U3BRGSET PIC32_R (0x22448) +#define U3BRGINV PIC32_R (0x2244C) + +#define U4MODE PIC32_R (0x22600) /* Mode */ +#define U4MODECLR PIC32_R (0x22604) +#define U4MODESET PIC32_R (0x22608) +#define U4MODEINV PIC32_R (0x2260C) +#define U4STA PIC32_R (0x22610) /* Status and control */ +#define U4STACLR PIC32_R (0x22614) +#define U4STASET PIC32_R (0x22618) +#define U4STAINV PIC32_R (0x2261C) +#define U4TXREG PIC32_R (0x22620) /* Transmit */ +#define U4RXREG PIC32_R (0x22630) /* Receive */ +#define U4BRG PIC32_R (0x22640) /* Baud rate */ +#define U4BRGCLR PIC32_R (0x22644) +#define U4BRGSET PIC32_R (0x22648) +#define U4BRGINV PIC32_R (0x2264C) + +#define U5MODE PIC32_R (0x22800) /* Mode */ +#define U5MODECLR PIC32_R (0x22804) +#define U5MODESET PIC32_R (0x22808) +#define U5MODEINV PIC32_R (0x2280C) +#define U5STA PIC32_R (0x22810) /* Status and control */ +#define U5STACLR PIC32_R (0x22814) +#define U5STASET PIC32_R (0x22818) +#define U5STAINV PIC32_R (0x2281C) +#define U5TXREG PIC32_R (0x22820) /* Transmit */ +#define U5RXREG PIC32_R (0x22830) /* Receive */ +#define U5BRG PIC32_R (0x22840) /* Baud rate */ +#define U5BRGCLR PIC32_R (0x22844) +#define U5BRGSET PIC32_R (0x22848) +#define U5BRGINV PIC32_R (0x2284C) + +#define U6MODE PIC32_R (0x22A00) /* Mode */ +#define U6MODECLR PIC32_R (0x22A04) +#define U6MODESET PIC32_R (0x22A08) +#define U6MODEINV PIC32_R (0x22A0C) +#define U6STA PIC32_R (0x22A10) /* Status and control */ +#define U6STACLR PIC32_R (0x22A14) +#define U6STASET PIC32_R (0x22A18) +#define U6STAINV PIC32_R (0x22A1C) +#define U6TXREG PIC32_R (0x22A20) /* Transmit */ +#define U6RXREG PIC32_R (0x22A30) /* Receive */ +#define U6BRG PIC32_R (0x22A40) /* Baud rate */ +#define U6BRGCLR PIC32_R (0x22A44) +#define U6BRGSET PIC32_R (0x22A48) +#define U6BRGINV PIC32_R (0x22A4C) + +/* + * UART Mode register. + */ +#define PIC32_UMODE_STSEL 0x0001 /* 2 Stop bits */ +#define PIC32_UMODE_PDSEL 0x0006 /* Bitmask: */ +#define PIC32_UMODE_PDSEL_8NPAR 0x0000 /* 8-bit data, no parity */ +#define PIC32_UMODE_PDSEL_8EVEN 0x0002 /* 8-bit data, even parity */ +#define PIC32_UMODE_PDSEL_8ODD 0x0004 /* 8-bit data, odd parity */ +#define PIC32_UMODE_PDSEL_9NPAR 0x0006 /* 9-bit data, no parity */ +#define PIC32_UMODE_BRGH 0x0008 /* High Baud Rate Enable */ +#define PIC32_UMODE_RXINV 0x0010 /* Receive Polarity Inversion */ +#define PIC32_UMODE_ABAUD 0x0020 /* Auto-Baud Enable */ +#define PIC32_UMODE_LPBACK 0x0040 /* UARTx Loopback Mode */ +#define PIC32_UMODE_WAKE 0x0080 /* Wake-up on start bit during Sleep Mode */ +#define PIC32_UMODE_UEN 0x0300 /* Bitmask: */ +#define PIC32_UMODE_UEN_RTS 0x0100 /* Using UxRTS pin */ +#define PIC32_UMODE_UEN_RTSCTS 0x0200 /* Using UxCTS and UxRTS pins */ +#define PIC32_UMODE_UEN_BCLK 0x0300 /* Using UxBCLK pin */ +#define PIC32_UMODE_RTSMD 0x0800 /* UxRTS Pin Simplex mode */ +#define PIC32_UMODE_IREN 0x1000 /* IrDA Encoder and Decoder Enable bit */ +#define PIC32_UMODE_SIDL 0x2000 /* Stop in Idle Mode */ +#define PIC32_UMODE_FRZ 0x4000 /* Freeze in Debug Exception Mode */ +#define PIC32_UMODE_ON 0x8000 /* UART Enable */ + +/* + * UART Control and status register. + */ +#define PIC32_USTA_URXDA 0x00000001 /* Receive Data Available (read-only) */ +#define PIC32_USTA_OERR 0x00000002 /* Receive Buffer Overrun */ +#define PIC32_USTA_FERR 0x00000004 /* Framing error detected (read-only) */ +#define PIC32_USTA_PERR 0x00000008 /* Parity error detected (read-only) */ +#define PIC32_USTA_RIDLE 0x00000010 /* Receiver is idle (read-only) */ +#define PIC32_USTA_ADDEN 0x00000020 /* Address Detect mode */ +#define PIC32_USTA_URXISEL 0x000000C0 /* Bitmask: receive interrupt is set when... */ +#define PIC32_USTA_URXISEL_NEMP 0x00000000 /* ...receive buffer is not empty */ +#define PIC32_USTA_URXISEL_HALF 0x00000040 /* ...receive buffer becomes 1/2 full */ +#define PIC32_USTA_URXISEL_3_4 0x00000080 /* ...receive buffer becomes 3/4 full */ +#define PIC32_USTA_TRMT 0x00000100 /* Transmit shift register is empty (read-only) */ +#define PIC32_USTA_UTXBF 0x00000200 /* Transmit buffer is full (read-only) */ +#define PIC32_USTA_UTXEN 0x00000400 /* Transmit Enable */ +#define PIC32_USTA_UTXBRK 0x00000800 /* Transmit Break */ +#define PIC32_USTA_URXEN 0x00001000 /* Receiver Enable */ +#define PIC32_USTA_UTXINV 0x00002000 /* Transmit Polarity Inversion */ +#define PIC32_USTA_UTXISEL 0x0000C000 /* Bitmask: TX interrupt is generated when... */ +#define PIC32_USTA_UTXISEL_1 0x00000000 /* ...the transmit buffer contains at least one empty space */ +#define PIC32_USTA_UTXISEL_ALL 0x00004000 /* ...all characters have been transmitted */ +#define PIC32_USTA_UTXISEL_EMP 0x00008000 /* ...the transmit buffer becomes empty */ +#define PIC32_USTA_ADDR 0x00FF0000 /* Automatic Address Mask */ +#define PIC32_USTA_ADM_EN 0x01000000 /* Automatic Address Detect */ + +/* + * Compute the 16-bit baud rate divisor, given + * the bus frequency and baud rate. + * Round to the nearest integer. + */ +#define PIC32_BRG_BAUD(fr,bd) ((((fr)/8 + (bd)) / (bd) / 2) - 1) + +/*-------------------------------------- + * Peripheral port select registers. + */ +#define INT1R PIC32_R (0x1404) +#define INT2R PIC32_R (0x1408) +#define INT3R PIC32_R (0x140C) +#define INT4R PIC32_R (0x1410) +#define T2CKR PIC32_R (0x1418) +#define T3CKR PIC32_R (0x141C) +#define T4CKR PIC32_R (0x1420) +#define T5CKR PIC32_R (0x1424) +#define T6CKR PIC32_R (0x1428) +#define T7CKR PIC32_R (0x142C) +#define T8CKR PIC32_R (0x1430) +#define T9CKR PIC32_R (0x1434) +#define IC1R PIC32_R (0x1438) +#define IC2R PIC32_R (0x143C) +#define IC3R PIC32_R (0x1440) +#define IC4R PIC32_R (0x1444) +#define IC5R PIC32_R (0x1448) +#define IC6R PIC32_R (0x144C) +#define IC7R PIC32_R (0x1450) +#define IC8R PIC32_R (0x1454) +#define IC9R PIC32_R (0x1458) +#define OCFAR PIC32_R (0x1460) +#define U1RXR PIC32_R (0x1468) +#define U1CTSR PIC32_R (0x146C) +#define U2RXR PIC32_R (0x1470) +#define U2CTSR PIC32_R (0x1474) +#define U3RXR PIC32_R (0x1478) +#define U3CTSR PIC32_R (0x147C) +#define U4RXR PIC32_R (0x1480) +#define U4CTSR PIC32_R (0x1484) +#define U5RXR PIC32_R (0x1488) +#define U5CTSR PIC32_R (0x148C) +#define U6RXR PIC32_R (0x1490) +#define U6CTSR PIC32_R (0x1494) +#define SDI1R PIC32_R (0x149C) +#define SS1R PIC32_R (0x14A0) +#define SDI2R PIC32_R (0x14A8) +#define SS2R PIC32_R (0x14AC) +#define SDI3R PIC32_R (0x14B4) +#define SS3R PIC32_R (0x14B8) +#define SDI4R PIC32_R (0x14C0) +#define SS4R PIC32_R (0x14C4) +#define SDI5R PIC32_R (0x14CC) +#define SS5R PIC32_R (0x14D0) +#define SDI6R PIC32_R (0x14D8) +#define SS6R PIC32_R (0x14DC) +#define C1RXR PIC32_R (0x14E0) +#define C2RXR PIC32_R (0x14E4) +#define REFCLKI1R PIC32_R (0x14E8) +#define REFCLKI3R PIC32_R (0x14F0) +#define REFCLKI4R PIC32_R (0x14F4) + +#define RPA14R PIC32_R (0x1538) +#define RPA15R PIC32_R (0x153C) +#define RPB0R PIC32_R (0x1540) +#define RPB1R PIC32_R (0x1544) +#define RPB2R PIC32_R (0x1548) +#define RPB3R PIC32_R (0x154C) +#define RPB5R PIC32_R (0x1554) +#define RPB6R PIC32_R (0x1558) +#define RPB7R PIC32_R (0x155C) +#define RPB8R PIC32_R (0x1560) +#define RPB9R PIC32_R (0x1564) +#define RPB10R PIC32_R (0x1568) +#define RPB14R PIC32_R (0x1578) +#define RPB15R PIC32_R (0x157C) +#define RPC1R PIC32_R (0x1584) +#define RPC2R PIC32_R (0x1588) +#define RPC3R PIC32_R (0x158C) +#define RPC4R PIC32_R (0x1590) +#define RPC13R PIC32_R (0x15B4) +#define RPC14R PIC32_R (0x15B8) +#define RPD0R PIC32_R (0x15C0) +#define RPD1R PIC32_R (0x15C4) +#define RPD2R PIC32_R (0x15C8) +#define RPD3R PIC32_R (0x15CC) +#define RPD4R PIC32_R (0x15D0) +#define RPD5R PIC32_R (0x15D4) +#define RPD6R PIC32_R (0x15D8) +#define RPD7R PIC32_R (0x15DC) +#define RPD9R PIC32_R (0x15E4) +#define RPD10R PIC32_R (0x15E8) +#define RPD11R PIC32_R (0x15EC) +#define RPD12R PIC32_R (0x15F0) +#define RPD14R PIC32_R (0x15F8) +#define RPD15R PIC32_R (0x15FC) +#define RPE3R PIC32_R (0x160C) +#define RPE5R PIC32_R (0x1614) +#define RPE8R PIC32_R (0x1620) +#define RPE9R PIC32_R (0x1624) +#define RPF0R PIC32_R (0x1640) +#define RPF1R PIC32_R (0x1644) +#define RPF2R PIC32_R (0x1648) +#define RPF3R PIC32_R (0x164C) +#define RPF4R PIC32_R (0x1650) +#define RPF5R PIC32_R (0x1654) +#define RPF8R PIC32_R (0x1660) +#define RPF12R PIC32_R (0x1670) +#define RPF13R PIC32_R (0x1674) +#define RPG0R PIC32_R (0x1680) +#define RPG1R PIC32_R (0x1684) +#define RPG6R PIC32_R (0x1698) +#define RPG7R PIC32_R (0x169C) +#define RPG8R PIC32_R (0x16A0) +#define RPG9R PIC32_R (0x16A4) + +/*-------------------------------------- + * Prefetch cache controller registers. + */ +#define PRECON PIC32_R (0xe0000) /* Prefetch cache control */ +#define PRECONCLR PIC32_R (0xe0004) +#define PRECONSET PIC32_R (0xe0008) +#define PRECONINV PIC32_R (0xe000C) +#define PRESTAT PIC32_R (0xe0010) /* Prefetch status */ +#define PRESTATCLR PIC32_R (0xe0014) +#define PRESTATSET PIC32_R (0xe0018) +#define PRESTATINV PIC32_R (0xe001C) +// TODO: other prefetch registers + +/*-------------------------------------- + * System controller registers. + */ +#define CFGCON PIC32_R (0x0000) +#define DEVID PIC32_R (0x0020) +#define SYSKEY PIC32_R (0x0030) +#define CFGEBIA PIC32_R (0x00c0) +#define CFGEBIACLR PIC32_R (0x00c4) +#define CFGEBIASET PIC32_R (0x00c8) +#define CFGEBIAINV PIC32_R (0x00cc) +#define CFGEBIC PIC32_R (0x00d0) +#define CFGEBICCLR PIC32_R (0x00d4) +#define CFGEBICSET PIC32_R (0x00d8) +#define CFGEBICINV PIC32_R (0x00dc) +#define CFGPG PIC32_R (0x00e0) + +#define OSCCON PIC32_R (0x1200) /* Oscillator Control */ +#define OSCTUN PIC32_R (0x1210) +#define SPLLCON PIC32_R (0x1220) +#define RCON PIC32_R (0x1240) +#define RSWRST PIC32_R (0x1250) +#define RSWRSTCLR PIC32_R (0x1254) +#define RSWRSTSET PIC32_R (0x1258) +#define RSWRSTINV PIC32_R (0x125c) +#define RNMICON PIC32_R (0x1260) +#define PWRCON PIC32_R (0x1270) +#define REFO1CON PIC32_R (0x1280) +#define REFO1TRIM PIC32_R (0x1290) +#define REFO2CON PIC32_R (0x12A0) +#define REFO2TRIM PIC32_R (0x12B0) +#define REFO3CON PIC32_R (0x12C0) +#define REFO3TRIM PIC32_R (0x12D0) +#define REFO4CON PIC32_R (0x12E0) +#define REFO4TRIM PIC32_R (0x12F0) +#define PB1DIV PIC32_R (0x1300) +#define PB2DIV PIC32_R (0x1310) +#define PB3DIV PIC32_R (0x1320) +#define PB4DIV PIC32_R (0x1330) +#define PB5DIV PIC32_R (0x1340) +#define PB7DIV PIC32_R (0x1360) +#define PB8DIV PIC32_R (0x1370) + +/* + * Configuration Control register. + */ +#define PIC32_CFGCON_DMAPRI 0x02000000 /* DMA gets High Priority access to SRAM */ +#define PIC32_CFGCON_CPUPRI 0x01000000 /* CPU gets High Priority access to SRAM */ +#define PIC32_CFGCON_ICACLK 0x00020000 /* Input Capture alternate clock selection */ +#define PIC32_CFGCON_OCACLK 0x00010000 /* Output Compare alternate clock selection */ +#define PIC32_CFGCON_IOLOCK 0x00002000 /* Peripheral pin select lock */ +#define PIC32_CFGCON_PMDLOCK 0x00001000 /* Peripheral module disable */ +#define PIC32_CFGCON_PGLOCK 0x00000800 /* Permission group lock */ +#define PIC32_CFGCON_USBSSEN 0x00000100 /* USB suspend sleep enable */ +#define PIC32_CFGCON_ECC_MASK 0x00000030 /* Flash ECC Configuration */ +#define PIC32_CFGCON_ECC_DISWR 0x00000030 /* ECC disabled, ECCCON<1:0> writable */ +#define PIC32_CFGCON_ECC_DISRO 0x00000020 /* ECC disabled, ECCCON<1:0> locked */ +#define PIC32_CFGCON_ECC_DYN 0x00000010 /* Dynamic Flash ECC is enabled */ +#define PIC32_CFGCON_ECC_EN 0x00000000 /* Flash ECC is enabled */ +#define PIC32_CFGCON_JTAGEN 0x00000008 /* JTAG port enable */ +#define PIC32_CFGCON_TROEN 0x00000004 /* Trace output enable */ +#define PIC32_CFGCON_TDOEN 0x00000001 /* 2-wire JTAG protocol uses TDO */ + +/*-------------------------------------- + * A/D Converter registers. + */ +#define AD1CON1 PIC32_R (0x4b000) /* Control register 1 */ +#define AD1CON2 PIC32_R (0x4b004) /* Control register 2 */ +#define AD1CON3 PIC32_R (0x4b008) /* Control register 3 */ +#define AD1IMOD PIC32_R (0x4b00c) +#define AD1GIRQEN1 PIC32_R (0x4b010) +#define AD1GIRQEN2 PIC32_R (0x4b014) +#define AD1CSS1 PIC32_R (0x4b018) +#define AD1CSS2 PIC32_R (0x4b01c) +#define AD1DSTAT1 PIC32_R (0x4b020) +#define AD1DSTAT2 PIC32_R (0x4b024) +#define AD1CMPEN1 PIC32_R (0x4b028) +#define AD1CMP1 PIC32_R (0x4b02c) +#define AD1CMPEN2 PIC32_R (0x4b030) +#define AD1CMP2 PIC32_R (0x4b034) +#define AD1CMPEN3 PIC32_R (0x4b038) +#define AD1CMP3 PIC32_R (0x4b03c) +#define AD1CMPEN4 PIC32_R (0x4b040) +#define AD1CMP4 PIC32_R (0x4b044) +#define AD1CMPEN5 PIC32_R (0x4b048) +#define AD1CMP5 PIC32_R (0x4b04c) +#define AD1CMPEN6 PIC32_R (0x4b050) +#define AD1CMP6 PIC32_R (0x4b054) +#define AD1FLTR1 PIC32_R (0x4b058) +#define AD1FLTR2 PIC32_R (0x4b05c) +#define AD1FLTR3 PIC32_R (0x4b060) +#define AD1FLTR4 PIC32_R (0x4b064) +#define AD1FLTR5 PIC32_R (0x4b068) +#define AD1FLTR6 PIC32_R (0x4b06c) +#define AD1TRG1 PIC32_R (0x4b070) +#define AD1TRG2 PIC32_R (0x4b074) +#define AD1TRG3 PIC32_R (0x4b078) +#define AD1CMPCON1 PIC32_R (0x4b090) +#define AD1CMPCON2 PIC32_R (0x4b094) +#define AD1CMPCON3 PIC32_R (0x4b098) +#define AD1CMPCON4 PIC32_R (0x4b09c) +#define AD1CMPCON5 PIC32_R (0x4b0a0) +#define AD1CMPCON6 PIC32_R (0x4b0a4) +#define AD1DATA0 PIC32_R (0x4b0b8) +#define AD1DATA1 PIC32_R (0x4b0bc) +#define AD1DATA2 PIC32_R (0x4b0c0) +#define AD1DATA3 PIC32_R (0x4b0c4) +#define AD1DATA4 PIC32_R (0x4b0c8) +#define AD1DATA5 PIC32_R (0x4b0cc) +#define AD1DATA6 PIC32_R (0x4b0d0) +#define AD1DATA7 PIC32_R (0x4b0d4) +#define AD1DATA8 PIC32_R (0x4b0d8) +#define AD1DATA9 PIC32_R (0x4b0dc) +#define AD1DATA10 PIC32_R (0x4b0e0) +#define AD1DATA11 PIC32_R (0x4b0e4) +#define AD1DATA12 PIC32_R (0x4b0e8) +#define AD1DATA13 PIC32_R (0x4b0ec) +#define AD1DATA14 PIC32_R (0x4b0f0) +#define AD1DATA15 PIC32_R (0x4b0f4) +#define AD1DATA16 PIC32_R (0x4b0f8) +#define AD1DATA17 PIC32_R (0x4b0fc) +#define AD1DATA18 PIC32_R (0x4b100) +#define AD1DATA19 PIC32_R (0x4b104) +#define AD1DATA20 PIC32_R (0x4b108) +#define AD1DATA21 PIC32_R (0x4b10c) +#define AD1DATA22 PIC32_R (0x4b110) +#define AD1DATA23 PIC32_R (0x4b114) +#define AD1DATA24 PIC32_R (0x4b118) +#define AD1DATA25 PIC32_R (0x4b11c) +#define AD1DATA26 PIC32_R (0x4b120) +#define AD1DATA27 PIC32_R (0x4b124) +#define AD1DATA28 PIC32_R (0x4b128) +#define AD1DATA29 PIC32_R (0x4b12c) +#define AD1DATA30 PIC32_R (0x4b130) +#define AD1DATA31 PIC32_R (0x4b134) +#define AD1DATA32 PIC32_R (0x4b138) +#define AD1DATA33 PIC32_R (0x4b13c) +#define AD1DATA34 PIC32_R (0x4b140) +#define AD1DATA35 PIC32_R (0x4b144) +#define AD1DATA36 PIC32_R (0x4b148) +#define AD1DATA37 PIC32_R (0x4b14c) +#define AD1DATA38 PIC32_R (0x4b150) +#define AD1DATA39 PIC32_R (0x4b154) +#define AD1DATA40 PIC32_R (0x4b158) +#define AD1DATA41 PIC32_R (0x4b15c) +#define AD1DATA42 PIC32_R (0x4b160) +#define AD1DATA43 PIC32_R (0x4b164) +#define AD1DATA44 PIC32_R (0x4b168) +#define AD1CAL1 PIC32_R (0x4b200) /* Calibration Data */ +#define AD1CAL2 PIC32_R (0x4b204) +#define AD1CAL3 PIC32_R (0x4b208) +#define AD1CAL4 PIC32_R (0x4b20c) +#define AD1CAL5 PIC32_R (0x4b210) + +/*-------------------------------------- + * SPI registers. + */ +#define SPI1CON PIC32_R (0x21000) /* Control */ +#define SPI1CONCLR PIC32_R (0x21004) +#define SPI1CONSET PIC32_R (0x21008) +#define SPI1CONINV PIC32_R (0x2100c) +#define SPI1STAT PIC32_R (0x21010) /* Status */ +#define SPI1STATCLR PIC32_R (0x21014) +#define SPI1STATSET PIC32_R (0x21018) +#define SPI1STATINV PIC32_R (0x2101c) +#define SPI1BUF PIC32_R (0x21020) /* Transmit and receive buffer */ +#define SPI1BRG PIC32_R (0x21030) /* Baud rate generator */ +#define SPI1BRGCLR PIC32_R (0x21034) +#define SPI1BRGSET PIC32_R (0x21038) +#define SPI1BRGINV PIC32_R (0x2103c) +#define SPI1CON2 PIC32_R (0x21040) /* Control 2 */ +#define SPI1CON2CLR PIC32_R (0x21044) +#define SPI1CON2SET PIC32_R (0x21048) +#define SPI1CON2INV PIC32_R (0x2104c) + +#define SPI2CON PIC32_R (0x21200) /* Control */ +#define SPI2CONCLR PIC32_R (0x21204) +#define SPI2CONSET PIC32_R (0x21208) +#define SPI2CONINV PIC32_R (0x2120c) +#define SPI2STAT PIC32_R (0x21210) /* Status */ +#define SPI2STATCLR PIC32_R (0x21214) +#define SPI2STATSET PIC32_R (0x21218) +#define SPI2STATINV PIC32_R (0x2121c) +#define SPI2BUF PIC32_R (0x21220) /* Transmit and receive buffer */ +#define SPI2BRG PIC32_R (0x21230) /* Baud rate generator */ +#define SPI2BRGCLR PIC32_R (0x21234) +#define SPI2BRGSET PIC32_R (0x21238) +#define SPI2BRGINV PIC32_R (0x2123c) +#define SPI2CON2 PIC32_R (0x21240) /* Control 2 */ +#define SPI2CON2CLR PIC32_R (0x21244) +#define SPI2CON2SET PIC32_R (0x21248) +#define SPI2CON2INV PIC32_R (0x2124c) + +#define SPI3CON PIC32_R (0x21400) /* Control */ +#define SPI3CONCLR PIC32_R (0x21404) +#define SPI3CONSET PIC32_R (0x21408) +#define SPI3CONINV PIC32_R (0x2140c) +#define SPI3STAT PIC32_R (0x21410) /* Status */ +#define SPI3STATCLR PIC32_R (0x21414) +#define SPI3STATSET PIC32_R (0x21418) +#define SPI3STATINV PIC32_R (0x2141c) +#define SPI3BUF PIC32_R (0x21420) /* Transmit and receive buffer */ +#define SPI3BRG PIC32_R (0x21430) /* Baud rate generator */ +#define SPI3BRGCLR PIC32_R (0x21434) +#define SPI3BRGSET PIC32_R (0x21438) +#define SPI3BRGINV PIC32_R (0x2143c) +#define SPI3CON2 PIC32_R (0x21440) /* Control 2 */ +#define SPI3CON2CLR PIC32_R (0x21444) +#define SPI3CON2SET PIC32_R (0x21448) +#define SPI3CON2INV PIC32_R (0x2144c) + +#define SPI4CON PIC32_R (0x21600) /* Control */ +#define SPI4CONCLR PIC32_R (0x21604) +#define SPI4CONSET PIC32_R (0x21608) +#define SPI4CONINV PIC32_R (0x2160c) +#define SPI4STAT PIC32_R (0x21610) /* Status */ +#define SPI4STATCLR PIC32_R (0x21614) +#define SPI4STATSET PIC32_R (0x21618) +#define SPI4STATINV PIC32_R (0x2161c) +#define SPI4BUF PIC32_R (0x21620) /* Transmit and receive buffer */ +#define SPI4BRG PIC32_R (0x21630) /* Baud rate generator */ +#define SPI4BRGCLR PIC32_R (0x21634) +#define SPI4BRGSET PIC32_R (0x21638) +#define SPI4BRGINV PIC32_R (0x2163c) +#define SPI4CON2 PIC32_R (0x21640) /* Control 2 */ +#define SPI4CON2CLR PIC32_R (0x21644) +#define SPI4CON2SET PIC32_R (0x21648) +#define SPI4CON2INV PIC32_R (0x2164c) + +#define SPI5CON PIC32_R (0x21800) /* Control */ +#define SPI5CONCLR PIC32_R (0x21804) +#define SPI5CONSET PIC32_R (0x21808) +#define SPI5CONINV PIC32_R (0x2180c) +#define SPI5STAT PIC32_R (0x21810) /* Status */ +#define SPI5STATCLR PIC32_R (0x21814) +#define SPI5STATSET PIC32_R (0x21818) +#define SPI5STATINV PIC32_R (0x2181c) +#define SPI5BUF PIC32_R (0x21820) /* Transmit and receive buffer */ +#define SPI5BRG PIC32_R (0x21830) /* Baud rate generator */ +#define SPI5BRGCLR PIC32_R (0x21834) +#define SPI5BRGSET PIC32_R (0x21838) +#define SPI5BRGINV PIC32_R (0x2183c) +#define SPI5CON2 PIC32_R (0x21840) /* Control 2 */ +#define SPI5CON2CLR PIC32_R (0x21844) +#define SPI5CON2SET PIC32_R (0x21848) +#define SPI5CON2INV PIC32_R (0x2184c) + +#define SPI6CON PIC32_R (0x21a00) /* Control */ +#define SPI6CONCLR PIC32_R (0x21a04) +#define SPI6CONSET PIC32_R (0x21a08) +#define SPI6CONINV PIC32_R (0x21a0c) +#define SPI6STAT PIC32_R (0x21a10) /* Status */ +#define SPI6STATCLR PIC32_R (0x21a14) +#define SPI6STATSET PIC32_R (0x21a18) +#define SPI6STATINV PIC32_R (0x21a1c) +#define SPI6BUF PIC32_R (0x21a20) /* Transmit and receive buffer */ +#define SPI6BRG PIC32_R (0x21a30) /* Baud rate generator */ +#define SPI6BRGCLR PIC32_R (0x21a34) +#define SPI6BRGSET PIC32_R (0x21a38) +#define SPI6BRGINV PIC32_R (0x21a3c) +#define SPI6CON2 PIC32_R (0x21a40) /* Control 2 */ +#define SPI6CON2CLR PIC32_R (0x21a44) +#define SPI6CON2SET PIC32_R (0x21a48) +#define SPI6CON2INV PIC32_R (0x21a4c) + +/* + * SPI Control register. + */ +#define PIC32_SPICON_MSTEN 0x00000020 /* Master mode */ +#define PIC32_SPICON_CKP 0x00000040 /* Idle clock is high level */ +#define PIC32_SPICON_SSEN 0x00000080 /* Slave mode: SSx pin enable */ +#define PIC32_SPICON_CKE 0x00000100 /* Output data changes on + * transition from active clock + * state to Idle clock state */ +#define PIC32_SPICON_SMP 0x00000200 /* Master mode: input data sampled + * at end of data output time. */ +#define PIC32_SPICON_MODE16 0x00000400 /* 16-bit data width */ +#define PIC32_SPICON_MODE32 0x00000800 /* 32-bit data width */ +#define PIC32_SPICON_DISSDO 0x00001000 /* SDOx pin is not used */ +#define PIC32_SPICON_SIDL 0x00002000 /* Stop in Idle mode */ +#define PIC32_SPICON_FRZ 0x00004000 /* Freeze in Debug mode */ +#define PIC32_SPICON_ON 0x00008000 /* SPI Peripheral is enabled */ +#define PIC32_SPICON_ENHBUF 0x00010000 /* Enhanced buffer enable */ +#define PIC32_SPICON_SPIFE 0x00020000 /* Frame synchronization pulse + * coincides with the first bit clock */ +#define PIC32_SPICON_FRMPOL 0x20000000 /* Frame pulse is active-high */ +#define PIC32_SPICON_FRMSYNC 0x40000000 /* Frame sync pulse input (Slave mode) */ +#define PIC32_SPICON_FRMEN 0x80000000 /* Framed SPI support */ + +/* + * SPI Status register. + */ +#define PIC32_SPISTAT_SPIRBF 0x00000001 /* Receive buffer is full */ +#define PIC32_SPISTAT_SPITBF 0x00000002 /* Transmit buffer is full */ +#define PIC32_SPISTAT_SPITBE 0x00000008 /* Transmit buffer is empty */ +#define PIC32_SPISTAT_SPIRBE 0x00000020 /* Receive buffer is empty */ +#define PIC32_SPISTAT_SPIROV 0x00000040 /* Receive overflow flag */ +#define PIC32_SPISTAT_SPIBUSY 0x00000800 /* SPI is busy */ + +/*-------------------------------------- + * Ethernet registers. + */ +#define ETHCON1 PIC32_R (0x82000) /* Control 1 */ +#define ETHCON1CLR PIC32_R (0x82004) +#define ETHCON1SET PIC32_R (0x82008) +#define ETHCON1INV PIC32_R (0x8200c) +#define ETHCON2 PIC32_R (0x82010) /* Control 2: RX data buffer size */ +#define ETHTXST PIC32_R (0x82020) /* Tx descriptor start address */ +#define ETHRXST PIC32_R (0x82030) /* Rx descriptor start address */ +#define ETHHT0 PIC32_R (0x82040) /* Hash tasble 0 */ +#define ETHHT1 PIC32_R (0x82050) /* Hash tasble 1 */ +#define ETHPMM0 PIC32_R (0x82060) /* Pattern match mask 0 */ +#define ETHPMM1 PIC32_R (0x82070) /* Pattern match mask 1 */ +#define ETHPMCS PIC32_R (0x82080) /* Pattern match checksum */ +#define ETHPMO PIC32_R (0x82090) /* Pattern match offset */ +#define ETHRXFC PIC32_R (0x820a0) /* Receive filter configuration */ +#define ETHRXWM PIC32_R (0x820b0) /* Receive watermarks */ +#define ETHIEN PIC32_R (0x820c0) /* Interrupt enable */ +#define ETHIENCLR PIC32_R (0x820c4) +#define ETHIENSET PIC32_R (0x820c8) +#define ETHIENINV PIC32_R (0x820cc) +#define ETHIRQ PIC32_R (0x820d0) /* Interrupt request */ +#define ETHIRQCLR PIC32_R (0x820d4) +#define ETHIRQSET PIC32_R (0x820d8) +#define ETHIRQINV PIC32_R (0x820dc) +#define ETHSTAT PIC32_R (0x820e0) /* Status */ +#define ETHRXOVFLOW PIC32_R (0x82100) /* Receive overflow statistics */ +#define ETHFRMTXOK PIC32_R (0x82110) /* Frames transmitted OK statistics */ +#define ETHSCOLFRM PIC32_R (0x82120) /* Single collision frames statistics */ +#define ETHMCOLFRM PIC32_R (0x82130) /* Multiple collision frames statistics */ +#define ETHFRMRXOK PIC32_R (0x82140) /* Frames received OK statistics */ +#define ETHFCSERR PIC32_R (0x82150) /* Frame check sequence error statistics */ +#define ETHALGNERR PIC32_R (0x82160) /* Alignment errors statistics */ +#define EMAC1CFG1 PIC32_R (0x82200) /* MAC configuration 1 */ +#define EMAC1CFG2 PIC32_R (0x82210) /* MAC configuration 2 */ +#define EMAC1CFG2CLR PIC32_R (0x82214) +#define EMAC1CFG2SET PIC32_R (0x82218) +#define EMAC1CFG2INV PIC32_R (0x8221c) +#define EMAC1IPGT PIC32_R (0x82220) /* MAC back-to-back interpacket gap */ +#define EMAC1IPGR PIC32_R (0x82230) /* MAC non-back-to-back interpacket gap */ +#define EMAC1CLRT PIC32_R (0x82240) /* MAC collision window/retry limit */ +#define EMAC1MAXF PIC32_R (0x82250) /* MAC maximum frame length */ +#define EMAC1SUPP PIC32_R (0x82260) /* MAC PHY support */ +#define EMAC1SUPPCLR PIC32_R (0x82264) +#define EMAC1SUPPSET PIC32_R (0x82268) +#define EMAC1SUPPINV PIC32_R (0x8226c) +#define EMAC1TEST PIC32_R (0x82270) /* MAC test */ +#define EMAC1MCFG PIC32_R (0x82280) /* MII configuration */ +#define EMAC1MCMD PIC32_R (0x82290) /* MII command */ +#define EMAC1MCMDCLR PIC32_R (0x82294) +#define EMAC1MCMDSET PIC32_R (0x82298) +#define EMAC1MCMDINV PIC32_R (0x8229c) +#define EMAC1MADR PIC32_R (0x822a0) /* MII address */ +#define EMAC1MWTD PIC32_R (0x822b0) /* MII write data */ +#define EMAC1MRDD PIC32_R (0x822c0) /* MII read data */ +#define EMAC1MIND PIC32_R (0x822d0) /* MII indicators */ +#define EMAC1SA0 PIC32_R (0x82300) /* MAC station address 0 */ +#define EMAC1SA1 PIC32_R (0x82310) /* MAC station address 1 */ +#define EMAC1SA2 PIC32_R (0x82320) /* MAC station address 2 */ + +/* + * Ethernet Control register 1. + */ +#define PIC32_ETHCON1_PTV(n) ((n)<<16) /* Pause timer value */ +#define PIC32_ETHCON1_ON 0x8000 /* Ethernet module enabled */ +#define PIC32_ETHCON1_SIDL 0x2000 /* Stop in idle mode */ +#define PIC32_ETHCON1_TXRTS 0x0200 /* Transmit request to send */ +#define PIC32_ETHCON1_RXEN 0x0100 /* Receive enable */ +#define PIC32_ETHCON1_AUTOFC 0x0080 /* Automatic flow control */ +#define PIC32_ETHCON1_MANFC 0x0010 /* Manual flow control */ +#define PIC32_ETHCON1_BUFCDEC 0x0001 /* Descriptor buffer count decrement */ + +/* + * Ethernet Receive Filter Configuration register. + */ +#define PIC32_ETHRXFC_HTEN 0x8000 /* Enable hash table filtering */ +#define PIC32_ETHRXFC_MPEN 0x4000 /* Enable Magic Packet filtering */ +#define PIC32_ETHRXFC_NOTPM 0x1000 /* Pattern match inversion */ +#define PIC32_ETHRXFC_PMMODE_MAGIC 0x0900 /* Packet = magic */ +#define PIC32_ETHRXFC_PMMODE_HT 0x0800 /* Hash table filter match */ +#define PIC32_ETHRXFC_PMMODE_BCAST 0x0600 /* Destination = broadcast address */ +#define PIC32_ETHRXFC_PMMODE_UCAST 0x0400 /* Destination = unicast address */ +#define PIC32_ETHRXFC_PMMODE_STN 0x0200 /* Destination = station address */ +#define PIC32_ETHRXFC_PMMODE_CSUM 0x0100 /* Successful if checksum matches */ +#define PIC32_ETHRXFC_CRCERREN 0x0080 /* CRC error collection enable */ +#define PIC32_ETHRXFC_CRCOKEN 0x0040 /* CRC OK enable */ +#define PIC32_ETHRXFC_RUNTERREN 0x0020 /* Runt error collection enable */ +#define PIC32_ETHRXFC_RUNTEN 0x0010 /* Runt filter enable */ +#define PIC32_ETHRXFC_UCEN 0x0008 /* Unicast filter enable */ +#define PIC32_ETHRXFC_NOTMEEN 0x0004 /* Not Me unicast enable */ +#define PIC32_ETHRXFC_MCEN 0x0002 /* Multicast filter enable */ +#define PIC32_ETHRXFC_BCEN 0x0001 /* Broadcast filter enable */ + +/* + * Ethernet Receive Watermarks register. + */ +#define PIC32_ETHRXWM_FWM(n) ((n)<<16) /* Receive Full Watermark */ +#define PIC32_ETHRXWM_EWM(n) (n) /* Receive Empty Watermark */ + +/* + * Ethernet Interrupt Request register. + */ +#define PIC32_ETHIRQ_TXBUSE 0x4000 /* Transmit Bus Error */ +#define PIC32_ETHIRQ_RXBUSE 0x2000 /* Receive Bus Error */ +#define PIC32_ETHIRQ_EWMARK 0x0200 /* Empty Watermark */ +#define PIC32_ETHIRQ_FWMARK 0x0100 /* Full Watermark */ +#define PIC32_ETHIRQ_RXDONE 0x0080 /* Receive Done */ +#define PIC32_ETHIRQ_PKTPEND 0x0040 /* Packet Pending */ +#define PIC32_ETHIRQ_RXACT 0x0020 /* Receive Activity */ +#define PIC32_ETHIRQ_TXDONE 0x0008 /* Transmit Done */ +#define PIC32_ETHIRQ_TXABORT 0x0004 /* Transmitter Abort */ +#define PIC32_ETHIRQ_RXBUFNA 0x0002 /* Receive Buffer Not Available */ +#define PIC32_ETHIRQ_RXOVFLW 0x0001 /* Receive FIFO Overflow */ + +/* + * Ethernet Status register. + */ +#define PIC32_ETHSTAT_BUFCNT 0x00ff0000 /* Packet buffer count */ +#define PIC32_ETHSTAT_ETHBUSY 0x0080 /* Ethernet logic is busy */ +#define PIC32_ETHSTAT_TXBUSY 0x0040 /* TX logic is receiving data */ +#define PIC32_ETHSTAT_RXBUSY 0x0020 /* RX logic is receiving data */ + +/* + * Ethernet MAC configuration register 1. + */ +#define PIC32_EMAC1CFG1_SOFTRESET 0x8000 /* Soft reset */ +#define PIC32_EMAC1CFG1_SIMRESET 0x4000 /* Reset TX random number generator */ +#define PIC32_EMAC1CFG1_RESETRMCS 0x0800 /* Reset MCS/RX logic */ +#define PIC32_EMAC1CFG1_RESETRFUN 0x0400 /* Reset RX function */ +#define PIC32_EMAC1CFG1_RESETTMCS 0x0200 /* Reset MCS/TX logic */ +#define PIC32_EMAC1CFG1_RESETTFUN 0x0100 /* Reset TX function */ +#define PIC32_EMAC1CFG1_LOOPBACK 0x0010 /* MAC Loopback mode */ +#define PIC32_EMAC1CFG1_TXPAUSE 0x0008 /* MAC TX flow control */ +#define PIC32_EMAC1CFG1_RXPAUSE 0x0004 /* MAC RX flow control */ +#define PIC32_EMAC1CFG1_PASSALL 0x0002 /* MAC accept control frames as well */ +#define PIC32_EMAC1CFG1_RXENABLE 0x0001 /* MAC Receive Enable */ + +/* + * Ethernet MAC configuration register 2. + */ +#define PIC32_EMAC1CFG2_EXCESSDFR 0x4000 /* Defer to carrier indefinitely */ +#define PIC32_EMAC1CFG2_BPNOBKOFF 0x2000 /* Backpressure/No Backoff */ +#define PIC32_EMAC1CFG2_NOBKOFF 0x1000 /* No Backoff */ +#define PIC32_EMAC1CFG2_LONGPRE 0x0200 /* Long preamble enforcement */ +#define PIC32_EMAC1CFG2_PUREPRE 0x0100 /* Pure preamble enforcement */ +#define PIC32_EMAC1CFG2_AUTOPAD 0x0080 /* Automatic detect pad enable */ +#define PIC32_EMAC1CFG2_VLANPAD 0x0040 /* VLAN pad enable */ +#define PIC32_EMAC1CFG2_PADENABLE 0x0020 /* Pad/CRC enable */ +#define PIC32_EMAC1CFG2_CRCENABLE 0x0010 /* CRC enable */ +#define PIC32_EMAC1CFG2_DELAYCRC 0x0008 /* Delayed CRC */ +#define PIC32_EMAC1CFG2_HUGEFRM 0x0004 /* Huge frame enable */ +#define PIC32_EMAC1CFG2_LENGTHCK 0x0002 /* Frame length checking */ +#define PIC32_EMAC1CFG2_FULLDPLX 0x0001 /* Full-duplex operation */ + +/* + * Ethernet MAC non-back-to-back interpacket gap register. + */ +#define PIC32_EMAC1IPGR(p1, p2) ((p1)<<8 | (p2)) + +/* + * Ethernet MAC collision window/retry limit register. + */ +#define PIC32_EMAC1CLRT(w, r) ((w)<<8 | (r)) + +/* + * Ethernet PHY support register. + */ +#define PIC32_EMAC1SUPP_RESETRMII 0x0800 /* Reset the RMII module */ +#define PIC32_EMAC1SUPP_SPEEDRMII 0x0100 /* RMII speed: 1=100Mbps, 0=10Mbps */ + +/* + * Ethernet MAC test register. + */ +#define PIC32_EMAC1TEST_TESTBP 0x0004 /* Test backpressure */ +#define PIC32_EMAC1TEST_TESTPAUSE 0x0002 /* Test pause */ +#define PIC32_EMAC1TEST_SHRTQNTA 0x0001 /* Shortcut pause quanta */ + +/* + * Ethernet MII configuration register. + */ +#define PIC32_EMAC1MCFG_RESETMGMT 0x8000 /* Reset the MII module */ +#define PIC32_EMAC1MCFG_CLKSEL_4 0x0000 /* Clock divide by 4 */ +#define PIC32_EMAC1MCFG_CLKSEL_6 0x0008 /* Clock divide by 6 */ +#define PIC32_EMAC1MCFG_CLKSEL_8 0x000c /* Clock divide by 8 */ +#define PIC32_EMAC1MCFG_CLKSEL_10 0x0010 /* Clock divide by 10 */ +#define PIC32_EMAC1MCFG_CLKSEL_14 0x0014 /* Clock divide by 14 */ +#define PIC32_EMAC1MCFG_CLKSEL_20 0x0018 /* Clock divide by 20 */ +#define PIC32_EMAC1MCFG_CLKSEL_28 0x001c /* Clock divide by 28 */ +#define PIC32_EMAC1MCFG_CLKSEL_40 0x0020 /* Clock divide by 40 */ +#define PIC32_EMAC1MCFG_CLKSEL_48 0x0024 /* Clock divide by 48 */ +#define PIC32_EMAC1MCFG_CLKSEL_50 0x0028 /* Clock divide by 50 */ +#define PIC32_EMAC1MCFG_NOPRE 0x0002 /* Suppress preamble */ +#define PIC32_EMAC1MCFG_SCANINC 0x0001 /* Scan increment */ + +/* + * Ethernet MII command register. + */ +#define PIC32_EMAC1MCMD_SCAN 0x0002 /* Continuous scan mode */ +#define PIC32_EMAC1MCMD_READ 0x0001 /* Single read cycle */ + +/* + * Ethernet MII address register. + */ +#define PIC32_EMAC1MADR(p, r) ((p)<<8 | (r)) + +/* + * Ethernet MII indicators register. + */ +#define PIC32_EMAC1MIND_LINKFAIL 0x0008 /* Link fail */ +#define PIC32_EMAC1MIND_NOTVALID 0x0004 /* Read data not valid */ +#define PIC32_EMAC1MIND_SCAN 0x0002 /* Scanning in progress */ +#define PIC32_EMAC1MIND_MIIMBUSY 0x0001 /* Read/write cycle in progress */ + +/*-------------------------------------- + * Interrupt controller registers. + */ +#define INTCON PIC32_R (0x10000) /* Interrupt Control */ +#define INTCONCLR PIC32_R (0x10004) +#define INTCONSET PIC32_R (0x10008) +#define INTCONINV PIC32_R (0x1000C) +#define PRISS PIC32_R (0x10010) /* Priority Shadow Select */ +#define PRISSCLR PIC32_R (0x10014) +#define PRISSSET PIC32_R (0x10018) +#define PRISSINV PIC32_R (0x1001C) +#define INTSTAT PIC32_R (0x10020) /* Interrupt Status */ +#define IPTMR PIC32_R (0x10030) /* Temporal Proximity Timer */ +#define IPTMRCLR PIC32_R (0x10034) +#define IPTMRSET PIC32_R (0x10038) +#define IPTMRINV PIC32_R (0x1003C) +#define IFS(n) PIC32_R (0x10040+((n)<<4)) /* IFS(0..5) - Interrupt Flag Status */ +#define IFSCLR(n) PIC32_R (0x10044+((n)<<4)) +#define IFSSET(n) PIC32_R (0x10048+((n)<<4)) +#define IFSINV(n) PIC32_R (0x1004C+((n)<<4)) +#define IFS0 IFS(0) +#define IFS1 IFS(1) +#define IFS2 IFS(2) +#define IFS3 IFS(3) +#define IFS4 IFS(4) +#define IFS5 IFS(5) +#define IEC(n) PIC32_R (0x100c0+((n)<<4)) /* IEC(0..5) - Interrupt Enable Control */ +#define IECCLR(n) PIC32_R (0x100c4+((n)<<4)) +#define IECSET(n) PIC32_R (0x100c8+((n)<<4)) +#define IECINV(n) PIC32_R (0x100cC+((n)<<4)) +#define IEC0 IEC(0) +#define IEC1 IEC(1) +#define IEC2 IEC(2) +#define IEC3 IEC(3) +#define IEC4 IEC(4) +#define IEC5 IEC(5) +#define IPC(n) PIC32_R (0x10140+((n)<<4)) /* IPC(0..47) - Interrupt Priority Control */ +#define IPCCLR(n) PIC32_R (0x10144+((n)<<4)) +#define IPCSET(n) PIC32_R (0x10148+((n)<<4)) +#define IPCINV(n) PIC32_R (0x1014C+((n)<<4)) +#define IPC0 IPC(0) +#define IPC1 IPC(1) +#define IPC2 IPC(2) +#define IPC3 IPC(3) +#define IPC4 IPC(4) +#define IPC5 IPC(5) +#define IPC6 IPC(6) +#define IPC7 IPC(7) +#define IPC8 IPC(8) +#define IPC9 IPC(9) +#define IPC10 IPC(10) +#define IPC11 IPC(11) +#define IPC12 IPC(12) +#define IPC13 IPC(13) +#define IPC14 IPC(14) +#define IPC15 IPC(15) +#define IPC16 IPC(16) +#define IPC17 IPC(17) +#define IPC18 IPC(18) +#define IPC19 IPC(19) +#define IPC20 IPC(20) +#define IPC21 IPC(21) +#define IPC22 IPC(22) +#define IPC23 IPC(23) +#define IPC24 IPC(24) +#define IPC25 IPC(25) +#define IPC26 IPC(26) +#define IPC27 IPC(27) +#define IPC28 IPC(28) +#define IPC29 IPC(29) +#define IPC30 IPC(30) +#define IPC31 IPC(31) +#define IPC32 IPC(32) +#define IPC33 IPC(33) +#define IPC34 IPC(34) +#define IPC35 IPC(35) +#define IPC36 IPC(36) +#define IPC37 IPC(37) +#define IPC38 IPC(38) +#define IPC39 IPC(39) +#define IPC40 IPC(40) +#define IPC41 IPC(41) +#define IPC42 IPC(42) +#define IPC43 IPC(43) +#define IPC44 IPC(44) +#define IPC45 IPC(45) +#define IPC46 IPC(46) +#define IPC47 IPC(47) +#define OFF(n) PIC32_R (0x10540+((n)<<2)) /* OFF(0..190) - Interrupt Vector Address Offset */ + +/* + * Interrupt Control register. + */ +#define PIC32_INTCON_INT0EP 0x00000001 /* External interrupt 0 polarity rising edge */ +#define PIC32_INTCON_INT1EP 0x00000002 /* External interrupt 1 polarity rising edge */ +#define PIC32_INTCON_INT2EP 0x00000004 /* External interrupt 2 polarity rising edge */ +#define PIC32_INTCON_INT3EP 0x00000008 /* External interrupt 3 polarity rising edge */ +#define PIC32_INTCON_INT4EP 0x00000010 /* External interrupt 4 polarity rising edge */ +#define PIC32_INTCON_TPC(x) ((x)<<8) /* Temporal proximity group priority */ +#define PIC32_INTCON_MVEC 0x00001000 /* Multi-vectored mode */ +#define PIC32_INTCON_SS0 0x00010000 /* Single vector has a shadow register set */ +#define PIC32_INTCON_VS(x) ((x)<<16) /* Temporal proximity group priority */ + +/* + * Interrupt Status register. + */ +#define PIC32_INTSTAT_VEC(s) ((s) & 0xff) /* Interrupt vector */ +#define PIC32_INTSTAT_SRIPL(s) ((s) >> 8 & 7) /* Requested priority level */ +#define PIC32_INTSTAT_SRIPL_MASK 0x0700 + +/* + * Interrupt Prority Control register. + */ +#define PIC32_IPC_IP(a,b,c,d) ((a)<<2 | (b)<<10 | (c)<<18 | (d)<<26) /* Priority */ +#define PIC32_IPC_IS(a,b,c,d) ((a) | (b)<<8 | (c)<<16 | (d)<<24) /* Subpriority */ + +/* + * IRQ numbers for PIC32MZ + */ +#define PIC32_IRQ_CT 0 /* Core Timer Interrupt */ +#define PIC32_IRQ_CS0 1 /* Core Software Interrupt 0 */ +#define PIC32_IRQ_CS1 2 /* Core Software Interrupt 1 */ +#define PIC32_IRQ_INT0 3 /* External Interrupt 0 */ +#define PIC32_IRQ_T1 4 /* Timer1 */ +#define PIC32_IRQ_IC1E 5 /* Input Capture 1 Error */ +#define PIC32_IRQ_IC1 6 /* Input Capture 1 */ +#define PIC32_IRQ_OC1 7 /* Output Compare 1 */ +#define PIC32_IRQ_INT1 8 /* External Interrupt 1 */ +#define PIC32_IRQ_T2 9 /* Timer2 */ +#define PIC32_IRQ_IC2E 10 /* Input Capture 2 Error */ +#define PIC32_IRQ_IC2 11 /* Input Capture 2 */ +#define PIC32_IRQ_OC2 12 /* Output Compare 2 */ +#define PIC32_IRQ_INT2 13 /* External Interrupt 2 */ +#define PIC32_IRQ_T3 14 /* Timer3 */ +#define PIC32_IRQ_IC3E 15 /* Input Capture 3 Error */ +#define PIC32_IRQ_IC3 16 /* Input Capture 3 */ +#define PIC32_IRQ_OC3 17 /* Output Compare 3 */ +#define PIC32_IRQ_INT3 18 /* External Interrupt 3 */ +#define PIC32_IRQ_T4 19 /* Timer4 */ +#define PIC32_IRQ_IC4E 20 /* Input Capture 4 Error */ +#define PIC32_IRQ_IC4 21 /* Input Capture 4 */ +#define PIC32_IRQ_OC4 22 /* Output Compare 4 */ +#define PIC32_IRQ_INT4 23 /* External Interrupt 4 */ +#define PIC32_IRQ_T5 24 /* Timer5 */ +#define PIC32_IRQ_IC5E 25 /* Input Capture 5 Error */ +#define PIC32_IRQ_IC5 26 /* Input Capture 5 */ +#define PIC32_IRQ_OC5 27 /* Output Compare 5 */ +#define PIC32_IRQ_T6 28 /* Timer6 */ +#define PIC32_IRQ_IC6E 29 /* Input Capture 6 Error */ +#define PIC32_IRQ_IC6 30 /* Input Capture 6 */ +#define PIC32_IRQ_OC6 31 /* Output Compare 6 */ +#define PIC32_IRQ_T7 32 /* Timer7 */ +#define PIC32_IRQ_IC7E 33 /* Input Capture 7 Error */ +#define PIC32_IRQ_IC7 34 /* Input Capture 7 */ +#define PIC32_IRQ_OC7 35 /* Output Compare 7 */ +#define PIC32_IRQ_T8 36 /* Timer8 */ +#define PIC32_IRQ_IC8E 37 /* Input Capture 8 Error */ +#define PIC32_IRQ_IC8 38 /* Input Capture 8 */ +#define PIC32_IRQ_OC8 39 /* Output Compare 8 */ +#define PIC32_IRQ_T9 40 /* Timer9 */ +#define PIC32_IRQ_IC9E 41 /* Input Capture 9 Error */ +#define PIC32_IRQ_IC9 42 /* Input Capture 9 */ +#define PIC32_IRQ_OC9 43 /* Output Compare 9 */ +#define PIC32_IRQ_AD1 44 /* ADC1 Global Interrupt */ + /* 45 -- Reserved */ +#define PIC32_IRQ_AD1DC1 46 /* ADC1 Digital Comparator 1 */ +#define PIC32_IRQ_AD1DC2 47 /* ADC1 Digital Comparator 2 */ +#define PIC32_IRQ_AD1DC3 48 /* ADC1 Digital Comparator 3 */ +#define PIC32_IRQ_AD1DC4 49 /* ADC1 Digital Comparator 4 */ +#define PIC32_IRQ_AD1DC5 50 /* ADC1 Digital Comparator 5 */ +#define PIC32_IRQ_AD1DC6 51 /* ADC1 Digital Comparator 6 */ +#define PIC32_IRQ_AD1DF1 52 /* ADC1 Digital Filter 1 */ +#define PIC32_IRQ_AD1DF2 53 /* ADC1 Digital Filter 2 */ +#define PIC32_IRQ_AD1DF3 54 /* ADC1 Digital Filter 3 */ +#define PIC32_IRQ_AD1DF4 55 /* ADC1 Digital Filter 4 */ +#define PIC32_IRQ_AD1DF5 56 /* ADC1 Digital Filter 5 */ +#define PIC32_IRQ_AD1DF6 57 /* ADC1 Digital Filter 6 */ + /* 58 -- Reserved */ +#define PIC32_IRQ_AD1D0 59 /* ADC1 Data 0 */ +#define PIC32_IRQ_AD1D1 60 /* ADC1 Data 1 */ +#define PIC32_IRQ_AD1D2 61 /* ADC1 Data 2 */ +#define PIC32_IRQ_AD1D3 62 /* ADC1 Data 3 */ +#define PIC32_IRQ_AD1D4 63 /* ADC1 Data 4 */ +#define PIC32_IRQ_AD1D5 64 /* ADC1 Data 5 */ +#define PIC32_IRQ_AD1D6 65 /* ADC1 Data 6 */ +#define PIC32_IRQ_AD1D7 66 /* ADC1 Data 7 */ +#define PIC32_IRQ_AD1D8 67 /* ADC1 Data 8 */ +#define PIC32_IRQ_AD1D9 68 /* ADC1 Data 9 */ +#define PIC32_IRQ_AD1D10 69 /* ADC1 Data 10 */ +#define PIC32_IRQ_AD1D11 70 /* ADC1 Data 11 */ +#define PIC32_IRQ_AD1D12 71 /* ADC1 Data 12 */ +#define PIC32_IRQ_AD1D13 72 /* ADC1 Data 13 */ +#define PIC32_IRQ_AD1D14 73 /* ADC1 Data 14 */ +#define PIC32_IRQ_AD1D15 74 /* ADC1 Data 15 */ +#define PIC32_IRQ_AD1D16 75 /* ADC1 Data 16 */ +#define PIC32_IRQ_AD1D17 76 /* ADC1 Data 17 */ +#define PIC32_IRQ_AD1D18 77 /* ADC1 Data 18 */ +#define PIC32_IRQ_AD1D19 78 /* ADC1 Data 19 */ +#define PIC32_IRQ_AD1D20 79 /* ADC1 Data 20 */ +#define PIC32_IRQ_AD1D21 80 /* ADC1 Data 21 */ +#define PIC32_IRQ_AD1D22 81 /* ADC1 Data 22 */ +#define PIC32_IRQ_AD1D23 82 /* ADC1 Data 23 */ +#define PIC32_IRQ_AD1D24 83 /* ADC1 Data 24 */ +#define PIC32_IRQ_AD1D25 84 /* ADC1 Data 25 */ +#define PIC32_IRQ_AD1D26 85 /* ADC1 Data 26 */ +#define PIC32_IRQ_AD1D27 86 /* ADC1 Data 27 */ +#define PIC32_IRQ_AD1D28 87 /* ADC1 Data 28 */ +#define PIC32_IRQ_AD1D29 88 /* ADC1 Data 29 */ +#define PIC32_IRQ_AD1D30 89 /* ADC1 Data 30 */ +#define PIC32_IRQ_AD1D31 90 /* ADC1 Data 31 */ +#define PIC32_IRQ_AD1D32 91 /* ADC1 Data 32 */ +#define PIC32_IRQ_AD1D33 92 /* ADC1 Data 33 */ +#define PIC32_IRQ_AD1D34 93 /* ADC1 Data 34 */ +#define PIC32_IRQ_AD1D35 94 /* ADC1 Data 35 */ +#define PIC32_IRQ_AD1D36 95 /* ADC1 Data 36 */ +#define PIC32_IRQ_AD1D37 96 /* ADC1 Data 37 */ +#define PIC32_IRQ_AD1D38 97 /* ADC1 Data 38 */ +#define PIC32_IRQ_AD1D39 98 /* ADC1 Data 39 */ +#define PIC32_IRQ_AD1D40 99 /* ADC1 Data 40 */ +#define PIC32_IRQ_AD1D41 100 /* ADC1 Data 41 */ +#define PIC32_IRQ_AD1D42 101 /* ADC1 Data 42 */ +#define PIC32_IRQ_AD1D43 102 /* ADC1 Data 43 */ +#define PIC32_IRQ_AD1D44 103 /* ADC1 Data 44 */ +#define PIC32_IRQ_CPC 104 /* Core Performance Counter */ +#define PIC32_IRQ_CFDC 105 /* Core Fast Debug Channel */ +#define PIC32_IRQ_SB 106 /* System Bus Protection Violation */ +#define PIC32_IRQ_CRPT 107 /* Crypto Engine Event */ + /* 108 -- Reserved */ +#define PIC32_IRQ_SPI1E 109 /* SPI1 Fault */ +#define PIC32_IRQ_SPI1RX 110 /* SPI1 Receive Done */ +#define PIC32_IRQ_SPI1TX 111 /* SPI1 Transfer Done */ +#define PIC32_IRQ_U1E 112 /* UART1 Fault */ +#define PIC32_IRQ_U1RX 113 /* UART1 Receive Done */ +#define PIC32_IRQ_U1TX 114 /* UART1 Transfer Done */ +#define PIC32_IRQ_I2C1B 115 /* I2C1 Bus Collision Event */ +#define PIC32_IRQ_I2C1S 116 /* I2C1 Slave Event */ +#define PIC32_IRQ_I2C1M 117 /* I2C1 Master Event */ +#define PIC32_IRQ_CNA 118 /* PORTA Input Change Interrupt */ +#define PIC32_IRQ_CNB 119 /* PORTB Input Change Interrupt */ +#define PIC32_IRQ_CNC 120 /* PORTC Input Change Interrupt */ +#define PIC32_IRQ_CND 121 /* PORTD Input Change Interrupt */ +#define PIC32_IRQ_CNE 122 /* PORTE Input Change Interrupt */ +#define PIC32_IRQ_CNF 123 /* PORTF Input Change Interrupt */ +#define PIC32_IRQ_CNG 124 /* PORTG Input Change Interrupt */ +#define PIC32_IRQ_CNH 125 /* PORTH Input Change Interrupt */ +#define PIC32_IRQ_CNJ 126 /* PORTJ Input Change Interrupt */ +#define PIC32_IRQ_CNK 127 /* PORTK Input Change Interrupt */ +#define PIC32_IRQ_PMP 128 /* Parallel Master Port */ +#define PIC32_IRQ_PMPE 129 /* Parallel Master Port Error */ +#define PIC32_IRQ_CMP1 130 /* Comparator 1 Interrupt */ +#define PIC32_IRQ_CMP2 131 /* Comparator 2 Interrupt */ +#define PIC32_IRQ_USB 132 /* USB General Event */ +#define PIC32_IRQ_USBDMA 133 /* USB DMA Event */ +#define PIC32_IRQ_DMA0 134 /* DMA Channel 0 */ +#define PIC32_IRQ_DMA1 135 /* DMA Channel 1 */ +#define PIC32_IRQ_DMA2 136 /* DMA Channel 2 */ +#define PIC32_IRQ_DMA3 137 /* DMA Channel 3 */ +#define PIC32_IRQ_DMA4 138 /* DMA Channel 4 */ +#define PIC32_IRQ_DMA5 139 /* DMA Channel 5 */ +#define PIC32_IRQ_DMA6 140 /* DMA Channel 6 */ +#define PIC32_IRQ_DMA7 141 /* DMA Channel 7 */ +#define PIC32_IRQ_SPI2E 142 /* SPI2 Fault */ +#define PIC32_IRQ_SPI2RX 143 /* SPI2 Receive Done */ +#define PIC32_IRQ_SPI2TX 144 /* SPI2 Transfer Done */ +#define PIC32_IRQ_U2E 145 /* UART2 Fault */ +#define PIC32_IRQ_U2RX 146 /* UART2 Receive Done */ +#define PIC32_IRQ_U2TX 147 /* UART2 Transfer Done */ +#define PIC32_IRQ_I2C2B 148 /* I2C2 Bus Collision Event */ +#define PIC32_IRQ_I2C2S 149 /* I2C2 Slave Event */ +#define PIC32_IRQ_I2C2M 150 /* I2C2 Master Event */ +#define PIC32_IRQ_CAN1 151 /* Control Area Network 1 */ +#define PIC32_IRQ_CAN2 152 /* Control Area Network 2 */ +#define PIC32_IRQ_ETH 153 /* Ethernet Interrupt */ +#define PIC32_IRQ_SPI3E 154 /* SPI3 Fault */ +#define PIC32_IRQ_SPI3RX 155 /* SPI3 Receive Done */ +#define PIC32_IRQ_SPI3TX 156 /* SPI3 Transfer Done */ +#define PIC32_IRQ_U3E 157 /* UART3 Fault */ +#define PIC32_IRQ_U3RX 158 /* UART3 Receive Done */ +#define PIC32_IRQ_U3TX 159 /* UART3 Transfer Done */ +#define PIC32_IRQ_I2C3B 160 /* I2C3 Bus Collision Event */ +#define PIC32_IRQ_I2C3S 161 /* I2C3 Slave Event */ +#define PIC32_IRQ_I2C3M 162 /* I2C3 Master Event */ +#define PIC32_IRQ_SPI4E 163 /* SPI4 Fault */ +#define PIC32_IRQ_SPI4RX 164 /* SPI4 Receive Done */ +#define PIC32_IRQ_SPI4TX 165 /* SPI4 Transfer Done */ +#define PIC32_IRQ_RTCC 166 /* Real Time Clock */ +#define PIC32_IRQ_FCE 167 /* Flash Control Event */ +#define PIC32_IRQ_PRE 168 /* Prefetch Module SEC Event */ +#define PIC32_IRQ_SQI1 169 /* SQI1 Event */ +#define PIC32_IRQ_U4E 170 /* UART4 Fault */ +#define PIC32_IRQ_U4RX 171 /* UART4 Receive Done */ +#define PIC32_IRQ_U4TX 172 /* UART4 Transfer Done */ +#define PIC32_IRQ_I2C4B 173 /* I2C4 Bus Collision Event */ +#define PIC32_IRQ_I2C4S 174 /* I2C4 Slave Event */ +#define PIC32_IRQ_I2C4M 175 /* I2C4 Master Event */ +#define PIC32_IRQ_SPI5E 176 /* SPI5 Fault */ +#define PIC32_IRQ_SPI5RX 177 /* SPI5 Receive Done */ +#define PIC32_IRQ_SPI5TX 178 /* SPI5 Transfer Done */ +#define PIC32_IRQ_U5E 179 /* UART5 Fault */ +#define PIC32_IRQ_U5RX 180 /* UART5 Receive Done */ +#define PIC32_IRQ_U5TX 181 /* UART5 Transfer Done */ +#define PIC32_IRQ_I2C5B 182 /* I2C5 Bus Collision Event */ +#define PIC32_IRQ_I2C5S 183 /* I2C5 Slave Event */ +#define PIC32_IRQ_I2C5M 184 /* I2C5 Master Event */ +#define PIC32_IRQ_SPI6E 185 /* SPI6 Fault */ +#define PIC32_IRQ_SPI6RX 186 /* SPI6 Receive Done */ +#define PIC32_IRQ_SPI6TX 187 /* SPI6 Transfer Done */ +#define PIC32_IRQ_U6E 188 /* UART6 Fault */ +#define PIC32_IRQ_U6RX 189 /* UART6 Receive Done */ +#define PIC32_IRQ_U6TX 190 /* UART6 Transfer Done */ + /* 191 -- Reserved */ +#define PIC32_IRQ_LAST 190 /* Last valid irq number */ + +#endif /* _IO_PIC32MZ_H */ From 0154a82e9c7c733ae837276e3a7d74498a638840 Mon Sep 17 00:00:00 2001 From: Serge Vakulenko Date: Fri, 20 Mar 2015 17:51:08 -0700 Subject: [PATCH 8/8] Ethernet device implemented for pic32mz. --- hw/mips/Makefile.objs | 1 + hw/mips/mips_pic32mx7.c | 12 +- hw/mips/mips_pic32mz.c | 915 ++++++++++++++++++++++++++++++------ hw/mips/pic32_ethernet.c | 530 +++++++++++++++++++++ hw/mips/pic32_peripherals.h | 16 +- hw/mips/pic32mx.h | 33 ++ hw/mips/pic32mz.h | 295 ++++++++++++ 7 files changed, 1649 insertions(+), 153 deletions(-) create mode 100644 hw/mips/pic32_ethernet.c diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs index 059af197fa48d..cb497fea16310 100644 --- a/hw/mips/Makefile.objs +++ b/hw/mips/Makefile.objs @@ -4,3 +4,4 @@ obj-$(CONFIG_FULONG) += mips_fulong2e.o obj-y += gt64xxx_pci.o obj-y += mips_pic32mz.o mips_pic32mx7.o obj-y += pic32_load_hex.o pic32_sdcard.o pic32_spi.o pic32_uart.o pic32_gpio.o +obj-y += pic32_ethernet.o diff --git a/hw/mips/mips_pic32mx7.c b/hw/mips/mips_pic32mx7.c index 3e00a8acad5b3..dfed12cdcef84 100644 --- a/hw/mips/mips_pic32mx7.c +++ b/hw/mips/mips_pic32mx7.c @@ -889,8 +889,8 @@ irq: update_irq_status(s); /*------------------------------------------------------------------------- * System controller. */ - STORAGE(OSCCON); break; // Oscillator Control - STORAGE(OSCTUN); break; // Oscillator Tuning + WRITEOPR(OSCCON, PIC32_OSCCON_UNUSED); break; // Oscillator Control + WRITEOPR(OSCTUN, PIC32_OSCTUN_UNUSED); break; // Oscillator Tuning STORAGE(DDPCON); break; // Debug Data Port Control READONLY(DEVID); // Device Identifier STORAGE(SYSKEY); // System Key @@ -902,7 +902,7 @@ irq: update_irq_status(s); else s->syskey_unlock = 0; break; - STORAGE(RCON); break; // Reset Control + WRITEOPR(RCON, PIC32_RCON_UNUSED); break; // Reset Control WRITEOP(RSWRST); // Software Reset if (s->syskey_unlock == 2 && (VALUE(RSWRST) & 1)) { /* Reset CPU. */ @@ -1435,9 +1435,9 @@ static void pic32_init(MachineState *machine, int board_type) BOOTMEM(DEVCFG3) = 0xffff0722; VALUE(DEVID) = 0x04307053; // MX795F512L VALUE(OSCCON) = 0x01453320; // external oscillator 8MHz - s->sdcard_spi_port = 3; // SD card at SPI4, - cs0_port = 3; cs0_pin = 3; // select0 at D3, - cs1_port = 3; cs1_pin = 4; // select1 at D4 + s->sdcard_spi_port = 1; // SD card at SPI2, + cs0_port = 2; cs0_pin = 14; // select0 at C14, + cs1_port = 3; cs1_pin = 1; // select1 at D1 break; case BOARD_MAXIMITE: BOOTMEM(DEVCFG0) = 0xffffff7f; // TODO: get real data from Maximite board diff --git a/hw/mips/mips_pic32mz.c b/hw/mips/mips_pic32mz.c index d25beef55f2a9..6b0258f6acacb 100644 --- a/hw/mips/mips_pic32mz.c +++ b/hw/mips/mips_pic32mz.c @@ -241,6 +241,8 @@ static void io_reset(pic32_t *s) VALUE(ANSELB) = 0xFFFF; // Port B: analog select VALUE(TRISB) = 0xFFFF; // Port B: mask of inputs VALUE(PORTB) = 0xFFFF; // Port B: read inputs, write outputs + if (s->board_type == BOARD_MEBII) + VALUE(PORTB) ^= 1 << 12; // Disable pin RB12 - button 1 VALUE(LATB) = 0xFFFF; // Port B: read/write outputs VALUE(ODCB) = 0; // Port B: open drain configuration VALUE(CNPUB) = 0; // Input pin pull-up @@ -379,48 +381,188 @@ static void io_reset(pic32_t *s) s->spi[i].wfifo = 0; } + /* + * Reset timers. + */ + VALUE(T1CON) = 0; + VALUE(TMR1) = 0; + VALUE(PR1) = 0xffff; + VALUE(T2CON) = 0; + VALUE(TMR2) = 0; + VALUE(PR2) = 0xffff; + VALUE(T3CON) = 0; + VALUE(TMR3) = 0; + VALUE(PR3) = 0xffff; + VALUE(T4CON) = 0; + VALUE(TMR4) = 0; + VALUE(PR4) = 0xffff; + VALUE(T5CON) = 0; + VALUE(TMR5) = 0; + VALUE(PR5) = 0xffff; + VALUE(T6CON) = 0; + VALUE(TMR6) = 0; + VALUE(PR6) = 0xffff; + VALUE(T7CON) = 0; + VALUE(TMR7) = 0; + VALUE(PR7) = 0xffff; + VALUE(T8CON) = 0; + VALUE(TMR8) = 0; + VALUE(PR8) = 0xffff; + VALUE(T9CON) = 0; + VALUE(TMR9) = 0; + VALUE(PR9) = 0xffff; + /* * Reset Ethernet. */ - VALUE(ETHCON1) = 0; // Control 1 - VALUE(ETHCON2) = 0; // Control 2: RX data buffer size - VALUE(ETHTXST) = 0; // Tx descriptor start address - VALUE(ETHRXST) = 0; // Rx descriptor start address - VALUE(ETHHT0) = 0; // Hash tasble 0 - VALUE(ETHHT1) = 0; // Hash tasble 1 - VALUE(ETHPMM0) = 0; // Pattern match mask 0 - VALUE(ETHPMM1) = 0; // Pattern match mask 1 - VALUE(ETHPMCS) = 0; // Pattern match checksum - VALUE(ETHPMO) = 0; // Pattern match offset - VALUE(ETHRXFC) = 0; // Receive filter configuration - VALUE(ETHRXWM) = 0; // Receive watermarks - VALUE(ETHIEN) = 0; // Interrupt enable - VALUE(ETHIRQ) = 0; // Interrupt request - VALUE(ETHSTAT) = 0; // Status - VALUE(ETHRXOVFLOW) = 0; // Receive overflow statistics - VALUE(ETHFRMTXOK) = 0; // Frames transmitted OK statistics - VALUE(ETHSCOLFRM) = 0; // Single collision frames statistics - VALUE(ETHMCOLFRM) = 0; // Multiple collision frames statistics - VALUE(ETHFRMRXOK) = 0; // Frames received OK statistics - VALUE(ETHFCSERR) = 0; // Frame check sequence error statistics - VALUE(ETHALGNERR) = 0; // Alignment errors statistics - VALUE(EMAC1CFG1) = 0x800d; // MAC configuration 1 - VALUE(EMAC1CFG2) = 0x4082; // MAC configuration 2 - VALUE(EMAC1IPGT) = 0x0012; // MAC back-to-back interpacket gap - VALUE(EMAC1IPGR) = 0x0c12; // MAC non-back-to-back interpacket gap - VALUE(EMAC1CLRT) = 0x370f; // MAC collision window/retry limit - VALUE(EMAC1MAXF) = 0x05ee; // MAC maximum frame length - VALUE(EMAC1SUPP) = 0x1000; // MAC PHY support - VALUE(EMAC1TEST) = 0; // MAC test - VALUE(EMAC1MCFG) = 0x0020; // MII configuration - VALUE(EMAC1MCMD) = 0; // MII command - VALUE(EMAC1MADR) = 0x0100; // MII address - VALUE(EMAC1MWTD) = 0; // MII write data - VALUE(EMAC1MRDD) = 0; // MII read data - VALUE(EMAC1MIND) = 0; // MII indicators - VALUE(EMAC1SA0) = 0x79c1; // MAC station address 0 - VALUE(EMAC1SA1) = 0xcbc0; // MAC station address 1 - VALUE(EMAC1SA2) = 0x1e00; // MAC station address 2 + VALUE(ETHCON1) = 0; // Control 1 + VALUE(ETHCON2) = 0; // Control 2: RX data buffer size + VALUE(ETHTXST) = 0; // Tx descriptor start address + VALUE(ETHRXST) = 0; // Rx descriptor start address + VALUE(ETHHT0) = 0; // Hash tasble 0 + VALUE(ETHHT1) = 0; // Hash tasble 1 + VALUE(ETHPMM0) = 0; // Pattern match mask 0 + VALUE(ETHPMM1) = 0; // Pattern match mask 1 + VALUE(ETHPMCS) = 0; // Pattern match checksum + VALUE(ETHPMO) = 0; // Pattern match offset + VALUE(ETHRXFC) = 0; // Receive filter configuration + VALUE(ETHRXWM) = 0; // Receive watermarks + VALUE(ETHIEN) = 0; // Interrupt enable + VALUE(ETHIRQ) = 0; // Interrupt request + VALUE(ETHSTAT) = 0; // Status + VALUE(ETHRXOVFLOW) = 0; // Receive overflow statistics + VALUE(ETHFRMTXOK) = 0; // Frames transmitted OK statistics + VALUE(ETHSCOLFRM) = 0; // Single collision frames statistics + VALUE(ETHMCOLFRM) = 0; // Multiple collision frames statistics + VALUE(ETHFRMRXOK) = 0; // Frames received OK statistics + VALUE(ETHFCSERR) = 0; // Frame check sequence error statistics + VALUE(ETHALGNERR) = 0; // Alignment errors statistics + VALUE(EMAC1CFG1) = 0x800d; // MAC configuration 1 + VALUE(EMAC1CFG2) = 0x4082; // MAC configuration 2 + VALUE(EMAC1IPGT) = 0x0012; // MAC back-to-back interpacket gap + VALUE(EMAC1IPGR) = 0x0c12; // MAC non-back-to-back interpacket gap + VALUE(EMAC1CLRT) = 0x370f; // MAC collision window/retry limit + VALUE(EMAC1MAXF) = 0x05ee; // MAC maximum frame length + VALUE(EMAC1SUPP) = 0x1000; // MAC PHY support + VALUE(EMAC1TEST) = 0; // MAC test + VALUE(EMAC1MCFG) = 0x0020; // MII configuration + VALUE(EMAC1MCMD) = 0; // MII command + VALUE(EMAC1MADR) = 0x0100; // MII address + VALUE(EMAC1MWTD) = 0; // MII write data + VALUE(EMAC1MRDD) = 0; // MII read data + VALUE(EMAC1MIND) = 0; // MII indicators + VALUE(EMAC1SA0) = 0x79c1; // MAC station address 0 + VALUE(EMAC1SA1) = 0xcbc0; // MAC station address 1 + VALUE(EMAC1SA2) = 0x1e00; // MAC station address 2 + + /* + * Reset USB. + */ + VALUE(USBCSR0) = 0x2000; + VALUE(USBCSR1) = 0x00ff0000; + VALUE(USBCSR2) = 0x060000fe; + VALUE(USBCSR3) = 0; + VALUE(USBIENCSR0) = 0; + VALUE(USBIENCSR1) = 0; + VALUE(USBIENCSR2) = 0; + VALUE(USBIENCSR3) = 0; + VALUE(USBFIFO0) = 0; + VALUE(USBFIFO1) = 0; + VALUE(USBFIFO2) = 0; + VALUE(USBFIFO3) = 0; + VALUE(USBFIFO4) = 0; + VALUE(USBFIFO5) = 0; + VALUE(USBFIFO6) = 0; + VALUE(USBFIFO7) = 0; + VALUE(USBOTG) = 0x0080; + VALUE(USBFIFOA) = 0; + VALUE(USBHWVER) = 0x0800; + VALUE(USBINFO) = 0x3C5C8C77; + VALUE(USBEOFRST) = 0x00727780; + VALUE(USBE0TXA) = 0; + VALUE(USBE0RXA) = 0; + VALUE(USBE1TXA) = 0; + VALUE(USBE1RXA) = 0; + VALUE(USBE2TXA) = 0; + VALUE(USBE2RXA) = 0; + VALUE(USBE3TXA) = 0; + VALUE(USBE3RXA) = 0; + VALUE(USBE4TXA) = 0; + VALUE(USBE4RXA) = 0; + VALUE(USBE5TXA) = 0; + VALUE(USBE5RXA) = 0; + VALUE(USBE6TXA) = 0; + VALUE(USBE6RXA) = 0; + VALUE(USBE7TXA) = 0; + VALUE(USBE7RXA) = 0; + VALUE(USBE0CSR0) = 0; + VALUE(USBE0CSR2) = 0; + VALUE(USBE0CSR3) = 0; + VALUE(USBE1CSR0) = 0; + VALUE(USBE1CSR1) = 0; + VALUE(USBE1CSR2) = 0; + VALUE(USBE1CSR3) = 0; + VALUE(USBE2CSR0) = 0; + VALUE(USBE2CSR1) = 0; + VALUE(USBE2CSR2) = 0; + VALUE(USBE2CSR3) = 0; + VALUE(USBE3CSR0) = 0; + VALUE(USBE3CSR1) = 0; + VALUE(USBE3CSR2) = 0; + VALUE(USBE3CSR3) = 0; + VALUE(USBE4CSR0) = 0; + VALUE(USBE4CSR1) = 0; + VALUE(USBE4CSR2) = 0; + VALUE(USBE4CSR3) = 0; + VALUE(USBE5CSR0) = 0; + VALUE(USBE5CSR1) = 0; + VALUE(USBE5CSR2) = 0; + VALUE(USBE5CSR3) = 0; + VALUE(USBE6CSR0) = 0; + VALUE(USBE6CSR1) = 0; + VALUE(USBE6CSR2) = 0; + VALUE(USBE6CSR3) = 0; + VALUE(USBE7CSR0) = 0; + VALUE(USBE7CSR1) = 0; + VALUE(USBE7CSR2) = 0; + VALUE(USBE7CSR3) = 0; + VALUE(USBDMAINT) = 0; + VALUE(USBDMA1C) = 0; + VALUE(USBDMA1A) = 0; + VALUE(USBDMA1N) = 0; + VALUE(USBDMA2C) = 0; + VALUE(USBDMA2A) = 0; + VALUE(USBDMA2N) = 0; + VALUE(USBDMA3C) = 0; + VALUE(USBDMA3A) = 0; + VALUE(USBDMA3N) = 0; + VALUE(USBDMA4C) = 0; + VALUE(USBDMA4A) = 0; + VALUE(USBDMA4N) = 0; + VALUE(USBDMA5C) = 0; + VALUE(USBDMA5A) = 0; + VALUE(USBDMA5N) = 0; + VALUE(USBDMA6C) = 0; + VALUE(USBDMA6A) = 0; + VALUE(USBDMA6N) = 0; + VALUE(USBDMA7C) = 0; + VALUE(USBDMA7A) = 0; + VALUE(USBDMA7N) = 0; + VALUE(USBDMA8C) = 0; + VALUE(USBDMA8A) = 0; + VALUE(USBDMA8N) = 0; + VALUE(USBE1RPC) = 0; + VALUE(USBE2RPC) = 0; + VALUE(USBE3RPC) = 0; + VALUE(USBE4RPC) = 0; + VALUE(USBE5RPC) = 0; + VALUE(USBE6RPC) = 0; + VALUE(USBE7RPC) = 0; + VALUE(USBDPBFD) = 0; + VALUE(USBTMCON1) = 0x05E64074; + VALUE(USBTMCON2) = 0; + VALUE(USBLPMR1) = 0; + VALUE(USBLMPR2) = 0; } static unsigned io_read32(pic32_t *s, unsigned offset, const char **namep) @@ -445,54 +587,130 @@ static unsigned io_read32(pic32_t *s, unsigned offset, const char **namep) STORAGE(IEC3); break; STORAGE(IEC4); break; STORAGE(IEC5); break; - STORAGE(IPC0); break; // IPC(0..11) - Interrupt Priority Control - STORAGE(IPC1); break; - STORAGE(IPC2); break; - STORAGE(IPC3); break; - STORAGE(IPC4); break; - STORAGE(IPC5); break; - STORAGE(IPC6); break; - STORAGE(IPC7); break; - STORAGE(IPC8); break; - STORAGE(IPC9); break; - STORAGE(IPC10); break; - STORAGE(IPC11); break; - STORAGE(IPC12); break; - STORAGE(IPC13); break; - STORAGE(IPC14); break; - STORAGE(IPC15); break; - STORAGE(IPC16); break; - STORAGE(IPC17); break; - STORAGE(IPC18); break; - STORAGE(IPC19); break; - STORAGE(IPC20); break; - STORAGE(IPC21); break; - STORAGE(IPC22); break; - STORAGE(IPC23); break; - STORAGE(IPC24); break; - STORAGE(IPC25); break; - STORAGE(IPC26); break; - STORAGE(IPC27); break; - STORAGE(IPC28); break; - STORAGE(IPC29); break; - STORAGE(IPC30); break; - STORAGE(IPC31); break; - STORAGE(IPC32); break; - STORAGE(IPC33); break; - STORAGE(IPC34); break; - STORAGE(IPC35); break; - STORAGE(IPC36); break; - STORAGE(IPC37); break; - STORAGE(IPC38); break; - STORAGE(IPC39); break; - STORAGE(IPC40); break; - STORAGE(IPC41); break; - STORAGE(IPC42); break; - STORAGE(IPC43); break; - STORAGE(IPC44); break; - STORAGE(IPC45); break; - STORAGE(IPC46); break; - STORAGE(IPC47); break; + + // IPC(0..11) - Interrupt Priority Control + STORAGE(IPC0); break; STORAGE(IPC1); break; + STORAGE(IPC2); break; STORAGE(IPC3); break; + STORAGE(IPC4); break; STORAGE(IPC5); break; + STORAGE(IPC6); break; STORAGE(IPC7); break; + STORAGE(IPC8); break; STORAGE(IPC9); break; + STORAGE(IPC10); break; STORAGE(IPC11); break; + STORAGE(IPC12); break; STORAGE(IPC13); break; + STORAGE(IPC14); break; STORAGE(IPC15); break; + STORAGE(IPC16); break; STORAGE(IPC17); break; + STORAGE(IPC18); break; STORAGE(IPC19); break; + STORAGE(IPC20); break; STORAGE(IPC21); break; + STORAGE(IPC22); break; STORAGE(IPC23); break; + STORAGE(IPC24); break; STORAGE(IPC25); break; + STORAGE(IPC26); break; STORAGE(IPC27); break; + STORAGE(IPC28); break; STORAGE(IPC29); break; + STORAGE(IPC30); break; STORAGE(IPC31); break; + STORAGE(IPC32); break; STORAGE(IPC33); break; + STORAGE(IPC34); break; STORAGE(IPC35); break; + STORAGE(IPC36); break; STORAGE(IPC37); break; + STORAGE(IPC38); break; STORAGE(IPC39); break; + STORAGE(IPC40); break; STORAGE(IPC41); break; + STORAGE(IPC42); break; STORAGE(IPC43); break; + STORAGE(IPC44); break; STORAGE(IPC45); break; + STORAGE(IPC46); break; STORAGE(IPC47); break; + + // OFF000..OFF190 - Interrupt Vector Address Offset + STORAGE(OFF(0)); break; STORAGE(OFF(1)); break; + STORAGE(OFF(2)); break; STORAGE(OFF(3)); break; + STORAGE(OFF(4)); break; STORAGE(OFF(5)); break; + STORAGE(OFF(6)); break; STORAGE(OFF(7)); break; + STORAGE(OFF(8)); break; STORAGE(OFF(9)); break; + STORAGE(OFF(10)); break; STORAGE(OFF(11)); break; + STORAGE(OFF(12)); break; STORAGE(OFF(13)); break; + STORAGE(OFF(14)); break; STORAGE(OFF(15)); break; + STORAGE(OFF(16)); break; STORAGE(OFF(17)); break; + STORAGE(OFF(18)); break; STORAGE(OFF(19)); break; + STORAGE(OFF(20)); break; STORAGE(OFF(21)); break; + STORAGE(OFF(22)); break; STORAGE(OFF(23)); break; + STORAGE(OFF(24)); break; STORAGE(OFF(25)); break; + STORAGE(OFF(26)); break; STORAGE(OFF(27)); break; + STORAGE(OFF(28)); break; STORAGE(OFF(29)); break; + STORAGE(OFF(30)); break; STORAGE(OFF(31)); break; + STORAGE(OFF(32)); break; STORAGE(OFF(33)); break; + STORAGE(OFF(34)); break; STORAGE(OFF(35)); break; + STORAGE(OFF(36)); break; STORAGE(OFF(37)); break; + STORAGE(OFF(38)); break; STORAGE(OFF(39)); break; + STORAGE(OFF(40)); break; STORAGE(OFF(41)); break; + STORAGE(OFF(42)); break; STORAGE(OFF(43)); break; + STORAGE(OFF(44)); break; STORAGE(OFF(45)); break; + STORAGE(OFF(46)); break; STORAGE(OFF(47)); break; + STORAGE(OFF(48)); break; STORAGE(OFF(49)); break; + STORAGE(OFF(50)); break; STORAGE(OFF(51)); break; + STORAGE(OFF(52)); break; STORAGE(OFF(53)); break; + STORAGE(OFF(54)); break; STORAGE(OFF(55)); break; + STORAGE(OFF(56)); break; STORAGE(OFF(57)); break; + STORAGE(OFF(58)); break; STORAGE(OFF(59)); break; + STORAGE(OFF(60)); break; STORAGE(OFF(61)); break; + STORAGE(OFF(62)); break; STORAGE(OFF(63)); break; + STORAGE(OFF(64)); break; STORAGE(OFF(65)); break; + STORAGE(OFF(66)); break; STORAGE(OFF(67)); break; + STORAGE(OFF(68)); break; STORAGE(OFF(69)); break; + STORAGE(OFF(70)); break; STORAGE(OFF(71)); break; + STORAGE(OFF(72)); break; STORAGE(OFF(73)); break; + STORAGE(OFF(74)); break; STORAGE(OFF(75)); break; + STORAGE(OFF(76)); break; STORAGE(OFF(77)); break; + STORAGE(OFF(78)); break; STORAGE(OFF(79)); break; + STORAGE(OFF(80)); break; STORAGE(OFF(81)); break; + STORAGE(OFF(82)); break; STORAGE(OFF(83)); break; + STORAGE(OFF(84)); break; STORAGE(OFF(85)); break; + STORAGE(OFF(86)); break; STORAGE(OFF(87)); break; + STORAGE(OFF(88)); break; STORAGE(OFF(89)); break; + STORAGE(OFF(90)); break; STORAGE(OFF(91)); break; + STORAGE(OFF(92)); break; STORAGE(OFF(93)); break; + STORAGE(OFF(94)); break; STORAGE(OFF(95)); break; + STORAGE(OFF(96)); break; STORAGE(OFF(97)); break; + STORAGE(OFF(98)); break; STORAGE(OFF(99)); break; + STORAGE(OFF(100)); break; STORAGE(OFF(101)); break; + STORAGE(OFF(102)); break; STORAGE(OFF(103)); break; + STORAGE(OFF(104)); break; STORAGE(OFF(105)); break; + STORAGE(OFF(106)); break; STORAGE(OFF(107)); break; + STORAGE(OFF(108)); break; STORAGE(OFF(109)); break; + STORAGE(OFF(110)); break; STORAGE(OFF(111)); break; + STORAGE(OFF(112)); break; STORAGE(OFF(113)); break; + STORAGE(OFF(114)); break; STORAGE(OFF(115)); break; + STORAGE(OFF(116)); break; STORAGE(OFF(117)); break; + STORAGE(OFF(118)); break; STORAGE(OFF(119)); break; + STORAGE(OFF(120)); break; STORAGE(OFF(121)); break; + STORAGE(OFF(122)); break; STORAGE(OFF(123)); break; + STORAGE(OFF(124)); break; STORAGE(OFF(125)); break; + STORAGE(OFF(126)); break; STORAGE(OFF(127)); break; + STORAGE(OFF(128)); break; STORAGE(OFF(129)); break; + STORAGE(OFF(130)); break; STORAGE(OFF(131)); break; + STORAGE(OFF(132)); break; STORAGE(OFF(133)); break; + STORAGE(OFF(134)); break; STORAGE(OFF(135)); break; + STORAGE(OFF(136)); break; STORAGE(OFF(137)); break; + STORAGE(OFF(138)); break; STORAGE(OFF(139)); break; + STORAGE(OFF(140)); break; STORAGE(OFF(141)); break; + STORAGE(OFF(142)); break; STORAGE(OFF(143)); break; + STORAGE(OFF(144)); break; STORAGE(OFF(145)); break; + STORAGE(OFF(146)); break; STORAGE(OFF(147)); break; + STORAGE(OFF(148)); break; STORAGE(OFF(149)); break; + STORAGE(OFF(150)); break; STORAGE(OFF(151)); break; + STORAGE(OFF(152)); break; STORAGE(OFF(153)); break; + STORAGE(OFF(154)); break; STORAGE(OFF(155)); break; + STORAGE(OFF(156)); break; STORAGE(OFF(157)); break; + STORAGE(OFF(158)); break; STORAGE(OFF(159)); break; + STORAGE(OFF(160)); break; STORAGE(OFF(161)); break; + STORAGE(OFF(162)); break; STORAGE(OFF(163)); break; + STORAGE(OFF(164)); break; STORAGE(OFF(165)); break; + STORAGE(OFF(166)); break; STORAGE(OFF(167)); break; + STORAGE(OFF(168)); break; STORAGE(OFF(169)); break; + STORAGE(OFF(170)); break; STORAGE(OFF(171)); break; + STORAGE(OFF(172)); break; STORAGE(OFF(173)); break; + STORAGE(OFF(174)); break; STORAGE(OFF(175)); break; + STORAGE(OFF(176)); break; STORAGE(OFF(177)); break; + STORAGE(OFF(178)); break; STORAGE(OFF(179)); break; + STORAGE(OFF(180)); break; STORAGE(OFF(181)); break; + STORAGE(OFF(182)); break; STORAGE(OFF(183)); break; + STORAGE(OFF(184)); break; STORAGE(OFF(185)); break; + STORAGE(OFF(186)); break; STORAGE(OFF(187)); break; + STORAGE(OFF(188)); break; STORAGE(OFF(189)); break; + STORAGE(OFF(190)); break; /*------------------------------------------------------------------------- * Prefetch controller. @@ -515,13 +733,50 @@ static unsigned io_read32(pic32_t *s, unsigned offset, const char **namep) STORAGE(OSCCON); break; // Oscillator Control STORAGE(OSCTUN); break; // Oscillator Tuning STORAGE(SPLLCON); break; // System PLL Control + STORAGE(REFO1CON); break; + STORAGE(REFO1CONCLR); *bufp = 0; break; + STORAGE(REFO1CONSET); *bufp = 0; break; + STORAGE(REFO1CONINV); *bufp = 0; break; + STORAGE(REFO2CON); break; + STORAGE(REFO2CONCLR); *bufp = 0; break; + STORAGE(REFO2CONSET); *bufp = 0; break; + STORAGE(REFO2CONINV); *bufp = 0; break; + STORAGE(REFO3CON); break; + STORAGE(REFO3CONCLR); *bufp = 0; break; + STORAGE(REFO3CONSET); *bufp = 0; break; + STORAGE(REFO3CONINV); *bufp = 0; break; + STORAGE(REFO4CON); break; + STORAGE(REFO4CONCLR); *bufp = 0; break; + STORAGE(REFO4CONSET); *bufp = 0; break; + STORAGE(REFO4CONINV); *bufp = 0; break; STORAGE(PB1DIV); break; // Peripheral bus 1 divisor + STORAGE(PB1DIVCLR); *bufp = 0; break; + STORAGE(PB1DIVSET); *bufp = 0; break; + STORAGE(PB1DIVINV); *bufp = 0; break; STORAGE(PB2DIV); break; // Peripheral bus 2 divisor + STORAGE(PB2DIVCLR); *bufp = 0; break; + STORAGE(PB2DIVSET); *bufp = 0; break; + STORAGE(PB2DIVINV); *bufp = 0; break; STORAGE(PB3DIV); break; // Peripheral bus 3 divisor + STORAGE(PB3DIVCLR); *bufp = 0; break; + STORAGE(PB3DIVSET); *bufp = 0; break; + STORAGE(PB3DIVINV); *bufp = 0; break; STORAGE(PB4DIV); break; // Peripheral bus 4 divisor + STORAGE(PB4DIVCLR); *bufp = 0; break; + STORAGE(PB4DIVSET); *bufp = 0; break; + STORAGE(PB4DIVINV); *bufp = 0; break; STORAGE(PB5DIV); break; // Peripheral bus 5 divisor + STORAGE(PB5DIVCLR); *bufp = 0; break; + STORAGE(PB5DIVSET); *bufp = 0; break; + STORAGE(PB5DIVINV); *bufp = 0; break; STORAGE(PB7DIV); break; // Peripheral bus 7 divisor + STORAGE(PB7DIVCLR); *bufp = 0; break; + STORAGE(PB7DIVSET); *bufp = 0; break; + STORAGE(PB7DIVINV); *bufp = 0; break; STORAGE(PB8DIV); break; // Peripheral bus 8 divisor + STORAGE(PB8DIVCLR); *bufp = 0; break; + STORAGE(PB8DIVSET); *bufp = 0; break; + STORAGE(PB8DIVINV); *bufp = 0; break; /*------------------------------------------------------------------------- * Peripheral port select registers: input. @@ -939,6 +1194,37 @@ static unsigned io_read32(pic32_t *s, unsigned offset, const char **namep) STORAGE(SPI4CON2SET); *bufp = 0; break; STORAGE(SPI4CON2INV); *bufp = 0; break; + /*------------------------------------------------------------------------- + * Timers. + */ + STORAGE(T1CON); break; + STORAGE(TMR1); break; + STORAGE(PR1); break; + STORAGE(T2CON); break; + STORAGE(TMR2); break; + STORAGE(PR2); break; + STORAGE(T3CON); break; + STORAGE(TMR3); break; + STORAGE(PR3); break; + STORAGE(T4CON); break; + STORAGE(TMR4); break; + STORAGE(PR4); break; + STORAGE(T5CON); break; + STORAGE(TMR5); break; + STORAGE(PR5); break; + STORAGE(T6CON); break; + STORAGE(TMR6); break; + STORAGE(PR6); break; + STORAGE(T7CON); break; + STORAGE(TMR7); break; + STORAGE(PR7); break; + STORAGE(T8CON); break; + STORAGE(TMR8); break; + STORAGE(PR8); break; + STORAGE(T9CON); break; + STORAGE(TMR9); break; + STORAGE(PR9); break; + /*------------------------------------------------------------------------- * Ethernet. */ @@ -982,6 +1268,115 @@ static unsigned io_read32(pic32_t *s, unsigned offset, const char **namep) STORAGE(EMAC1SA1); break; // MAC station address 1 STORAGE(EMAC1SA2); break; // MAC station address 2 + /*------------------------------------------------------------------------- + * USB. + */ + STORAGE(USBCSR0); break; + STORAGE(USBCSR1); break; + STORAGE(USBCSR2); break; + STORAGE(USBCSR3); break; + STORAGE(USBIENCSR0); break; + STORAGE(USBIENCSR1); break; + STORAGE(USBIENCSR2); break; + STORAGE(USBIENCSR3); break; + STORAGE(USBFIFO0); break; + STORAGE(USBFIFO1); break; + STORAGE(USBFIFO2); break; + STORAGE(USBFIFO3); break; + STORAGE(USBFIFO4); break; + STORAGE(USBFIFO5); break; + STORAGE(USBFIFO6); break; + STORAGE(USBFIFO7); break; + STORAGE(USBOTG); break; + STORAGE(USBFIFOA); break; + STORAGE(USBHWVER); break; + STORAGE(USBINFO); break; + STORAGE(USBEOFRST); break; + STORAGE(USBE0TXA); break; + STORAGE(USBE0RXA); break; + STORAGE(USBE1TXA); break; + STORAGE(USBE1RXA); break; + STORAGE(USBE2TXA); break; + STORAGE(USBE2RXA); break; + STORAGE(USBE3TXA); break; + STORAGE(USBE3RXA); break; + STORAGE(USBE4TXA); break; + STORAGE(USBE4RXA); break; + STORAGE(USBE5TXA); break; + STORAGE(USBE5RXA); break; + STORAGE(USBE6TXA); break; + STORAGE(USBE6RXA); break; + STORAGE(USBE7TXA); break; + STORAGE(USBE7RXA); break; + STORAGE(USBE0CSR0); break; + STORAGE(USBE0CSR2); break; + STORAGE(USBE0CSR3); break; + STORAGE(USBE1CSR0); break; + STORAGE(USBE1CSR1); break; + STORAGE(USBE1CSR2); break; + STORAGE(USBE1CSR3); break; + STORAGE(USBE2CSR0); break; + STORAGE(USBE2CSR1); break; + STORAGE(USBE2CSR2); break; + STORAGE(USBE2CSR3); break; + STORAGE(USBE3CSR0); break; + STORAGE(USBE3CSR1); break; + STORAGE(USBE3CSR2); break; + STORAGE(USBE3CSR3); break; + STORAGE(USBE4CSR0); break; + STORAGE(USBE4CSR1); break; + STORAGE(USBE4CSR2); break; + STORAGE(USBE4CSR3); break; + STORAGE(USBE5CSR0); break; + STORAGE(USBE5CSR1); break; + STORAGE(USBE5CSR2); break; + STORAGE(USBE5CSR3); break; + STORAGE(USBE6CSR0); break; + STORAGE(USBE6CSR1); break; + STORAGE(USBE6CSR2); break; + STORAGE(USBE6CSR3); break; + STORAGE(USBE7CSR0); break; + STORAGE(USBE7CSR1); break; + STORAGE(USBE7CSR2); break; + STORAGE(USBE7CSR3); break; + STORAGE(USBDMAINT); break; + STORAGE(USBDMA1C); break; + STORAGE(USBDMA1A); break; + STORAGE(USBDMA1N); break; + STORAGE(USBDMA2C); break; + STORAGE(USBDMA2A); break; + STORAGE(USBDMA2N); break; + STORAGE(USBDMA3C); break; + STORAGE(USBDMA3A); break; + STORAGE(USBDMA3N); break; + STORAGE(USBDMA4C); break; + STORAGE(USBDMA4A); break; + STORAGE(USBDMA4N); break; + STORAGE(USBDMA5C); break; + STORAGE(USBDMA5A); break; + STORAGE(USBDMA5N); break; + STORAGE(USBDMA6C); break; + STORAGE(USBDMA6A); break; + STORAGE(USBDMA6N); break; + STORAGE(USBDMA7C); break; + STORAGE(USBDMA7A); break; + STORAGE(USBDMA7N); break; + STORAGE(USBDMA8C); break; + STORAGE(USBDMA8A); break; + STORAGE(USBDMA8N); break; + STORAGE(USBE1RPC); break; + STORAGE(USBE2RPC); break; + STORAGE(USBE3RPC); break; + STORAGE(USBE4RPC); break; + STORAGE(USBE5RPC); break; + STORAGE(USBE6RPC); break; + STORAGE(USBE7RPC); break; + STORAGE(USBDPBFD); break; + STORAGE(USBTMCON1); break; + STORAGE(USBTMCON2); break; + STORAGE(USBLPMR1); break; + STORAGE(USBLMPR2); break; + default: printf("--- Read 1f8%05x: peripheral register not supported\n", offset); @@ -1153,57 +1548,133 @@ static void io_write32(pic32_t *s, unsigned offset, unsigned data, const char ** WRITEOP(IEC3); goto irq; WRITEOP(IEC4); goto irq; WRITEOP(IEC5); goto irq; - WRITEOP(IPC0); goto irq; // IPC(0..11) - Interrupt Priority Control - WRITEOP(IPC1); goto irq; - WRITEOP(IPC2); goto irq; - WRITEOP(IPC3); goto irq; - WRITEOP(IPC4); goto irq; - WRITEOP(IPC5); goto irq; - WRITEOP(IPC6); goto irq; - WRITEOP(IPC7); goto irq; - WRITEOP(IPC8); goto irq; - WRITEOP(IPC9); goto irq; - WRITEOP(IPC10); goto irq; - WRITEOP(IPC11); goto irq; - WRITEOP(IPC12); goto irq; - WRITEOP(IPC13); goto irq; - WRITEOP(IPC14); goto irq; - WRITEOP(IPC15); goto irq; - WRITEOP(IPC16); goto irq; - WRITEOP(IPC17); goto irq; - WRITEOP(IPC18); goto irq; - WRITEOP(IPC19); goto irq; - WRITEOP(IPC20); goto irq; - WRITEOP(IPC21); goto irq; - WRITEOP(IPC22); goto irq; - WRITEOP(IPC23); goto irq; - WRITEOP(IPC24); goto irq; - WRITEOP(IPC25); goto irq; - WRITEOP(IPC26); goto irq; - WRITEOP(IPC27); goto irq; - WRITEOP(IPC28); goto irq; - WRITEOP(IPC29); goto irq; - WRITEOP(IPC30); goto irq; - WRITEOP(IPC31); goto irq; - WRITEOP(IPC32); goto irq; - WRITEOP(IPC33); goto irq; - WRITEOP(IPC34); goto irq; - WRITEOP(IPC35); goto irq; - WRITEOP(IPC36); goto irq; - WRITEOP(IPC37); goto irq; - WRITEOP(IPC38); goto irq; - WRITEOP(IPC39); goto irq; - WRITEOP(IPC40); goto irq; - WRITEOP(IPC41); goto irq; - WRITEOP(IPC42); goto irq; - WRITEOP(IPC43); goto irq; - WRITEOP(IPC44); goto irq; - WRITEOP(IPC45); goto irq; - WRITEOP(IPC46); goto irq; - WRITEOP(IPC47); + + // IPC(0..11) - Interrupt Priority Control + WRITEOP(IPC0); goto irq; WRITEOP(IPC1); goto irq; + WRITEOP(IPC2); goto irq; WRITEOP(IPC3); goto irq; + WRITEOP(IPC4); goto irq; WRITEOP(IPC5); goto irq; + WRITEOP(IPC6); goto irq; WRITEOP(IPC7); goto irq; + WRITEOP(IPC8); goto irq; WRITEOP(IPC9); goto irq; + WRITEOP(IPC10); goto irq; WRITEOP(IPC11); goto irq; + WRITEOP(IPC12); goto irq; WRITEOP(IPC13); goto irq; + WRITEOP(IPC14); goto irq; WRITEOP(IPC15); goto irq; + WRITEOP(IPC16); goto irq; WRITEOP(IPC17); goto irq; + WRITEOP(IPC18); goto irq; WRITEOP(IPC19); goto irq; + WRITEOP(IPC20); goto irq; WRITEOP(IPC21); goto irq; + WRITEOP(IPC22); goto irq; WRITEOP(IPC23); goto irq; + WRITEOP(IPC24); goto irq; WRITEOP(IPC25); goto irq; + WRITEOP(IPC26); goto irq; WRITEOP(IPC27); goto irq; + WRITEOP(IPC28); goto irq; WRITEOP(IPC29); goto irq; + WRITEOP(IPC30); goto irq; WRITEOP(IPC31); goto irq; + WRITEOP(IPC32); goto irq; WRITEOP(IPC33); goto irq; + WRITEOP(IPC34); goto irq; WRITEOP(IPC35); goto irq; + WRITEOP(IPC36); goto irq; WRITEOP(IPC37); goto irq; + WRITEOP(IPC38); goto irq; WRITEOP(IPC39); goto irq; + WRITEOP(IPC40); goto irq; WRITEOP(IPC41); goto irq; + WRITEOP(IPC42); goto irq; WRITEOP(IPC43); goto irq; + WRITEOP(IPC44); goto irq; WRITEOP(IPC45); goto irq; + WRITEOP(IPC46); goto irq; WRITEOP(IPC47); irq: update_irq_status(s); return; + // OFF000..OFF190 - Interrupt Vector Address Offset + STORAGE(OFF(0)); break; STORAGE(OFF(1)); break; + STORAGE(OFF(2)); break; STORAGE(OFF(3)); break; + STORAGE(OFF(4)); break; STORAGE(OFF(5)); break; + STORAGE(OFF(6)); break; STORAGE(OFF(7)); break; + STORAGE(OFF(8)); break; STORAGE(OFF(9)); break; + STORAGE(OFF(10)); break; STORAGE(OFF(11)); break; + STORAGE(OFF(12)); break; STORAGE(OFF(13)); break; + STORAGE(OFF(14)); break; STORAGE(OFF(15)); break; + STORAGE(OFF(16)); break; STORAGE(OFF(17)); break; + STORAGE(OFF(18)); break; STORAGE(OFF(19)); break; + STORAGE(OFF(20)); break; STORAGE(OFF(21)); break; + STORAGE(OFF(22)); break; STORAGE(OFF(23)); break; + STORAGE(OFF(24)); break; STORAGE(OFF(25)); break; + STORAGE(OFF(26)); break; STORAGE(OFF(27)); break; + STORAGE(OFF(28)); break; STORAGE(OFF(29)); break; + STORAGE(OFF(30)); break; STORAGE(OFF(31)); break; + STORAGE(OFF(32)); break; STORAGE(OFF(33)); break; + STORAGE(OFF(34)); break; STORAGE(OFF(35)); break; + STORAGE(OFF(36)); break; STORAGE(OFF(37)); break; + STORAGE(OFF(38)); break; STORAGE(OFF(39)); break; + STORAGE(OFF(40)); break; STORAGE(OFF(41)); break; + STORAGE(OFF(42)); break; STORAGE(OFF(43)); break; + STORAGE(OFF(44)); break; STORAGE(OFF(45)); break; + STORAGE(OFF(46)); break; STORAGE(OFF(47)); break; + STORAGE(OFF(48)); break; STORAGE(OFF(49)); break; + STORAGE(OFF(50)); break; STORAGE(OFF(51)); break; + STORAGE(OFF(52)); break; STORAGE(OFF(53)); break; + STORAGE(OFF(54)); break; STORAGE(OFF(55)); break; + STORAGE(OFF(56)); break; STORAGE(OFF(57)); break; + STORAGE(OFF(58)); break; STORAGE(OFF(59)); break; + STORAGE(OFF(60)); break; STORAGE(OFF(61)); break; + STORAGE(OFF(62)); break; STORAGE(OFF(63)); break; + STORAGE(OFF(64)); break; STORAGE(OFF(65)); break; + STORAGE(OFF(66)); break; STORAGE(OFF(67)); break; + STORAGE(OFF(68)); break; STORAGE(OFF(69)); break; + STORAGE(OFF(70)); break; STORAGE(OFF(71)); break; + STORAGE(OFF(72)); break; STORAGE(OFF(73)); break; + STORAGE(OFF(74)); break; STORAGE(OFF(75)); break; + STORAGE(OFF(76)); break; STORAGE(OFF(77)); break; + STORAGE(OFF(78)); break; STORAGE(OFF(79)); break; + STORAGE(OFF(80)); break; STORAGE(OFF(81)); break; + STORAGE(OFF(82)); break; STORAGE(OFF(83)); break; + STORAGE(OFF(84)); break; STORAGE(OFF(85)); break; + STORAGE(OFF(86)); break; STORAGE(OFF(87)); break; + STORAGE(OFF(88)); break; STORAGE(OFF(89)); break; + STORAGE(OFF(90)); break; STORAGE(OFF(91)); break; + STORAGE(OFF(92)); break; STORAGE(OFF(93)); break; + STORAGE(OFF(94)); break; STORAGE(OFF(95)); break; + STORAGE(OFF(96)); break; STORAGE(OFF(97)); break; + STORAGE(OFF(98)); break; STORAGE(OFF(99)); break; + STORAGE(OFF(100)); break; STORAGE(OFF(101)); break; + STORAGE(OFF(102)); break; STORAGE(OFF(103)); break; + STORAGE(OFF(104)); break; STORAGE(OFF(105)); break; + STORAGE(OFF(106)); break; STORAGE(OFF(107)); break; + STORAGE(OFF(108)); break; STORAGE(OFF(109)); break; + STORAGE(OFF(110)); break; STORAGE(OFF(111)); break; + STORAGE(OFF(112)); break; STORAGE(OFF(113)); break; + STORAGE(OFF(114)); break; STORAGE(OFF(115)); break; + STORAGE(OFF(116)); break; STORAGE(OFF(117)); break; + STORAGE(OFF(118)); break; STORAGE(OFF(119)); break; + STORAGE(OFF(120)); break; STORAGE(OFF(121)); break; + STORAGE(OFF(122)); break; STORAGE(OFF(123)); break; + STORAGE(OFF(124)); break; STORAGE(OFF(125)); break; + STORAGE(OFF(126)); break; STORAGE(OFF(127)); break; + STORAGE(OFF(128)); break; STORAGE(OFF(129)); break; + STORAGE(OFF(130)); break; STORAGE(OFF(131)); break; + STORAGE(OFF(132)); break; STORAGE(OFF(133)); break; + STORAGE(OFF(134)); break; STORAGE(OFF(135)); break; + STORAGE(OFF(136)); break; STORAGE(OFF(137)); break; + STORAGE(OFF(138)); break; STORAGE(OFF(139)); break; + STORAGE(OFF(140)); break; STORAGE(OFF(141)); break; + STORAGE(OFF(142)); break; STORAGE(OFF(143)); break; + STORAGE(OFF(144)); break; STORAGE(OFF(145)); break; + STORAGE(OFF(146)); break; STORAGE(OFF(147)); break; + STORAGE(OFF(148)); break; STORAGE(OFF(149)); break; + STORAGE(OFF(150)); break; STORAGE(OFF(151)); break; + STORAGE(OFF(152)); break; STORAGE(OFF(153)); break; + STORAGE(OFF(154)); break; STORAGE(OFF(155)); break; + STORAGE(OFF(156)); break; STORAGE(OFF(157)); break; + STORAGE(OFF(158)); break; STORAGE(OFF(159)); break; + STORAGE(OFF(160)); break; STORAGE(OFF(161)); break; + STORAGE(OFF(162)); break; STORAGE(OFF(163)); break; + STORAGE(OFF(164)); break; STORAGE(OFF(165)); break; + STORAGE(OFF(166)); break; STORAGE(OFF(167)); break; + STORAGE(OFF(168)); break; STORAGE(OFF(169)); break; + STORAGE(OFF(170)); break; STORAGE(OFF(171)); break; + STORAGE(OFF(172)); break; STORAGE(OFF(173)); break; + STORAGE(OFF(174)); break; STORAGE(OFF(175)); break; + STORAGE(OFF(176)); break; STORAGE(OFF(177)); break; + STORAGE(OFF(178)); break; STORAGE(OFF(179)); break; + STORAGE(OFF(180)); break; STORAGE(OFF(181)); break; + STORAGE(OFF(182)); break; STORAGE(OFF(183)); break; + STORAGE(OFF(184)); break; STORAGE(OFF(185)); break; + STORAGE(OFF(186)); break; STORAGE(OFF(187)); break; + STORAGE(OFF(188)); break; STORAGE(OFF(189)); break; + STORAGE(OFF(190)); break; + /*------------------------------------------------------------------------- * Prefetch controller. */ @@ -1247,13 +1718,17 @@ irq: update_irq_status(s); STORAGE(OSCCON); break; // Oscillator Control STORAGE(OSCTUN); break; // Oscillator Tuning STORAGE(SPLLCON); break; // System PLL Control - STORAGE(PB1DIV); break; // Peripheral bus 1 divisor - STORAGE(PB2DIV); break; // Peripheral bus 2 divisor - STORAGE(PB3DIV); break; // Peripheral bus 3 divisor - STORAGE(PB4DIV); break; // Peripheral bus 4 divisor - STORAGE(PB5DIV); break; // Peripheral bus 5 divisor - STORAGE(PB7DIV); break; // Peripheral bus 7 divisor - STORAGE(PB8DIV); break; // Peripheral bus 8 divisor + WRITEOP(REFO1CON); return; + WRITEOP(REFO2CON); return; + WRITEOP(REFO3CON); return; + WRITEOP(REFO4CON); return; + WRITEOP(PB1DIV); return; // Peripheral bus 1 divisor + WRITEOP(PB2DIV); return; // Peripheral bus 2 divisor + WRITEOP(PB3DIV); return; // Peripheral bus 3 divisor + WRITEOP(PB4DIV); return; // Peripheral bus 4 divisor + WRITEOP(PB5DIV); return; // Peripheral bus 5 divisor + WRITEOP(PB7DIV); return; // Peripheral bus 7 divisor + WRITEOP(PB8DIV); return; // Peripheral bus 8 divisor /*------------------------------------------------------------------------- * Peripheral port select registers: input. @@ -1654,10 +2129,43 @@ irq: update_irq_status(s); WRITEOP(SPI4BRG); return; // Baud rate WRITEOP(SPI4CON2); return; // Control 2 + /* + * Timers 1-9. + */ + WRITEOP(T1CON); return; + WRITEOP(TMR1); return; + WRITEOP(PR1); return; + WRITEOP(T2CON); return; + WRITEOP(TMR2); return; + WRITEOP(PR2); return; + WRITEOP(T3CON); return; + WRITEOP(TMR3); return; + WRITEOP(PR3); return; + WRITEOP(T4CON); return; + WRITEOP(TMR4); return; + WRITEOP(PR4); return; + WRITEOP(T5CON); return; + WRITEOP(TMR5); return; + WRITEOP(PR5); return; + WRITEOP(T6CON); return; + WRITEOP(TMR6); return; + WRITEOP(PR6); return; + WRITEOP(T7CON); return; + WRITEOP(TMR7); return; + WRITEOP(PR7); return; + WRITEOP(T8CON); return; + WRITEOP(TMR8); return; + WRITEOP(PR8); return; + WRITEOP(T9CON); return; + WRITEOP(TMR9); return; + WRITEOP(PR9); return; + /*------------------------------------------------------------------------- * Ethernet. */ - WRITEOP(ETHCON1); return; // Control 1 + WRITEOP(ETHCON1); // Control 1 + pic32_eth_control(s); + return; WRITEOP(ETHCON2); return; // Control 2: RX data buffer size WRITEOP(ETHTXST); return; // Tx descriptor start address WRITEOP(ETHRXST); return; // Rx descriptor start address @@ -1688,15 +2196,128 @@ irq: update_irq_status(s); WRITEOP(EMAC1SUPP); return; // MAC PHY support WRITEOP(EMAC1TEST); return; // MAC test WRITEOP(EMAC1MCFG); return; // MII configuration - WRITEOP(EMAC1MCMD); return; // MII command + WRITEOP(EMAC1MCMD); // MII command + pic32_mii_command(s); + return; WRITEOP(EMAC1MADR); return; // MII address - WRITEOP(EMAC1MWTD); return; // MII write data + WRITEOP(EMAC1MWTD); // MII write data + pic32_mii_write(s); + return; WRITEOP(EMAC1MRDD); return; // MII read data WRITEOP(EMAC1MIND); return; // MII indicators WRITEOP(EMAC1SA0); return; // MAC station address 0 WRITEOP(EMAC1SA1); return; // MAC station address 1 WRITEOP(EMAC1SA2); return; // MAC station address 2 + /*------------------------------------------------------------------------- + * USB. + */ + STORAGE(USBCSR0); break; + STORAGE(USBCSR1); break; + STORAGE(USBCSR2); break; + STORAGE(USBCSR3); break; + STORAGE(USBIENCSR0); break; + STORAGE(USBIENCSR1); break; + STORAGE(USBIENCSR2); break; + STORAGE(USBIENCSR3); break; + STORAGE(USBFIFO0); break; + STORAGE(USBFIFO1); break; + STORAGE(USBFIFO2); break; + STORAGE(USBFIFO3); break; + STORAGE(USBFIFO4); break; + STORAGE(USBFIFO5); break; + STORAGE(USBFIFO6); break; + STORAGE(USBFIFO7); break; + STORAGE(USBOTG); break; + STORAGE(USBFIFOA); break; + STORAGE(USBHWVER); break; + STORAGE(USBINFO); break; + STORAGE(USBEOFRST); break; + STORAGE(USBE0TXA); break; + STORAGE(USBE0RXA); break; + STORAGE(USBE1TXA); break; + STORAGE(USBE1RXA); break; + STORAGE(USBE2TXA); break; + STORAGE(USBE2RXA); break; + STORAGE(USBE3TXA); break; + STORAGE(USBE3RXA); break; + STORAGE(USBE4TXA); break; + STORAGE(USBE4RXA); break; + STORAGE(USBE5TXA); break; + STORAGE(USBE5RXA); break; + STORAGE(USBE6TXA); break; + STORAGE(USBE6RXA); break; + STORAGE(USBE7TXA); break; + STORAGE(USBE7RXA); break; + STORAGE(USBE0CSR0); break; + STORAGE(USBE0CSR2); break; + STORAGE(USBE0CSR3); break; + STORAGE(USBE1CSR0); break; + STORAGE(USBE1CSR1); break; + STORAGE(USBE1CSR2); break; + STORAGE(USBE1CSR3); break; + STORAGE(USBE2CSR0); break; + STORAGE(USBE2CSR1); break; + STORAGE(USBE2CSR2); break; + STORAGE(USBE2CSR3); break; + STORAGE(USBE3CSR0); break; + STORAGE(USBE3CSR1); break; + STORAGE(USBE3CSR2); break; + STORAGE(USBE3CSR3); break; + STORAGE(USBE4CSR0); break; + STORAGE(USBE4CSR1); break; + STORAGE(USBE4CSR2); break; + STORAGE(USBE4CSR3); break; + STORAGE(USBE5CSR0); break; + STORAGE(USBE5CSR1); break; + STORAGE(USBE5CSR2); break; + STORAGE(USBE5CSR3); break; + STORAGE(USBE6CSR0); break; + STORAGE(USBE6CSR1); break; + STORAGE(USBE6CSR2); break; + STORAGE(USBE6CSR3); break; + STORAGE(USBE7CSR0); break; + STORAGE(USBE7CSR1); break; + STORAGE(USBE7CSR2); break; + STORAGE(USBE7CSR3); break; + STORAGE(USBDMAINT); break; + STORAGE(USBDMA1C); break; + STORAGE(USBDMA1A); break; + STORAGE(USBDMA1N); break; + STORAGE(USBDMA2C); break; + STORAGE(USBDMA2A); break; + STORAGE(USBDMA2N); break; + STORAGE(USBDMA3C); break; + STORAGE(USBDMA3A); break; + STORAGE(USBDMA3N); break; + STORAGE(USBDMA4C); break; + STORAGE(USBDMA4A); break; + STORAGE(USBDMA4N); break; + STORAGE(USBDMA5C); break; + STORAGE(USBDMA5A); break; + STORAGE(USBDMA5N); break; + STORAGE(USBDMA6C); break; + STORAGE(USBDMA6A); break; + STORAGE(USBDMA6N); break; + STORAGE(USBDMA7C); break; + STORAGE(USBDMA7A); break; + STORAGE(USBDMA7N); break; + STORAGE(USBDMA8C); break; + STORAGE(USBDMA8A); break; + STORAGE(USBDMA8N); break; + STORAGE(USBE1RPC); break; + STORAGE(USBE2RPC); break; + STORAGE(USBE3RPC); break; + STORAGE(USBE4RPC); break; + STORAGE(USBE5RPC); break; + STORAGE(USBE6RPC); break; + STORAGE(USBE7RPC); break; + STORAGE(USBDPBFD); break; + STORAGE(USBTMCON1); break; + STORAGE(USBTMCON2); break; + STORAGE(USBLPMR1); break; + STORAGE(USBLMPR2); break; + default: printf("--- Write %08x to 1f8%05x: peripheral register not supported\n", data, offset); @@ -2015,6 +2636,10 @@ static void pic32_init(MachineState *machine, int board_type) pic32_sdcard_init(s, 0, "sd0", sd0_file, cs0_port, cs0_pin); pic32_sdcard_init(s, 1, "sd1", sd1_file, cs1_port, cs1_pin); + /* Ethernet. */ + if (nd_table[0].used) + pic32_eth_init(s, &nd_table[0]); + io_reset(s); pic32_sdcard_reset(s); pic32_pass_signal_chars(); diff --git a/hw/mips/pic32_ethernet.c b/hw/mips/pic32_ethernet.c new file mode 100644 index 0000000000000..9be00d6eb69c8 --- /dev/null +++ b/hw/mips/pic32_ethernet.c @@ -0,0 +1,530 @@ +/* + * Ethernet port. + * + * Copyright (C) 2014-2015 Serge Vakulenko + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of the author not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * + * The author disclaim all warranties with regard to this + * software, including all implied warranties of merchantability + * and fitness. In no event shall the author be liable for any + * special, indirect or consequential damages or any damages + * whatsoever resulting from loss of use, data or profits, whether + * in an action of contract, negligence or other tortious action, + * arising out of or in connection with the use or performance of + * this software. + */ +#include "hw/hw.h" +#include "exec/address-spaces.h" +#include "sysemu/dma.h" +#include "pic32_peripherals.h" + +#include "pic32mz.h" + +//#define TRACE printf +#ifndef TRACE +#define TRACE(...) /*empty*/ +#endif + +#define NAME_PIC32_ETH "pic32-eth" + +#define MIN_RX_SIZE 60 + +/* + * PIC32 Ethernet device. + */ +struct _eth_t { + SysBusDevice parent_obj; + + pic32_t *pic32; + NICState *eth_nic; /* virtual network interface */ + NICConf eth_conf; /* network configuration */ + + uint16_t phy_reg[32]; /* PHY registers */ + +}; + +/* + * DMA buffer descriptor. + */ +typedef struct { + uint32_t hdr; /* Flags */ + uint32_t paddr; /* Phys address of data buffer */ + uint32_t ctl; /* TX options / RX filter status */ + uint32_t status; /* Status */ +} eth_desc_t; + +/* Start of packet */ +#define DESC_SOP(d) ((d)->hdr & 0x80000000) +#define DESC_SET_SOP(d) ((d)->hdr |= 0x80000000) +#define DESC_CLEAR_SOP(d) ((d)->hdr &= ~0x80000000) + +/* End of packet */ +#define DESC_EOP(d) ((d)->hdr & 0x40000000) +#define DESC_SET_EOP(d) ((d)->hdr |= 0x40000000) +#define DESC_CLEAR_EOP(d) ((d)->hdr &= ~0x40000000) + +/* Number of data bytes */ +#define DESC_BYTECNT(d) ((d)->hdr >> 16 & 0x7ff) +#define DESC_SET_BYTECNT(d,n) ((d)->hdr = ((d)->hdr & ~0x7ff0000) | (n) << 16) + +/* Next descriptor pointer valid */ +#define DESC_NPV(d) ((d)->hdr & 0x00000100) +#define DESC_SET_NPV(d) ((d)->hdr |= 0x00000100) +#define DESC_CLEAR_NPV(d) ((d)->hdr &= ~0x00000100) + +/* Eth controller owns this desc */ +#define DESC_EOWN(d) ((d)->hdr & 0x00000080) +#define DESC_SET_EOWN(d) ((d)->hdr |= 0x00000080) +#define DESC_CLEAR_EOWN(d) ((d)->hdr &= ~0x00000080) + +/* Size of received packet */ +#define DESC_FRAMESZ(d) ((d)->status & 0xffff) +#define DESC_SET_FRAMESZ(d,n) ((d)->status = ((d)->status & ~0xffff) | (n)) + +/* Receive filter status */ +#define DESC_RXF(d) ((d)->ctl >> 24) +#define DESC_SET_RXF(d,n) ((d)->ctl = ((d)->ctl & 0xffffff) | (n) << 24) + +/*------------------------------------------------------------- + * PHY declarations for SMSC LAN8720A/8740A chip. + */ +#define PHY_CONTROL 0 /* Basic Control Register */ +#define PHY_STATUS 1 /* Basic Status Register */ +#define PHY_ID1 2 /* PHY identifier 1 */ +#define PHY_ID2 3 /* PHY identifier 2 */ +#define PHY_MODE 18 /* Special Modes */ +#define PHY_SPECIAL 31 /* Special Control/Status Register */ + +#define PHY_CONTROL_RESET 0x8000 /* Soft reset, bit self cleared */ + +#define PHY_STATUS_CAP_100_FDX 0x4000 /* Can do 100Base-TX full duplex */ +#define PHY_STATUS_CAP_100_HDX 0x2000 /* Can do 100Base-TX half duplex */ +#define PHY_STATUS_CAP_10_FDX 0x1000 /* Can do 10Base-TX full duplex */ +#define PHY_STATUS_CAP_10_HDX 0x0800 /* Can do 10Base-TX half duplex */ +#define PHY_STATUS_ANEG_ACK 0x0020 /* Auto-negotiation acknowledge */ +#define PHY_STATUS_CAP_ANEG 0x0008 /* Auto-negotiation available */ +#define PHY_STATUS_LINK 0x0004 /* Link valid */ + +#define PHY_MODE_PHYAD 0x000f /* PHY address mask */ + +#define PHY_SPECIAL_AUTODONE 0x1000 /* Auto-negotiation is done */ +#define PHY_SPECIAL_FDX 0x0010 /* Full duplex */ +#define PHY_SPECIAL_100 0x0008 /* Speed 100 Mbps */ + +/* + * Reset the PHY chip. + */ +static void phy_reset(eth_t *e) +{ + TRACE("--- PHY reset\n"); + e->phy_reg[PHY_ID1] = 0x0007; /* Vendor: SMSC */ + e->phy_reg[PHY_ID2] = 0xc111; /* Device: LAN8740A */ + e->phy_reg[PHY_CONTROL] = 0x1000; + e->phy_reg[PHY_MODE] = 0x4000; /* RMII interface */ + e->phy_reg[PHY_STATUS] = PHY_STATUS_ANEG_ACK | + PHY_STATUS_CAP_ANEG | + PHY_STATUS_LINK | + PHY_STATUS_CAP_100_FDX | + PHY_STATUS_CAP_100_HDX | + PHY_STATUS_CAP_10_FDX | + PHY_STATUS_CAP_10_HDX; + e->phy_reg[PHY_SPECIAL] = PHY_SPECIAL_AUTODONE | + PHY_SPECIAL_FDX | + PHY_SPECIAL_100; +} + +/* + * Reset the Ethernet controller. + */ +static void eth_reset(eth_t *e) +{ + uint8_t *macaddr = e->eth_conf.macaddr.a; + pic32_t *s = e->pic32; + + TRACE("--- %s()\n", __func__); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Ethernet reset\n"); + s->irq_clear(s, PIC32_IRQ_ETH); + VALUE(ETHSTAT) = 0; + VALUE(EMAC1SA2) = macaddr[0] | (macaddr[1] << 8); + VALUE(EMAC1SA1) = macaddr[2] | (macaddr[3] << 8); + VALUE(EMAC1SA0) = macaddr[4] | (macaddr[5] << 8); +} + +/* + * Write to ETHCON1 register. + */ +void pic32_eth_control(pic32_t *s) +{ + eth_t *e = s->eth; + + if (! (VALUE(ETHCON1) & PIC32_ETHCON1_ON)) { + /* Ethernet controller is disabled. */ + TRACE("--- %s() ETH disabled\n", __func__); + eth_reset(e); + return; + } + + if (VALUE(ETHCON1) & PIC32_ETHCON1_TXRTS) { + /* Transmit request. */ + eth_desc_t d = { 0 }; + unsigned paddr = VALUE(ETHTXST); + unsigned nbytes, i; + unsigned char buf[2048]; + + d.hdr = ldl_le_phys(&address_space_memory, paddr); + d.paddr = ldl_le_phys(&address_space_memory, paddr + 4); + + nbytes = DESC_BYTECNT(&d); + TRACE("--- %s() trasmit request %u bytes\n", __func__, nbytes); + TRACE("--- TX desc [%08x] = %08x %08x\n", paddr, d.hdr, d.paddr); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Ethernet transmit request, %u bytes\n", nbytes); + if (nbytes > 0 && nbytes <= sizeof(buf)) { + for (i=0; ieth_nic), buf, nbytes); + } + + /* Activate TXDONE interrupt. */ + VALUE(ETHCON1) &= ~PIC32_ETHCON1_TXRTS; + VALUE(ETHIRQ) |= PIC32_ETHIRQ_TXDONE; + s->irq_raise(s, PIC32_IRQ_ETH); + } +} + +/* + * Write to EMAC1MCMD register. + */ +void pic32_mii_command(pic32_t *s) +{ + eth_t *e = s->eth; + unsigned cmd = VALUE(EMAC1MCMD); + unsigned addr = VALUE(EMAC1MADR); + unsigned data; + + if (cmd & (PIC32_EMAC1MCMD_READ | PIC32_EMAC1MCMD_SCAN)) { + data = e->phy_reg[addr & 0x1f]; + //TRACE("--- %s() cmd = %04x, addr = %04x\n", __func__, cmd, addr); + TRACE("--- %s() read register [%u] = %04x\n", __func__, addr & 0x1f, data); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Ethernet MII read register [%u] = %04x\n", + addr & 0x1f, data); + VALUE(EMAC1MRDD) = data; + } +} + +/* + * Write to EMAC1MWTD register. + */ +void pic32_mii_write(pic32_t *s) +{ + eth_t *e = s->eth; + unsigned addr = VALUE(EMAC1MADR); + unsigned data = VALUE(EMAC1MWTD); + + TRACE("--- %s() write register [%u] = %04x\n", __func__, addr & 0x1f, data); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Ethernet MII write register [%u] = %04x\n", + addr & 0x1f, data); + switch (addr & 0x1f) { + case PHY_CONTROL: /* Basic Control Register */ + e->phy_reg[PHY_CONTROL] = data; + if (data & PHY_CONTROL_RESET) { + phy_reset(e); + } + break; + } +} + +/* + * Return true when no receive buffers available. + */ +static int eth_buffer_full(pic32_t *s) +{ + eth_desc_t d = { 0 }; + + d.hdr = ldl_le_phys(&address_space_memory, VALUE(ETHRXST)); + return !DESC_EOWN(&d); +} + +/* + * Return true when we are ready to receive a packet. + */ +static int nic_can_receive(NetClientState *nc) +{ + eth_t *e = qemu_get_nic_opaque(nc); + pic32_t *s = e->pic32; + + //TRACE("--- %s()\n", __func__); + if (! (VALUE(ETHCON1) & PIC32_ETHCON1_ON)) { + /* While interface is down, + * we can receive anything (and discard). */ + return 1; + } + + /* Check whether we have at least one receive buffer available. */ + return !eth_buffer_full(s); +} + +/* + * Receive a packet. + */ +static ssize_t nic_receive(NetClientState *nc, const uint8_t *buf, size_t size) +{ + eth_t *e = qemu_get_nic_opaque(nc); + pic32_t *s = e->pic32; + unsigned rxfc, rxf, rxst, rxst0, rxbufsz, nbytes, len; + int start_of_packet; + uint8_t buf1[60]; + eth_desc_t *d, desc0, desc1; + + TRACE("--- %s: %d bytes\n", __func__, (int) size); + if (qemu_loglevel_mask(CPU_LOG_INSTR)) + fprintf(qemu_logfile, "--- Ethernet receive, %u bytes\n", (unsigned)size); + if (! (VALUE(ETHCON1) & PIC32_ETHCON1_ON)) { + /* Ethernet controller is down. */ + return -1; + } + + if (eth_buffer_full(s)) + return -1; + + /* Cast acceptance filter. */ + rxfc = VALUE(ETHRXFC); + if (buf[0] == 0xff && buf[1] == 0xff && buf[2] == 0xff && + buf[3] == 0xff && buf[4] == 0xff && buf[5] == 0xff) { + /* Broadcast address. */ + if (! (rxfc & PIC32_ETHRXFC_BCEN)) + return size; + rxf = 0x40; + } else if (buf[0] & 0x01) { + /* Multicast. */ + if (! (rxfc & PIC32_ETHRXFC_MCEN)) + return size; + rxf = 0x80; + } else if (VALUE(EMAC1SA2) == (buf[0] | (buf[1] << 8)) || + VALUE(EMAC1SA2) == (buf[2] | (buf[3] << 8)) || + VALUE(EMAC1SA2) == (buf[4] | (buf[5] << 8))) { + /* Unicast for our MAC address. */ + if (! (rxfc & PIC32_ETHRXFC_UCEN)) + return size; + rxf = 0x20; + } else { + /* Not-Me Unicast. */ + if (! (rxfc & PIC32_ETHRXFC_NOTMEEN)) + return size; + rxf = 0x00; + } + + /* If packet too small, then expand it */ + nbytes = size; + if (nbytes < MIN_RX_SIZE) { + memcpy(buf1, buf, nbytes); + memset(buf1 + nbytes, 0, MIN_RX_SIZE - nbytes); + buf = buf1; + nbytes = MIN_RX_SIZE; + } + + /* Copy data to descriptor chain. */ + rxst0 = VALUE(ETHRXST); + rxbufsz = VALUE(ETHCON2) & 0x7f0; + start_of_packet = 1; + d = &desc0; + rxst = rxst0; + for (;;) { + /* Get descriptor. */ + dma_memory_read(&address_space_memory, rxst, d, 16); + if (! DESC_EOWN(d) || (! start_of_packet && rxst == rxst0)) { + TRACE("--- No more descriptors available\n"); + VALUE(ETHIRQ) |= PIC32_ETHIRQ_RXBUFNA; + break; + } + + /* Copy data to buffer. */ + len = nbytes; + if (len > rxbufsz) + len = rxbufsz; + TRACE("--- Copy %d bytes to %08x\n", len, d->paddr); + dma_memory_write(&address_space_memory, d->paddr, buf, len); + buf += len; + + /* Update the descriptor. */ + DESC_CLEAR_EOWN(d); + DESC_SET_BYTECNT(d, len); + if (start_of_packet) { + DESC_SET_SOP(d); + DESC_SET_FRAMESZ(d, nbytes); + DESC_SET_RXF(d, rxf); + start_of_packet = 0; + } else + DESC_CLEAR_SOP(d); + if (nbytes == len) + DESC_SET_EOP(d); + else + DESC_CLEAR_EOP(d); + + /* Write the descriptor back memory (all but the first). */ + if (d == &desc1) { + TRACE("--- RX desc [%08x] = %08x ... ... %08x\n", rxst, desc1.hdr, desc1.status); + dma_memory_write(&address_space_memory, rxst, &desc1, 16); + } + + /* Switch to next descriptor. */ + rxst += 16; + if (DESC_NPV(d)) + rxst = ldl_le_phys(&address_space_memory, rxst); + VALUE(ETHRXST) = rxst; + d = &desc1; + + nbytes -= len; + if (nbytes == 0) { + /* Update the first descriptor. */ + TRACE("--- RX desc [%08x] = %08x ... ... %08x\n", rxst0, desc0.hdr, desc0.status); + dma_memory_write(&address_space_memory, rxst0, &desc0, 16); + + /* Packet successfully received. */ + VALUE(ETHIRQ) |= PIC32_ETHIRQ_RXDONE; + break; + } + } + + /* Activate interrupt. */ + s->irq_raise(s, PIC32_IRQ_ETH); + return size; +} + +/* + * Deallocate the QEMU network interface. + */ +static void nic_cleanup(NetClientState *nc) +{ + eth_t *e = qemu_get_nic_opaque(nc); + + //TRACE("--- %s()\n", __func__); + e->eth_nic = 0; +} + +/* + * Initialize Ethernet device. + */ +void pic32_eth_init(pic32_t *s, NICInfo *nd) +{ + TRACE("--- %s()\n", __func__); + + /* Create Ethernet device. */ + s->eth_dev = qdev_create(NULL, NAME_PIC32_ETH); + qdev_set_nic_properties(s->eth_dev, nd); + qdev_init_nofail(s->eth_dev); + + /* Setup back pointer from Ethernet device to pic32 object. */ + s->eth = OBJECT_CHECK(eth_t, s->eth_dev, NAME_PIC32_ETH); + s->eth->pic32 = s; +} + +/* + * Initialize pic32-eth object. + */ +static int eth_object_init(SysBusDevice *sbd) +{ + /* Table of methods for QEMU network interface. */ + static NetClientInfo nic_info = { + .type = NET_CLIENT_OPTIONS_KIND_NIC, + .size = sizeof(NICState), + .can_receive = nic_can_receive, + .receive = nic_receive, + .cleanup = nic_cleanup, + }; + DeviceState *dev = DEVICE(sbd); + eth_t *e = OBJECT_CHECK(eth_t, dev, NAME_PIC32_ETH); + + //TRACE("--- %s()\n", __func__); + + /* Initialize MAC address. */ + qemu_macaddr_default_if_unset(&e->eth_conf.macaddr); + + /* Create a QEMU network interface. */ + e->eth_nic = qemu_new_nic(&nic_info, &e->eth_conf, + object_get_typename(OBJECT(dev)), dev->id, e); + + qemu_format_nic_info_str(qemu_get_queue(e->eth_nic), + e->eth_conf.macaddr.a); + + return 0; +} + +/* + * Reset pic32-eth object. + */ +static void eth_object_reset(DeviceState *dev) +{ + eth_t *e = OBJECT_CHECK(eth_t, dev, NAME_PIC32_ETH); + + //TRACE("--- %s()\n", __func__); + eth_reset(e); + phy_reset(e); +} + +/* + * Descriptor of eth_t data structure. + */ +static const VMStateDescription vmstate_info = { + .name = NAME_PIC32_ETH, + .version_id = 0, + .minimum_version_id = 0, + .fields = (VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +/* + * Build pic32-eth object. + */ +static void eth_object_constructor(ObjectClass *klass, void *data) +{ + static Property eth_properties[] = { + DEFINE_NIC_PROPERTIES(eth_t, eth_conf), + DEFINE_PROP_END_OF_LIST(), + }; + DeviceClass *dc = DEVICE_CLASS(klass); + SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + + k->init = eth_object_init; + set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); + dc->desc = "PIC32 Ethernet device"; + dc->reset = eth_object_reset; + dc->vmsd = &vmstate_info; + dc->props = eth_properties; +} + +/* + * Instantiate pic32-eth class. + */ +static void eth_register_types(void) +{ + static const TypeInfo eth_class_info = { + .name = NAME_PIC32_ETH, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(eth_t), + .class_init = eth_object_constructor, + }; + + type_register_static(ð_class_info); +} + +type_init(eth_register_types) diff --git a/hw/mips/pic32_peripherals.h b/hw/mips/pic32_peripherals.h index 243ed67b03f06..4d95fd2826318 100644 --- a/hw/mips/pic32_peripherals.h +++ b/hw/mips/pic32_peripherals.h @@ -22,6 +22,7 @@ * this software. */ #include "hw/sysbus.h" /* SysBusDevice */ +#include "net/net.h" #define IO_MEM_SIZE (1024*1024) /* 1 Mbyte */ @@ -29,6 +30,7 @@ typedef struct _uart_t uart_t; typedef struct _spi_t spi_t; typedef struct _sdcard_t sdcard_t; typedef struct _pic32_t pic32_t; +typedef struct _eth_t eth_t; /* * UART private data. @@ -97,6 +99,9 @@ struct _pic32_t { unsigned sdcard_spi_port; /* SPI port number of SD card */ sdcard_t sdcard [2]; /* SD card data */ + DeviceState *eth_dev; /* Ethernet device */ + eth_t *eth; /* Ethernet driver data */ + void (*irq_raise)(pic32_t *s, int irq); /* set interrupt request */ void (*irq_clear)(pic32_t *s, int irq); /* clear interrupt request */ }; @@ -133,6 +138,14 @@ void pic32_sdcard_reset(pic32_t *s); void pic32_sdcard_select(pic32_t *s, int unit, int on); unsigned pic32_sdcard_io(pic32_t *s, unsigned data); +/* + * Ethernet routines. + */ +void pic32_eth_init(pic32_t *s, NICInfo *nd); +void pic32_eth_control(pic32_t *s); +void pic32_mii_command(pic32_t *s); +void pic32_mii_write(pic32_t *s); + /* * Load a binary file in hex or srec format. */ @@ -160,5 +173,4 @@ int pic32_load_hex_file(const char *filename, case name+4: *namep = #name"CLR"; goto op_##name;\ case name+8: *namep = #name"SET"; goto op_##name;\ case name+12: *namep = #name"INV"; op_##name: \ - VALUE(name) &= romask; \ - VALUE(name) |= write_op(VALUE(name), data, offset) & ~(romask) + VALUE(name) = (VALUE(name) & (romask)) | (write_op(VALUE(name), data, offset) & ~(romask)) diff --git a/hw/mips/pic32mx.h b/hw/mips/pic32mx.h index ebb929286c948..e5d14b143fae4 100644 --- a/hw/mips/pic32mx.h +++ b/hw/mips/pic32mx.h @@ -764,7 +764,13 @@ * System controller registers. */ #define OSCCON PIC32_R (0xf000) +#define OSCCONCLR PIC32_R (0xf004) +#define OSCCONSET PIC32_R (0xf008) +#define OSCCONINV PIC32_R (0xf00c) #define OSCTUN PIC32_R (0xf010) +#define OSCTUNCLR PIC32_R (0xf014) +#define OSCTUNSET PIC32_R (0xf018) +#define OSCTUNINV PIC32_R (0xf01c) #define DDPCON PIC32_R (0xf200) /* Debug Data Port Control */ #define DEVID PIC32_R (0xf220) #define SYSKEY PIC32_R (0xf230) @@ -777,9 +783,36 @@ #define RSWRSTSET PIC32_R (0xf618) #define RSWRSTINV PIC32_R (0xf61C) +/* + * Oscillator control register. + */ +#define PIC32_OSCCON_UNUSED 0xc0a08800 +#define PIC32_OSCCON_OSWEN 0x00000001 +#define PIC32_OSCCON_SOSCEN 0x00000002 +#define PIC32_OSCCON_UFRCEN 0x00000004 +#define PIC32_OSCCON_CF 0x00000008 +#define PIC32_OSCCON_SLPEN 0x00000010 +#define PIC32_OSCCON_SLOCK 0x00000020 +#define PIC32_OSCCON_ULOCK 0x00000040 +#define PIC32_OSCCON_CLKLOCK 0x00000080 +#define PIC32_OSCCON_NOSC 0x00000700 +#define PIC32_OSCCON_COSC 0x00007000 +#define PIC32_OSCCON_PLLMULT 0x00070000 +#define PIC32_OSCCON_PBDIV 0x00180000 +#define PIC32_OSCCON_SOSCRDY 0x00400000 +#define PIC32_OSCCON_FRCDIV 0x07000000 +#define PIC32_OSCCON_PLLODIV 0x38000000 + +/* + * Oscillator tune register. + */ +#define PIC32_OSCTUN_UNUSED 0xffffffc0 +#define PIC32_OSCTUN_TUN 0x0000003f + /* * Reset control register. */ +#define PIC32_RCON_UNUSED 0xfffffc20 #define PIC32_RCON_POR 0x00000001 #define PIC32_RCON_BOR 0x00000002 #define PIC32_RCON_IDLE 0x00000004 diff --git a/hw/mips/pic32mz.h b/hw/mips/pic32mz.h index f46e5e052a786..0ed92b24ba3c5 100644 --- a/hw/mips/pic32mz.h +++ b/hw/mips/pic32mz.h @@ -24,6 +24,47 @@ #ifndef _IO_PIC32MZ_H #define _IO_PIC32MZ_H +/* + * Register memory map: + * + * BF80 0000...03FF Configuration + * BF80 0600...07FF Flash Controller + * BF80 0800...09FF Watchdog Timer + * BF80 0A00...0BFF Deadman Timer + * BF80 0C00...0DFF RTCC + * BF80 0E00...0FFF CVref + * BF80 1200...13FF Oscillator + * BF80 1400...17FF PPS + * + * BF81 0000...0FFF Interrupt Controller + * BF81 1000...1FFF DMA + * + * BF82 0000...09FF I2C1 - I2C5 + * BF82 1000...1BFF SPI1 - SPI6 + * BF82 2000...2BFF UART1 - UART6 + * BF82 E000...E1FF PMP + * + * BF84 0000...11FF Timer1 - Timer9 + * BF84 2000...31FF IC1 - IC9 + * BF84 4000...51FF OC1 - OC9 + * BF84 B000...B3FF ADC1 + * BF84 C000...C1FF Comparator 1, 2 + * + * BF86 0000...09FF PORTA - PORTK + * + * BF88 0000...1FFF CAN1 and CAN2 + * BF88 2000...2FFF Ethernet + * + * BF8E 0000...0FFF Prefetch + * BF8E 1000...1FFF EBI + * BF8E 2000...2FFF SQI1 + * BF8E 3000...3FFF USB + * BF8E 5000...5FFF Crypto + * BF8E 6000...6FFF RNG + * + * BF8F 0000...FFFF System Bus + */ + /*-------------------------------------- * Configuration registers. */ @@ -576,6 +617,118 @@ #define CNSTATKSET PIC32_R (0x60998) #define CNSTATKINV PIC32_R (0x6099C) +/*-------------------------------------- + * Timer registers. + */ +#define T1CON PIC32_R (0x40000) /* Timer 1: Control */ +#define T1CONCLR PIC32_R (0x40004) +#define T1CONSET PIC32_R (0x40008) +#define T1CONINV PIC32_R (0x4000C) +#define TMR1 PIC32_R (0x40010) /* Timer 1: Count */ +#define TMR1CLR PIC32_R (0x40014) +#define TMR1SET PIC32_R (0x40018) +#define TMR1INV PIC32_R (0x4001C) +#define PR1 PIC32_R (0x40020) /* Timer 1: Period register */ +#define PR1CLR PIC32_R (0x40024) +#define PR1SET PIC32_R (0x40028) +#define PR1INV PIC32_R (0x4002C) +#define T2CON PIC32_R (0x40200) /* Timer 2: Control */ +#define T2CONCLR PIC32_R (0x40204) +#define T2CONSET PIC32_R (0x40208) +#define T2CONINV PIC32_R (0x4020C) +#define TMR2 PIC32_R (0x40210) /* Timer 2: Count */ +#define TMR2CLR PIC32_R (0x40214) +#define TMR2SET PIC32_R (0x40218) +#define TMR2INV PIC32_R (0x4021C) +#define PR2 PIC32_R (0x40220) /* Timer 2: Period register */ +#define PR2CLR PIC32_R (0x40224) +#define PR2SET PIC32_R (0x40228) +#define PR2INV PIC32_R (0x4022C) +#define T3CON PIC32_R (0x40400) /* Timer 3: Control */ +#define T3CONCLR PIC32_R (0x40404) +#define T3CONSET PIC32_R (0x40408) +#define T3CONINV PIC32_R (0x4040C) +#define TMR3 PIC32_R (0x40410) /* Timer 3: Count */ +#define TMR3CLR PIC32_R (0x40414) +#define TMR3SET PIC32_R (0x40418) +#define TMR3INV PIC32_R (0x4041C) +#define PR3 PIC32_R (0x40420) /* Timer 3: Period register */ +#define PR3CLR PIC32_R (0x40424) +#define PR3SET PIC32_R (0x40428) +#define PR3INV PIC32_R (0x4042C) +#define T4CON PIC32_R (0x40600) /* Timer 4: Control */ +#define T4CONCLR PIC32_R (0x40604) +#define T4CONSET PIC32_R (0x40608) +#define T4CONINV PIC32_R (0x4060C) +#define TMR4 PIC32_R (0x40610) /* Timer 4: Count */ +#define TMR4CLR PIC32_R (0x40614) +#define TMR4SET PIC32_R (0x40618) +#define TMR4INV PIC32_R (0x4061C) +#define PR4 PIC32_R (0x40620) /* Timer 4: Period register */ +#define PR4CLR PIC32_R (0x40624) +#define PR4SET PIC32_R (0x40628) +#define PR4INV PIC32_R (0x4062C) +#define T5CON PIC32_R (0x40800) /* Timer 5: Control */ +#define T5CONCLR PIC32_R (0x40804) +#define T5CONSET PIC32_R (0x40808) +#define T5CONINV PIC32_R (0x4080C) +#define TMR5 PIC32_R (0x40810) /* Timer 5: Count */ +#define TMR5CLR PIC32_R (0x40814) +#define TMR5SET PIC32_R (0x40818) +#define TMR5INV PIC32_R (0x4081C) +#define PR5 PIC32_R (0x40820) /* Timer 5: Period register */ +#define PR5CLR PIC32_R (0x40824) +#define PR5SET PIC32_R (0x40828) +#define PR5INV PIC32_R (0x4082C) +#define T6CON PIC32_R (0x40A00) /* Timer 6: Control */ +#define T6CONCLR PIC32_R (0x40A04) +#define T6CONSET PIC32_R (0x40A08) +#define T6CONINV PIC32_R (0x40A0C) +#define TMR6 PIC32_R (0x40A10) /* Timer 6: Count */ +#define TMR6CLR PIC32_R (0x40A14) +#define TMR6SET PIC32_R (0x40A18) +#define TMR6INV PIC32_R (0x40A1C) +#define PR6 PIC32_R (0x40A20) /* Timer 6: Period register */ +#define PR6CLR PIC32_R (0x40A24) +#define PR6SET PIC32_R (0x40A28) +#define PR6INV PIC32_R (0x40A2C) +#define T7CON PIC32_R (0x40C00) /* Timer 7: Control */ +#define T7CONCLR PIC32_R (0x40C04) +#define T7CONSET PIC32_R (0x40C08) +#define T7CONINV PIC32_R (0x40C0C) +#define TMR7 PIC32_R (0x40C10) /* Timer 7: Count */ +#define TMR7CLR PIC32_R (0x40C14) +#define TMR7SET PIC32_R (0x40C18) +#define TMR7INV PIC32_R (0x40C1C) +#define PR7 PIC32_R (0x40C20) /* Timer 7: Period register */ +#define PR7CLR PIC32_R (0x40C24) +#define PR7SET PIC32_R (0x40C28) +#define PR7INV PIC32_R (0x40C2C) +#define T8CON PIC32_R (0x40E00) /* Timer 8: Control */ +#define T8CONCLR PIC32_R (0x40E04) +#define T8CONSET PIC32_R (0x40E08) +#define T8CONINV PIC32_R (0x40E0C) +#define TMR8 PIC32_R (0x40E10) /* Timer 8: Count */ +#define TMR8CLR PIC32_R (0x40E14) +#define TMR8SET PIC32_R (0x40E18) +#define TMR8INV PIC32_R (0x40E1C) +#define PR8 PIC32_R (0x40E20) /* Timer 8: Period register */ +#define PR8CLR PIC32_R (0x40E24) +#define PR8SET PIC32_R (0x40E28) +#define PR8INV PIC32_R (0x40E2C) +#define T9CON PIC32_R (0x41000) /* Timer 9: Control */ +#define T9CONCLR PIC32_R (0x41004) +#define T9CONSET PIC32_R (0x41008) +#define T9CONINV PIC32_R (0x4100C) +#define TMR9 PIC32_R (0x41010) /* Timer 9: Count */ +#define TMR9CLR PIC32_R (0x41014) +#define TMR9SET PIC32_R (0x41018) +#define TMR9INV PIC32_R (0x4101C) +#define PR9 PIC32_R (0x41020) /* Timer 9: Period register */ +#define PR9CLR PIC32_R (0x41024) +#define PR9SET PIC32_R (0x41028) +#define PR9INV PIC32_R (0x4102C) + /*-------------------------------------- * Parallel master port registers. */ @@ -977,20 +1130,53 @@ #define RNMICON PIC32_R (0x1260) #define PWRCON PIC32_R (0x1270) #define REFO1CON PIC32_R (0x1280) +#define REFO1CONCLR PIC32_R (0x1284) +#define REFO1CONSET PIC32_R (0x1288) +#define REFO1CONINV PIC32_R (0x128c) #define REFO1TRIM PIC32_R (0x1290) #define REFO2CON PIC32_R (0x12A0) +#define REFO2CONCLR PIC32_R (0x12A4) +#define REFO2CONSET PIC32_R (0x12A8) +#define REFO2CONINV PIC32_R (0x12Ac) #define REFO2TRIM PIC32_R (0x12B0) #define REFO3CON PIC32_R (0x12C0) +#define REFO3CONCLR PIC32_R (0x12C4) +#define REFO3CONSET PIC32_R (0x12C8) +#define REFO3CONINV PIC32_R (0x12Cc) #define REFO3TRIM PIC32_R (0x12D0) #define REFO4CON PIC32_R (0x12E0) +#define REFO4CONCLR PIC32_R (0x12E4) +#define REFO4CONSET PIC32_R (0x12E8) +#define REFO4CONINV PIC32_R (0x12Ec) #define REFO4TRIM PIC32_R (0x12F0) #define PB1DIV PIC32_R (0x1300) +#define PB1DIVCLR PIC32_R (0x1304) +#define PB1DIVSET PIC32_R (0x1308) +#define PB1DIVINV PIC32_R (0x130c) #define PB2DIV PIC32_R (0x1310) +#define PB2DIVCLR PIC32_R (0x1314) +#define PB2DIVSET PIC32_R (0x1318) +#define PB2DIVINV PIC32_R (0x131c) #define PB3DIV PIC32_R (0x1320) +#define PB3DIVCLR PIC32_R (0x1324) +#define PB3DIVSET PIC32_R (0x1328) +#define PB3DIVINV PIC32_R (0x132c) #define PB4DIV PIC32_R (0x1330) +#define PB4DIVCLR PIC32_R (0x1334) +#define PB4DIVSET PIC32_R (0x1338) +#define PB4DIVINV PIC32_R (0x133c) #define PB5DIV PIC32_R (0x1340) +#define PB5DIVCLR PIC32_R (0x1344) +#define PB5DIVSET PIC32_R (0x1348) +#define PB5DIVINV PIC32_R (0x134c) #define PB7DIV PIC32_R (0x1360) +#define PB7DIVCLR PIC32_R (0x1364) +#define PB7DIVSET PIC32_R (0x1368) +#define PB7DIVINV PIC32_R (0x136c) #define PB8DIV PIC32_R (0x1370) +#define PB8DIVCLR PIC32_R (0x1374) +#define PB8DIVSET PIC32_R (0x1378) +#define PB8DIVINV PIC32_R (0x137c) /* * Configuration Control register. @@ -1248,6 +1434,115 @@ #define PIC32_SPISTAT_SPIROV 0x00000040 /* Receive overflow flag */ #define PIC32_SPISTAT_SPIBUSY 0x00000800 /* SPI is busy */ +/*-------------------------------------- + * USB registers. + */ +#define USBCSR0 PIC32_R (0xE3000) /* */ +#define USBCSR1 PIC32_R (0xE3004) +#define USBCSR2 PIC32_R (0xE3008) +#define USBCSR3 PIC32_R (0xE300C) +#define USBIENCSR0 PIC32_R (0xE3010) /* */ +#define USBIENCSR1 PIC32_R (0xE3014) +#define USBIENCSR2 PIC32_R (0xE3018) +#define USBIENCSR3 PIC32_R (0xE301C) +#define USBFIFO0 PIC32_R (0xE3020) /* */ +#define USBFIFO1 PIC32_R (0xE3024) +#define USBFIFO2 PIC32_R (0xE3028) +#define USBFIFO3 PIC32_R (0xE302C) +#define USBFIFO4 PIC32_R (0xE3030) +#define USBFIFO5 PIC32_R (0xE3034) +#define USBFIFO6 PIC32_R (0xE3038) +#define USBFIFO7 PIC32_R (0xE303C) +#define USBOTG PIC32_R (0xE3060) /* */ +#define USBFIFOA PIC32_R (0xE3064) /* */ +#define USBHWVER PIC32_R (0xE306C) /* */ +#define USBINFO PIC32_R (0xE3078) /* */ +#define USBEOFRST PIC32_R (0xE307C) /* */ +#define USBE0TXA PIC32_R (0xE3080) /* */ +#define USBE0RXA PIC32_R (0xE3084) /* */ +#define USBE1TXA PIC32_R (0xE3088) +#define USBE1RXA PIC32_R (0xE308C) +#define USBE2TXA PIC32_R (0xE3090) +#define USBE2RXA PIC32_R (0xE3094) +#define USBE3TXA PIC32_R (0xE3098) +#define USBE3RXA PIC32_R (0xE309C) +#define USBE4TXA PIC32_R (0xE30A0) +#define USBE4RXA PIC32_R (0xE30A4) +#define USBE5TXA PIC32_R (0xE30A8) +#define USBE5RXA PIC32_R (0xE30AC) +#define USBE6TXA PIC32_R (0xE30B0) +#define USBE6RXA PIC32_R (0xE30B4) +#define USBE7TXA PIC32_R (0xE30B8) +#define USBE7RXA PIC32_R (0xE30BC) +#define USBE0CSR0 PIC32_R (0xE3100) /* */ +#define USBE0CSR2 PIC32_R (0xE3108) +#define USBE0CSR3 PIC32_R (0xE310C) +#define USBE1CSR0 PIC32_R (0xE3110) +#define USBE1CSR1 PIC32_R (0xE3114) +#define USBE1CSR2 PIC32_R (0xE3118) +#define USBE1CSR3 PIC32_R (0xE311C) +#define USBE2CSR0 PIC32_R (0xE3120) +#define USBE2CSR1 PIC32_R (0xE3124) +#define USBE2CSR2 PIC32_R (0xE3128) +#define USBE2CSR3 PIC32_R (0xE312C) +#define USBE3CSR0 PIC32_R (0xE3130) +#define USBE3CSR1 PIC32_R (0xE3134) +#define USBE3CSR2 PIC32_R (0xE3138) +#define USBE3CSR3 PIC32_R (0xE313C) +#define USBE4CSR0 PIC32_R (0xE3140) +#define USBE4CSR1 PIC32_R (0xE3144) +#define USBE4CSR2 PIC32_R (0xE3148) +#define USBE4CSR3 PIC32_R (0xE314C) +#define USBE5CSR0 PIC32_R (0xE3150) +#define USBE5CSR1 PIC32_R (0xE3154) +#define USBE5CSR2 PIC32_R (0xE3158) +#define USBE5CSR3 PIC32_R (0xE315C) +#define USBE6CSR0 PIC32_R (0xE3160) +#define USBE6CSR1 PIC32_R (0xE3164) +#define USBE6CSR2 PIC32_R (0xE3168) +#define USBE6CSR3 PIC32_R (0xE316C) +#define USBE7CSR0 PIC32_R (0xE3170) +#define USBE7CSR1 PIC32_R (0xE3174) +#define USBE7CSR2 PIC32_R (0xE3178) +#define USBE7CSR3 PIC32_R (0xE317C) +#define USBDMAINT PIC32_R (0xE3200) /* */ +#define USBDMA1C PIC32_R (0xE3204) /* */ +#define USBDMA1A PIC32_R (0xE3208) /* */ +#define USBDMA1N PIC32_R (0xE320C) /* */ +#define USBDMA2C PIC32_R (0xE3214) +#define USBDMA2A PIC32_R (0xE3218) +#define USBDMA2N PIC32_R (0xE321C) +#define USBDMA3C PIC32_R (0xE3224) +#define USBDMA3A PIC32_R (0xE3228) +#define USBDMA3N PIC32_R (0xE322C) +#define USBDMA4C PIC32_R (0xE3234) +#define USBDMA4A PIC32_R (0xE3238) +#define USBDMA4N PIC32_R (0xE323C) +#define USBDMA5C PIC32_R (0xE3244) +#define USBDMA5A PIC32_R (0xE3248) +#define USBDMA5N PIC32_R (0xE324C) +#define USBDMA6C PIC32_R (0xE3254) +#define USBDMA6A PIC32_R (0xE3258) +#define USBDMA6N PIC32_R (0xE325C) +#define USBDMA7C PIC32_R (0xE3264) +#define USBDMA7A PIC32_R (0xE3268) +#define USBDMA7N PIC32_R (0xE326C) +#define USBDMA8C PIC32_R (0xE3274) +#define USBDMA8A PIC32_R (0xE3278) +#define USBDMA8N PIC32_R (0xE327C) +#define USBE1RPC PIC32_R (0xE3304) /* */ +#define USBE2RPC PIC32_R (0xE3308) +#define USBE3RPC PIC32_R (0xE330C) +#define USBE4RPC PIC32_R (0xE3310) +#define USBE5RPC PIC32_R (0xE3314) +#define USBE6RPC PIC32_R (0xE3318) +#define USBE7RPC PIC32_R (0xE331C) +#define USBDPBFD PIC32_R (0xE3340) /* */ +#define USBTMCON1 PIC32_R (0xE3344) /* */ +#define USBTMCON2 PIC32_R (0xE3348) /* */ +#define USBLPMR1 PIC32_R (0xE3360) /* */ +#define USBLMPR2 PIC32_R (0xE3364) /* */ + /*-------------------------------------- * Ethernet registers. */