📄 syscon_cpu.c
字号:
t_syscon_obj *objects ) /* Array of SYSCON objects */{ UINT32 mask; UINT32 config, config1, config2, config3, ctrl; bool tag_data, lladdr, watch, trace, cacheerr, errctl; UINT32 i; syscon_objects = objects; /* CP0 registers */ for(i=0;i<SYSCON_CP0_REG_COUNT;i++) { syscon_register_generic( cp0_reg[i].id, cpu_read_cp0, (void *)&(cp0_reg[i]), cpu_write_cp0, (void *)&(cp0_reg[i]) ); } switch( sys_processor ) { case MIPS_20Kc : case MIPS_25Kf : cp0_reg[SYSCON_DERRCTL].valid = TRUE; cp0_reg[SYSCON_IERRCTL].valid = TRUE; cp0_reg[SYSCON_ITAGLO ].valid = TRUE; cp0_reg[SYSCON_IDATALO].valid = TRUE; cp0_reg[SYSCON_DTAGLO ].valid = TRUE; cp0_reg[SYSCON_DDATALO].valid = TRUE; cp0_reg[SYSCON_ITAGHI ].valid = TRUE; cp0_reg[SYSCON_IDATAHI].valid = TRUE; cp0_reg[SYSCON_DTAGHI ].valid = TRUE; cp0_reg[SYSCON_DDATAHI].valid = TRUE; /* Fallthrough !! */ case MIPS_4Kc : case MIPS_4Kmp : case MIPS_4KEc : case MIPS_4KEc_R2 : case MIPS_4KEmp : case MIPS_4KEmp_R2 : case MIPS_4KSc : case MIPS_4KSd : case MIPS_M4K : case MIPS_5K : case MIPS_5KE : /* Store initial setting of CP0 CONFIG1 register */ config1 = sys_cp0_read32( R_C0_Config, R_C0_SelConfig1 ); config1_init = config1; /* Detect whether cache/TLB is configurable */ /* This feature is present specifically to support configuration * testing of the core in a lead vehicle, and is not supported * in any other environment. Attempting to use this feature * outside of the scope of a lead vehicle is a violation of the * MIPS Architecture, and may cause unpredictable operation of * the processor. */ mask = sys_cpu_configurability(); cache_configurable = (mask & SYS_CPU_CONFIGURABILITY_CACHE) ? TRUE : FALSE; mmu_configurable = (mask & SYS_CPU_CONFIGURABILITY_MMU) ? TRUE : FALSE; config = sys_cp0_read32( R_C0_Config, R_C0_SelConfig ); /* TLB availability */ tlb = ( (config & M_ConfigMT) >> S_ConfigMT == K_ConfigMT_TLBMMU ) ? TRUE : FALSE; /* Watch */ watch = (config1 & M_Config1WR) ? TRUE : FALSE; /* TagHi, TagLo, DataHi, DataLo */ tag_data = ( sys_processor != MIPS_20Kc ) && ( sys_processor != MIPS_25Kf ) && ( sys_processor != MIPS_M4K ); /* LLAddr */ lladdr = ( sys_processor != MIPS_M4K ) && ( sys_processor != MIPS_5K ) && ( sys_processor != MIPS_5KE ); /* CacheErr */ cacheerr = ( sys_processor != MIPS_4Kc ) && ( sys_processor != MIPS_4Kmp ) && ( sys_processor != MIPS_4KEc ) && ( sys_processor != MIPS_4KEc_R2 ) && ( sys_processor != MIPS_4KEmp ) && ( sys_processor != MIPS_4KEmp_R2 ) && ( sys_processor != MIPS_4KSc ) && ( sys_processor != MIPS_4KSd ) && ( sys_processor != MIPS_M4K ); /* ErrCtl */ errctl = ( sys_processor != MIPS_20Kc ) && ( sys_processor != MIPS_25Kf ) && ( sys_processor != MIPS_M4K ); /* Release 2 */ if( sys_arch_rev >= K_ConfigAR_Rel2 ) { cp0_reg[SYSCON_PAGEGRAIN].valid = TRUE; cp0_reg[SYSCON_HWRENA ].valid = TRUE; cp0_reg[SYSCON_EBASE ].valid = TRUE; cp0_reg[SYSCON_INTCTL ].valid = TRUE; cp0_reg[SYSCON_SRSCTL ].valid = TRUE; cp0_reg[SYSCON_SRSMAP ].valid = TRUE; } /* EJTAG */ cp0_reg[SYSCON_DEBUG ].valid = sys_ejtag; cp0_reg[SYSCON_DEPC ].valid = sys_ejtag; cp0_reg[SYSCON_DESAVE ].valid = sys_ejtag; /* Config1/2/3 */ cp0_reg[SYSCON_CONFIG1 ].valid = TRUE; cp0_reg[SYSCON_CONFIG2 ].valid = (config1 & M_Config1M) ? TRUE : FALSE; if( cp0_reg[SYSCON_CONFIG2].valid ) { config2 = sys_cp0_read32( R_C0_Config, R_C0_SelConfig2 ); cp0_reg[SYSCON_CONFIG3].valid = (config2 & M_Config2M) ? TRUE : FALSE; } /* Trace */ if( cp0_reg[SYSCON_CONFIG3].valid ) { config3 = sys_cp0_read32( R_C0_Config, R_C0_SelConfig3 ); trace = (config3 & M_Config3TL) ? TRUE : FALSE; cp0_reg[SYSCON_TRACECONTROL ].valid = trace; cp0_reg[SYSCON_TRACECONTROL2].valid = trace; cp0_reg[SYSCON_USERTRACEDATA].valid = trace; cp0_reg[SYSCON_TRACEBPC ].valid = trace; } /* Performance counters */ if( config1 & M_Config1PC ) { cp0_reg[SYSCON_PERFCOUNT ].valid = TRUE; cp0_reg[SYSCON_PERFCOUNT_COUNT0].valid = TRUE; ctrl = sys_cp0_read32( R_C0_PerfCnt, R_C0_SelPerfCnt ); if( ctrl & M_PerfCntM ) { cp0_reg[SYSCON_PERFCOUNT_CTRL1 ].valid = TRUE; cp0_reg[SYSCON_PERFCOUNT_COUNT1].valid = TRUE; ctrl = sys_cp0_read32( R_C0_PerfCnt, R_C0_SelPerfCnt+1 ); if( ctrl & M_PerfCntM ) { cp0_reg[SYSCON_PERFCOUNT_CTRL2 ].valid = TRUE; cp0_reg[SYSCON_PERFCOUNT_COUNT2].valid = TRUE; } } } break; default : cache_configurable = FALSE; mmu_configurable = FALSE; tlb = TRUE; tag_data = TRUE; lladdr = TRUE; watch = TRUE; cacheerr = TRUE; errctl = TRUE; break; } /* Following registers are always required */ cp0_reg[SYSCON_BADVADDR].valid = TRUE; cp0_reg[SYSCON_COUNT ].valid = TRUE; cp0_reg[SYSCON_COMPARE ].valid = TRUE; cp0_reg[SYSCON_STATUS ].valid = TRUE; cp0_reg[SYSCON_CAUSE ].valid = TRUE; cp0_reg[SYSCON_EPC ].valid = TRUE; cp0_reg[SYSCON_PRID ].valid = TRUE; cp0_reg[SYSCON_CONFIG ].valid = TRUE; cp0_reg[SYSCON_ERROREPC].valid = TRUE; /* Following registers are required if TLB is present */ cp0_reg[SYSCON_INDEX ].valid = tlb; cp0_reg[SYSCON_RANDOM ].valid = tlb; cp0_reg[SYSCON_ENTRYLO0].valid = tlb; cp0_reg[SYSCON_ENTRYLO1].valid = tlb; cp0_reg[SYSCON_CONTEXT ].valid = tlb; cp0_reg[SYSCON_PAGEMASK].valid = tlb; cp0_reg[SYSCON_WIRED ].valid = tlb; cp0_reg[SYSCON_ENTRYHI ].valid = tlb; cp0_reg[SYSCON_XCONTEXT].valid = tlb && sys_64bit; cp0_reg[SYSCON_TAGLO ].valid = tag_data; cp0_reg[SYSCON_DATALO ].valid = tag_data; cp0_reg[SYSCON_TAGHI ].valid = tag_data; cp0_reg[SYSCON_DATAHI ].valid = tag_data; cp0_reg[SYSCON_LLADDR ].valid = lladdr; cp0_reg[SYSCON_WATCHLO ].valid = watch; cp0_reg[SYSCON_WATCHHI ].valid = watch; cp0_reg[SYSCON_CACHEERR].valid = cacheerr; cp0_reg[SYSCON_ERRCTL].valid = errctl; /* Following registers are 64 bit on a 64 bit CPU */ if (sys_64bit) { cp0_reg[SYSCON_ENTRYLO0].regsize = sizeof(UINT64); cp0_reg[SYSCON_ENTRYLO1].regsize = sizeof(UINT64); cp0_reg[SYSCON_CONTEXT].regsize = sizeof(UINT64); cp0_reg[SYSCON_BADVADDR].regsize = sizeof(UINT64); cp0_reg[SYSCON_ENTRYHI].regsize = sizeof(UINT64); cp0_reg[SYSCON_EPC].regsize = sizeof(UINT64); cp0_reg[SYSCON_LLADDR].regsize = sizeof(UINT64); cp0_reg[SYSCON_WATCHLO].regsize = sizeof(UINT64); cp0_reg[SYSCON_WATCHHI].regsize = sizeof(UINT64); cp0_reg[SYSCON_XCONTEXT].regsize = sizeof(UINT64); cp0_reg[SYSCON_DEPC].regsize = sizeof(UINT64); cp0_reg[SYSCON_ERROREPC].regsize = sizeof(UINT64); cp0_reg[SYSCON_DESAVE].regsize = sizeof(UINT64); } /**** Register objects ****/ syscon_register_generic( SYSCON_CPU_CYCLE_PER_COUNT_ID, syscon_uint32_read, (void *)&cycle_per_count, NULL, NULL ); syscon_register_generic( SYSCON_CPU_TLB_COUNT_RESET_ID, syscon_uint8_read, (void *)&tlb_reset, NULL, NULL ); syscon_register_generic( SYSCON_CPU_TLB_AVAIL_ID, syscon_bool_read, (void *)&tlb, syscon_bool_write, (void *)&tlb ); syscon_register_generic( SYSCON_CPU_CACHE_CONFIGURABLE_ID, syscon_bool_read, (void *)&cache_configurable, NULL, NULL ); syscon_register_generic( SYSCON_CPU_MMU_CONFIGURABLE_ID, syscon_bool_read, (void *)&mmu_configurable, NULL, NULL ); /* MIPS32/64 specifics */ syscon_register_id_mips32( SYSCON_CPU_CP0_CONFIG1_RESET_ID, /* MIPS32/64 */ cpu_cp0_config1_reset_mips32_read, NULL, NULL, NULL, /* Other */ NULL, NULL, NULL, NULL ); syscon_register_id_mips32( SYSCON_CPU_TLB_COUNT_ID, /* MIPS32/64 */ cpu_tlb_count_mips32_read, NULL, NULL, NULL, /* Other (assume QED RM5261) */ cpu_tlb_count_rm5261_read, NULL, NULL, NULL ); /* Determine initial TLB entry count */ if( tlb ) { SYSCON_read( SYSCON_CPU_TLB_COUNT_ID, (void *)&tlb_reset, sizeof(UINT8) ); } else { tlb_reset = 0; } /* Setup clock cycles per COUNT register increment */ switch( sys_processor ) { case MIPS_4Kc : case MIPS_4Kmp : case MIPS_4KEc : case MIPS_4KEc_R2 : case MIPS_4KEmp : case MIPS_4KEmp_R2 : case MIPS_4KSc : case MIPS_4KSd : cycle_per_count = MIPS4K_COUNT_CLK_PER_CYCLE; break; case MIPS_5K : case MIPS_5KE : cycle_per_count = MIPS5K_COUNT_CLK_PER_CYCLE; break; case MIPS_20Kc : case MIPS_25Kf : cycle_per_count = MIPS20Kc_COUNT_CLK_PER_CYCLE; break; case MIPS_M4K : cycle_per_count = MIPSM4K_COUNT_CLK_PER_CYCLE; break; case QED_RM70XX : /* Assume QED RM7061A */ cycle_per_count = QED_RM7061A_COUNT_CLK_PER_CYCLE; break; case QED_RM52XX : /* Assume QED RM5261 */ default : cycle_per_count = QED_RM5261_COUNT_CLK_PER_CYCLE; break; }}/************************************************************************ * * syscon_register_id_mips32 * Description : * ------------- * * Function used to register SYSCON object functions for objects * that depend on whether CPU is MIPS32/64 or not. * * A read and/or write function may be registered. * A NULL function pointer indicates that the operation (read or * write) is not allowed. * * read_data and write_data pointers are passed to the read and write * function. * Return values : * --------------- * * None * ************************************************************************/void syscon_register_id_mips32( t_syscon_ids id, /* OBJECT ID from syscon_api.h */ /* MIPS32/MIPS64 processor */ t_syscon_func read_mips32, /* MIPS32/64 read function */ void *read_data_mips32, /* Registered data */ t_syscon_func write_mips32, /* MIPS32/64 write function */ void *write_data_mips32, /* Registered data */ /* Other processor */ t_syscon_func read_other, /* "Other CPU" read function */ void *read_data_other, /* Registered data */ t_syscon_func write_other, /* "Other CPU" write function */ void *write_data_other ) /* Registered data */{ t_syscon_obj *obj; obj = &syscon_objects[id]; if( sys_mips32_64 ) { /* MIPS32/64 CPU */ obj->read = read_mips32; obj->read_data = read_data_mips32; obj->write = write_mips32; obj->write_data = write_data_mips32; } else { /* Not MIPS32/64 CPU */ obj->read = read_other; obj->read_data = read_data_other; obj->write = write_other; obj->write_data = write_data_other; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -