void vr41xx_disable_kiuint(uint16_t mask) { struct irq_desc *desc = irq_to_desc(KIU_IRQ); unsigned long flags; if (current_cpu_type() == CPU_VR4111 || current_cpu_type() == CPU_VR4121) { raw_spin_lock_irqsave(&desc->lock, flags); icu1_clear(MKIUINTREG, mask); raw_spin_unlock_irqrestore(&desc->lock, flags); } }
void vr41xx_enable_aiuint(uint16_t mask) { struct irq_desc *desc = irq_desc + AIU_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4111 || current_cpu_type() == CPU_VR4121) { spin_lock_irqsave(&desc->lock, flags); icu1_set(MAIUINTREG, mask); spin_unlock_irqrestore(&desc->lock, flags); } }
void vr41xx_enable_scuint(void) { struct irq_desc *desc = irq_to_desc(SCU_IRQ); unsigned long flags; if (current_cpu_type() == CPU_VR4122 || current_cpu_type() == CPU_VR4131 || current_cpu_type() == CPU_VR4133) { raw_spin_lock_irqsave(&desc->lock, flags); icu2_write(MSCUINTREG, SCUINT0); raw_spin_unlock_irqrestore(&desc->lock, flags); } }
void vr41xx_disable_bcuint(void) { struct irq_desc *desc = irq_desc + BCU_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4122 || current_cpu_type() == CPU_VR4131 || current_cpu_type() == CPU_VR4133) { spin_lock_irqsave(&desc->lock, flags); icu2_write(MBCUINTREG, 0); spin_unlock_irqrestore(&desc->lock, flags); } }
void vr41xx_enable_pciint(void) { struct irq_desc *desc = irq_desc + PCI_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4122 || current_cpu_type() == CPU_VR4131 || current_cpu_type() == CPU_VR4133) { spin_lock_irqsave(&desc->lock, flags); icu2_write(MPCIINTREG, PCIINT0); spin_unlock_irqrestore(&desc->lock, flags); } }
void vr41xx_disable_csiint(uint16_t mask) { struct irq_desc *desc = irq_desc + CSI_IRQ; unsigned long flags; if (current_cpu_type() == CPU_VR4122 || current_cpu_type() == CPU_VR4131 || current_cpu_type() == CPU_VR4133) { spin_lock_irqsave(&desc->lock, flags); icu2_clear(MCSIINTREG, mask); spin_unlock_irqrestore(&desc->lock, flags); } }
void vr41xx_enable_csiint(uint16_t mask) { struct irq_desc *desc = irq_to_desc(CSI_IRQ); unsigned long flags; if (current_cpu_type() == CPU_VR4122 || current_cpu_type() == CPU_VR4131 || current_cpu_type() == CPU_VR4133) { raw_spin_lock_irqsave(&desc->lock, flags); icu2_set(MCSIINTREG, mask); raw_spin_unlock_irqrestore(&desc->lock, flags); } }
void __init prom_init(void) { extern void dec_machine_halt(void); static char cpu_msg[] __initdata = "Sorry, this kernel is compiled for a wrong CPU type!\n"; s32 argc = fw_arg0; s32 *argv = (void *)fw_arg1; u32 magic = fw_arg2; s32 *prom_vec = (void *)fw_arg3; /* * Determine which PROM we have * (and therefore which machine we're on!) */ which_prom(magic, prom_vec); if (prom_is_rex(magic)) rex_clear_cache(); /* Register the early console. */ register_prom_console(); /* Were we compiled with the right CPU option? */ #if defined(CONFIG_CPU_R3000) if ((current_cpu_type() == CPU_R4000SC) || (current_cpu_type() == CPU_R4400SC)) { static char r4k_msg[] __initdata = "Please recompile with \"CONFIG_CPU_R4x00 = y\".\n"; printk(cpu_msg); printk(r4k_msg); dec_machine_halt(); } #endif #if defined(CONFIG_CPU_R4X00) if ((current_cpu_type() == CPU_R3000) || (current_cpu_type() == CPU_R3000A)) { static char r3k_msg[] __initdata = "Please recompile with \"CONFIG_CPU_R3000 = y\".\n"; printk(cpu_msg); printk(r3k_msg); dec_machine_halt(); } #endif prom_meminit(magic); prom_identify_arch(magic); prom_init_cmdline(argc, argv, magic); }
static __init int cpu_has_mfc0_count_bug(void) { switch (current_cpu_type()) { case CPU_R4000PC: case CPU_R4000SC: case CPU_R4000MC: /* * V3.0 is documented as suffering from the mfc0 from count bug. * Afaik this is the last version of the R4000. Later versions * were marketed as R4400. */ return 1; case CPU_R4400PC: case CPU_R4400SC: case CPU_R4400MC: /* * The published errata for the R4400 up to 3.0 say the CPU * has the mfc0 from count bug. */ if ((current_cpu_data.processor_id & 0xff) <= 0x30) return 1; /* * we assume newer revisions are ok */ return 0; } return 0; }
void __init vr41xx_siu_setup(void) { struct uart_port port; struct resource *res; unsigned int *type; int i; switch (current_cpu_type()) { case CPU_VR4111: case CPU_VR4121: type = siu_type1_ports; res = siu_type1_resource; break; case CPU_VR4122: case CPU_VR4131: case CPU_VR4133: type = siu_type2_ports; res = siu_type2_resource; break; default: return; } for (i = 0; i < SIU_PORTS_MAX; i++) { port.line = i; port.type = type[i]; if (port.type == PORT_UNKNOWN) break; port.mapbase = res[i].start; port.membase = (unsigned char __iomem *)KSEG1ADDR(res[i].start); vr41xx_siu_early_setup(&port); } }
static __init void build_adjust_context(u32 **p, unsigned int ctx) { unsigned int shift = 4 - (PTE_T_LOG2 + 1) + PAGE_SHIFT - 12; unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1); switch (current_cpu_type()) { case CPU_VR41XX: case CPU_VR4111: case CPU_VR4121: case CPU_VR4122: case CPU_VR4131: case CPU_VR4181: case CPU_VR4181A: case CPU_VR4133: shift += 2; break; default: break; } if (shift) UASM_i_SRL(p, ctx, ctx, shift); uasm_i_andi(p, ctx, ctx, mask); }
static inline unsigned long calculate_tclock(uint16_t clkspeed, unsigned long pclock, unsigned long vtclock) { unsigned long tclock = 0; switch (current_cpu_type()) { case CPU_VR4111: if (!(clkspeed & DIV2B)) tclock = pclock / 2; else if (!(clkspeed & DIV3B)) tclock = pclock / 3; else if (!(clkspeed & DIV4B)) tclock = pclock / 4; break; case CPU_VR4121: tclock = pclock / DIVT(clkspeed); break; case CPU_VR4122: case CPU_VR4131: case CPU_VR4133: tclock = vtclock / TDIVMODE(clkspeed); break; default: printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); break; } printk(KERN_INFO "TClock: %ldHz\n", tclock); return tclock; }
void __cpuinit tlb_init(void) { /* * You should never change this register: * - On R4600 1.7 the tlbp never hits for pages smaller than * the value in the c0_pagemask register. * - The entire mm handling assumes the c0_pagemask register to * be set to fixed-size pages. */ write_c0_pagemask(PM_DEFAULT_MASK); write_c0_wired(0); if (current_cpu_type() == CPU_R10000 || current_cpu_type() == CPU_R12000 || current_cpu_type() == CPU_R14000) write_c0_framemask(0); if (kernel_uses_smartmips_rixi) { /* * Enable the no read, no exec bits, and enable large virtual * address. */ u32 pg = PG_RIE | PG_XIE; #ifdef CONFIG_64BIT pg |= PG_ELPA; #endif write_c0_pagegrain(pg); } //temp_tlb_entry = current_cpu_data.tlbsize - 1; printk("TLB ÊýÁ¿%d.\n", current_cpu_data.tlbsize); /* From this point on the ARC firmware is dead. */ local_flush_tlb_all(); /* Did I tell you that ARC SUCKS? */ // if (ntlb) { // if (ntlb > 1 && ntlb <= current_cpu_data.tlbsize) { // int wired = current_cpu_data.tlbsize - ntlb; // write_c0_wired(wired); // write_c0_index(wired-1); // printk("Restricting TLB to %d entries\n", ntlb); // } else // printk("Ignoring invalid argument ntlb=%d\n", ntlb); // } // build_tlb_refill_handler(); }
int __init oprofile_arch_init(struct oprofile_operations *ops) { struct op_mips_model *lmodel = NULL; int res; switch (current_cpu_type()) { case CPU_5KC: case CPU_20KC: case CPU_24K: case CPU_25KF: case CPU_34K: case CPU_1004K: case CPU_74K: case CPU_SB1: case CPU_SB1A: case CPU_R10000: case CPU_R12000: case CPU_R14000: lmodel = &op_model_mipsxx_ops; break; #ifdef CONFIG_BRCMSTB case CPU_BMIPS3300: case CPU_BMIPS4380: lmodel = &op_model_bmips_ops; break; case CPU_BMIPS5000: lmodel = &op_model_mipsxx_ops; break; #endif case CPU_RM9000: lmodel = &op_model_rm9000_ops; break; }; if (!lmodel) return -ENODEV; res = lmodel->init(); if (res) return res; model = lmodel; ops->create_files = op_mips_create_files; ops->setup = op_mips_setup; //ops->shutdown = op_mips_shutdown; ops->start = op_mips_start; ops->stop = op_mips_stop; ops->cpu_type = lmodel->cpu_type; printk(KERN_INFO "oprofile: using %s performance monitoring.\n", lmodel->cpu_type); return 0; }
int __init oprofile_arch_init(struct oprofile_operations *ops) { struct op_mips_model *lmodel = NULL; int res; switch (current_cpu_type()) { case CPU_5KC: case CPU_20KC: case CPU_24K: case CPU_25KF: case CPU_34K: case CPU_1004K: case CPU_74K: case CPU_SB1: case CPU_SB1A: case CPU_R10000: case CPU_R12000: case CPU_R14000: lmodel = &op_model_mipsxx_ops; break; case CPU_RM9000: lmodel = &op_model_rm9000_ops; break; case CPU_LOONGSON2: lmodel = &op_model_loongson2_ops; break; case CPU_CAVIUM_OCTEON: case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: lmodel = &op_model_octeon; break; }; if (!lmodel) return -ENODEV; res = lmodel->init(); if (res) return res; model = lmodel; ops->create_files = op_mips_create_files; ops->setup = op_mips_setup; //ops->shutdown = op_mips_shutdown; ops->start = op_mips_start; ops->stop = op_mips_stop; ops->cpu_type = lmodel->cpu_type; printk(KERN_INFO "oprofile: using %s performance monitoring.\n", lmodel->cpu_type); return 0; }
/* * LOONGSON2/3 has a 4 entry itlb which is a subset of dtlb, * unfortunately, itlb is not totally transparent to software. */ static inline void flush_itlb(void) { switch (current_cpu_type()) { case CPU_LOONGSON2: case CPU_LOONGSON3: write_c0_diag(4); break; default: break; } }
void __init plat_time_init(void) { nlm_init_pic_timer(); mips_hpt_frequency = nlm_get_cpu_frequency(); if (current_cpu_type() == CPU_XLR) preset_lpj = mips_hpt_frequency / (3 * HZ); else preset_lpj = mips_hpt_frequency / (2 * HZ); pr_info("MIPS counter frequency [%ld]\n", (unsigned long)mips_hpt_frequency); }
static int __init vr41xx_cmu_init(void) { unsigned long start, size; switch (current_cpu_type()) { case CPU_VR4111: case CPU_VR4121: start = CMU_TYPE1_BASE; size = CMU_TYPE1_SIZE; break; case CPU_VR4122: case CPU_VR4131: start = CMU_TYPE2_BASE; size = CMU_TYPE2_SIZE; break; case CPU_VR4133: start = CMU_TYPE3_BASE; size = CMU_TYPE3_SIZE; break; default: panic("Unexpected CPU of NEC VR4100 series"); break; } if (request_mem_region(start, size, "CMU") == NULL) return -EBUSY; cmu_base = ioremap(start, size); if (cmu_base == NULL) { release_mem_region(start, size); return -EBUSY; } cmuclkmsk = cmu_read(CMUCLKMSK); if (current_cpu_type() == CPU_VR4133) cmuclkmsk2 = cmu_read(CMUCLKMSK2); spin_lock_init(&cmu_lock); return 0; }
/* * LOONGSON-2 has a 4 entry itlb which is a subset of jtlb, LOONGSON-3 has * a 4 entry itlb and a 4 entry dtlb which are subsets of jtlb. Unfortunately, * itlb/dtlb are not totally transparent to software. */ static inline void flush_micro_tlb(void) { switch (current_cpu_type()) { case CPU_LOONGSON2: write_c0_diag(LOONGSON_DIAG_ITLB); break; case CPU_LOONGSON3: write_c0_diag(LOONGSON_DIAG_ITLB | LOONGSON_DIAG_DTLB); break; default: break; } }
static inline unsigned long calculate_pclock(uint16_t clkspeed) { unsigned long pclock = 0; switch (current_cpu_type()) { case CPU_VR4111: case CPU_VR4121: pclock = 18432000 * 64; pclock /= CLKSP(clkspeed); break; case CPU_VR4122: pclock = 18432000 * 98; pclock /= CLKSP(clkspeed); break; case CPU_VR4131: pclock = 18432000 * 108; pclock /= CLKSP(clkspeed); break; case CPU_VR4133: switch (CLKSP_VR4133(clkspeed)) { case 0: pclock = 133000000; break; case 1: pclock = 149000000; break; case 2: pclock = 165900000; break; case 3: pclock = 199100000; break; case 4: pclock = 265900000; break; default: printk(KERN_INFO "Unknown PClock speed for NEC VR4133\n"); break; } break; default: printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); break; } printk(KERN_INFO "PClock: %ldHz\n", pclock); return pclock; }
static int __init vr41xx_giu_add(void) { struct platform_device *pdev; struct resource *res; unsigned int num; int retval; pdev = platform_device_alloc("GIU", -1); if (!pdev) return -ENOMEM; switch (current_cpu_type()) { case CPU_VR4111: case CPU_VR4121: pdev->id = GPIO_50PINS_PULLUPDOWN; res = giu_50pins_pullupdown_resource; num = ARRAY_SIZE(giu_50pins_pullupdown_resource); break; case CPU_VR4122: case CPU_VR4131: pdev->id = GPIO_36PINS; res = giu_36pins_resource; num = ARRAY_SIZE(giu_36pins_resource); break; case CPU_VR4133: pdev->id = GPIO_48PINS_EDGE_SELECT; res = giu_48pins_resource; num = ARRAY_SIZE(giu_48pins_resource); break; default: retval = -ENODEV; goto err_free_device; } retval = platform_device_add_resources(pdev, res, num); if (retval) goto err_free_device; retval = platform_device_add(pdev); if (retval) goto err_free_device; return 0; err_free_device: platform_device_put(pdev); return retval; }
static inline uint16_t read_clkspeed(void) { switch (current_cpu_type()) { case CPU_VR4111: case CPU_VR4121: return readw(CLKSPEEDREG_TYPE1); case CPU_VR4122: case CPU_VR4131: case CPU_VR4133: return readw(CLKSPEEDREG_TYPE2); default: printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); break; } return 0; }
int vr41xx_set_intassign(unsigned int irq, unsigned char intassign) { int retval = -EINVAL; if (current_cpu_type() != CPU_VR4133) return -EINVAL; if (intassign > INTASSIGN_MAX) return -EINVAL; if (irq >= SYSINT1_IRQ_BASE && irq <= SYSINT1_IRQ_LAST) retval = set_sysint1_assign(irq, intassign); else if (irq >= SYSINT2_IRQ_BASE && irq <= SYSINT2_IRQ_LAST) retval = set_sysint2_assign(irq, intassign); return retval; }
/* * Hazards * * From the IDT errata for the QED RM5230 (Nevada), processor revision 1.0: * 2. A timing hazard exists for the TLBP instruction. * * stalling_instruction * TLBP * * The JTLB is being read for the TLBP throughout the stall generated by the * previous instruction. This is not really correct as the stalling instruction * can modify the address used to access the JTLB. The failure symptom is that * the TLBP instruction will use an address created for the stalling instruction * and not the address held in C0_ENHI and thus report the wrong results. * * The software work-around is to not allow the instruction preceding the TLBP * to stall - make it an NOP or some other instruction guaranteed not to stall. * * Errata 2 will not be fixed. This errata is also on the R5000. * * As if we MIPS hackers wouldn't know how to nop pipelines happy ... */ static __init void __attribute__((unused)) build_tlb_probe_entry(u32 **p) { switch (current_cpu_type()) { /* Found by experiment: R4600 v2.0 needs this, too. */ case CPU_R4600: case CPU_R5000: case CPU_R5000A: case CPU_NEVADA: uasm_i_nop(p); uasm_i_tlbp(p); break; default: uasm_i_tlbp(p); break; } }
static int __init vr41xx_siu_add(void) { struct platform_device *pdev; struct resource *res; unsigned int num; int retval; pdev = platform_device_alloc("SIU", -1); if (!pdev) return -ENOMEM; switch (current_cpu_type()) { case CPU_VR4111: case CPU_VR4121: pdev->dev.platform_data = siu_type1_ports; res = siu_type1_resource; num = ARRAY_SIZE(siu_type1_resource); break; case CPU_VR4122: case CPU_VR4131: case CPU_VR4133: pdev->dev.platform_data = siu_type2_ports; res = siu_type2_resource; num = ARRAY_SIZE(siu_type2_resource); break; default: retval = -ENODEV; goto err_free_device; } retval = platform_device_add_resources(pdev, res, num); if (retval) goto err_free_device; retval = platform_device_add(pdev); if (retval) goto err_free_device; return 0; err_free_device: platform_device_put(pdev); return retval; }
void __cpuinit build_tlb_refill_handler(void) { /* * The refill handler is generated per-CPU, multi-node systems * may have local storage for it. The other handlers are only * needed once. */ static int run_once = 0; switch (current_cpu_type()) { case CPU_R2000: case CPU_R3000: case CPU_R3000A: case CPU_R3081E: case CPU_TX3912: case CPU_TX3922: case CPU_TX3927: build_r3000_tlb_refill_handler(); if (!run_once) { build_r3000_tlb_load_handler(); build_r3000_tlb_store_handler(); build_r3000_tlb_modify_handler(); run_once++; } break; case CPU_R6000: case CPU_R6000A: panic("No R6000 TLB refill handler yet"); break; case CPU_R8000: panic("No R8000 TLB refill handler yet"); break; default: build_r4000_tlb_refill_handler(); if (!run_once) { build_r4000_tlb_load_handler(); build_r4000_tlb_store_handler(); build_r4000_tlb_modify_handler(); run_once++; } } }
/* * Hazards * * From the IDT errata for the QED RM5230 (Nevada), processor revision 1.0: * 2. A timing hazard exists for the TLBP instruction. * * stalling_instruction * TLBP * * The JTLB is being read for the TLBP throughout the stall generated by the * previous instruction. This is not really correct as the stalling instruction * can modify the address used to access the JTLB. The failure symptom is that * the TLBP instruction will use an address created for the stalling instruction * and not the address held in C0_ENHI and thus report the wrong results. * * The software work-around is to not allow the instruction preceding the TLBP * to stall - make it an NOP or some other instruction guaranteed not to stall. * * Errata 2 will not be fixed. This errata is also on the R5000. * * As if we MIPS hackers wouldn't know how to nop pipelines happy ... */ static void __cpuinit __maybe_unused build_tlb_probe_entry(u32 **p) { switch (current_cpu_type()) { /* Found by experiment: R4600 v2.0/R4700 needs this, too. */ case CPU_R4600: case CPU_R4700: case CPU_R5000: case CPU_R5000A: case CPU_NEVADA: uasm_i_nop(p); uasm_i_tlbp(p); break; default: uasm_i_tlbp(p); break; } }
int get_c0_fdc_int(void) { /* * Some cores claim the FDC is routable through the GIC, but it doesn't * actually seem to be connected for those Malta bitstreams. */ switch (current_cpu_type()) { case CPU_INTERAPTIV: case CPU_PROAPTIV: return -1; }; if (cpu_has_veic) return -1; else if (gic_present) return gic_get_c0_fdc_int(); else if (cp0_fdc_irq >= 0) return MIPS_CPU_IRQ_BASE + cp0_fdc_irq; else return -1; }
static inline void software_reset(void) { uint16_t pmucnt2; switch (current_cpu_type()) { case CPU_VR4122: case CPU_VR4131: case CPU_VR4133: pmucnt2 = pmu_read(PMUCNT2REG); pmucnt2 |= SOFTRST; pmu_write(PMUCNT2REG, pmucnt2); break; default: set_c0_status(ST0_BEV | ST0_ERL); change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); __flush_cache_all(); write_c0_wired(0); __asm__("jr %0"::"r"(0xbfc00000)); break; } }
static inline unsigned long calculate_vtclock(uint16_t clkspeed, unsigned long pclock) { unsigned long vtclock = 0; switch (current_cpu_type()) { case CPU_VR4111: /* The NEC VR4111 doesn't have the VTClock. */ break; case CPU_VR4121: vtclock = pclock; /* DIVVT == 9 Divide by 1.5 . VTClock = (PClock * 6) / 9 */ if (DIVVT(clkspeed) == 9) vtclock = pclock * 6; /* DIVVT == 10 Divide by 2.5 . VTClock = (PClock * 4) / 10 */ else if (DIVVT(clkspeed) == 10) vtclock = pclock * 4; vtclock /= DIVVT(clkspeed); printk(KERN_INFO "VTClock: %ldHz\n", vtclock); break; case CPU_VR4122: if(VTDIVMODE(clkspeed) == 7) vtclock = pclock / 1; else if(VTDIVMODE(clkspeed) == 1) vtclock = pclock / 2; else vtclock = pclock / VTDIVMODE(clkspeed); printk(KERN_INFO "VTClock: %ldHz\n", vtclock); break; case CPU_VR4131: case CPU_VR4133: vtclock = pclock / VTDIVMODE(clkspeed); printk(KERN_INFO "VTClock: %ldHz\n", vtclock); break; default: printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); break; } return vtclock; }