1406107daSMichal Simek /* 2406107daSMichal Simek * Support for MicroBlaze PVR (processor version register) 3406107daSMichal Simek * 4406107daSMichal Simek * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> 5406107daSMichal Simek * Copyright (C) 2007-2009 PetaLogix 6406107daSMichal Simek * Copyright (C) 2007 John Williams <john.williams@petalogix.com> 7406107daSMichal Simek * 8406107daSMichal Simek * This file is subject to the terms and conditions of the GNU General Public 9406107daSMichal Simek * License. See the file "COPYING" in the main directory of this archive 10406107daSMichal Simek * for more details. 11406107daSMichal Simek */ 12406107daSMichal Simek 13406107daSMichal Simek #include <linux/init.h> 14406107daSMichal Simek #include <linux/string.h> 15406107daSMichal Simek #include <asm/pvr.h> 16406107daSMichal Simek #include <asm/cpuinfo.h> 17406107daSMichal Simek 18406107daSMichal Simek /* 19406107daSMichal Simek * Helper macro to map between fields in our struct cpuinfo, and 20406107daSMichal Simek * the PVR macros in pvr.h. 21406107daSMichal Simek */ 22406107daSMichal Simek 23406107daSMichal Simek #define CI(c, p) { ci->c = PVR_##p(pvr); } 24f6e1f1b4SMichal Simek 25f6e1f1b4SMichal Simek #if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_SERIAL_UARTLITE_CONSOLE) 26406107daSMichal Simek #define err_printk(x) \ 27406107daSMichal Simek early_printk("ERROR: Microblaze " x "-different for PVR and DTS\n"); 28f6e1f1b4SMichal Simek #else 29f6e1f1b4SMichal Simek #define err_printk(x) \ 30f6e1f1b4SMichal Simek printk(KERN_INFO "ERROR: Microblaze " x "-different for PVR and DTS\n"); 31f6e1f1b4SMichal Simek #endif 32406107daSMichal Simek 33406107daSMichal Simek void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) 34406107daSMichal Simek { 35406107daSMichal Simek struct pvr_s pvr; 36406107daSMichal Simek int temp; /* for saving temp value */ 37406107daSMichal Simek get_pvr(&pvr); 38406107daSMichal Simek 39fbeda677SMichal Simek CI(ver_code, VERSION); 40fbeda677SMichal Simek if (!ci->ver_code) { 41fbeda677SMichal Simek printk(KERN_ERR "ERROR: MB has broken PVR regs " 42fbeda677SMichal Simek "-> use DTS setting\n"); 43fbeda677SMichal Simek return; 44fbeda677SMichal Simek } 45fbeda677SMichal Simek 46406107daSMichal Simek temp = PVR_USE_BARREL(pvr) | PVR_USE_MSR_INSTR(pvr) |\ 47406107daSMichal Simek PVR_USE_PCMP_INSTR(pvr) | PVR_USE_DIV(pvr); 48406107daSMichal Simek if (ci->use_instr != temp) 49406107daSMichal Simek err_printk("BARREL, MSR, PCMP or DIV"); 50406107daSMichal Simek ci->use_instr = temp; 51406107daSMichal Simek 52406107daSMichal Simek temp = PVR_USE_HW_MUL(pvr) | PVR_USE_MUL64(pvr); 53406107daSMichal Simek if (ci->use_mult != temp) 54406107daSMichal Simek err_printk("HW_MUL"); 55406107daSMichal Simek ci->use_mult = temp; 56406107daSMichal Simek 57406107daSMichal Simek temp = PVR_USE_FPU(pvr) | PVR_USE_FPU2(pvr); 58406107daSMichal Simek if (ci->use_fpu != temp) 59406107daSMichal Simek err_printk("HW_FPU"); 60406107daSMichal Simek ci->use_fpu = temp; 61406107daSMichal Simek 62406107daSMichal Simek ci->use_exc = PVR_OPCODE_0x0_ILLEGAL(pvr) |\ 63406107daSMichal Simek PVR_UNALIGNED_EXCEPTION(pvr) |\ 64406107daSMichal Simek PVR_ILL_OPCODE_EXCEPTION(pvr) |\ 65406107daSMichal Simek PVR_IOPB_BUS_EXCEPTION(pvr) |\ 66406107daSMichal Simek PVR_DOPB_BUS_EXCEPTION(pvr) |\ 67406107daSMichal Simek PVR_DIV_ZERO_EXCEPTION(pvr) |\ 68406107daSMichal Simek PVR_FPU_EXCEPTION(pvr) |\ 69406107daSMichal Simek PVR_FSL_EXCEPTION(pvr); 70406107daSMichal Simek 71406107daSMichal Simek CI(pvr_user1, USER1); 72406107daSMichal Simek CI(pvr_user2, USER2); 73406107daSMichal Simek 74406107daSMichal Simek CI(mmu, USE_MMU); 75406107daSMichal Simek 76406107daSMichal Simek CI(use_icache, USE_ICACHE); 77406107daSMichal Simek CI(icache_tagbits, ICACHE_ADDR_TAG_BITS); 78406107daSMichal Simek CI(icache_write, ICACHE_ALLOW_WR); 7944e4e196SMichal Simek ci->icache_line_length = PVR_ICACHE_LINE_LEN(pvr) << 2; 80406107daSMichal Simek CI(icache_size, ICACHE_BYTE_SIZE); 81406107daSMichal Simek CI(icache_base, ICACHE_BASEADDR); 82406107daSMichal Simek CI(icache_high, ICACHE_HIGHADDR); 83406107daSMichal Simek 84406107daSMichal Simek CI(use_dcache, USE_DCACHE); 85406107daSMichal Simek CI(dcache_tagbits, DCACHE_ADDR_TAG_BITS); 86406107daSMichal Simek CI(dcache_write, DCACHE_ALLOW_WR); 8744e4e196SMichal Simek ci->dcache_line_length = PVR_DCACHE_LINE_LEN(pvr) << 2; 88406107daSMichal Simek CI(dcache_size, DCACHE_BYTE_SIZE); 89406107daSMichal Simek CI(dcache_base, DCACHE_BASEADDR); 90406107daSMichal Simek CI(dcache_high, DCACHE_HIGHADDR); 91406107daSMichal Simek 92f6e1f1b4SMichal Simek temp = PVR_DCACHE_USE_WRITEBACK(pvr); 93f6e1f1b4SMichal Simek if (ci->dcache_wb != temp) 94f6e1f1b4SMichal Simek err_printk("DCACHE WB"); 95f6e1f1b4SMichal Simek ci->dcache_wb = temp; 96f6e1f1b4SMichal Simek 97406107daSMichal Simek CI(use_dopb, D_OPB); 98406107daSMichal Simek CI(use_iopb, I_OPB); 99406107daSMichal Simek CI(use_dlmb, D_LMB); 100406107daSMichal Simek CI(use_ilmb, I_LMB); 101406107daSMichal Simek CI(num_fsl, FSL_LINKS); 102406107daSMichal Simek 103406107daSMichal Simek CI(irq_edge, INTERRUPT_IS_EDGE); 104406107daSMichal Simek CI(irq_positive, EDGE_IS_POSITIVE); 105406107daSMichal Simek 106406107daSMichal Simek CI(area_optimised, AREA_OPTIMISED); 107406107daSMichal Simek 108406107daSMichal Simek CI(hw_debug, DEBUG_ENABLED); 109406107daSMichal Simek CI(num_pc_brk, NUMBER_OF_PC_BRK); 110406107daSMichal Simek CI(num_rd_brk, NUMBER_OF_RD_ADDR_BRK); 111406107daSMichal Simek CI(num_wr_brk, NUMBER_OF_WR_ADDR_BRK); 112406107daSMichal Simek 113406107daSMichal Simek CI(fpga_family_code, TARGET_FAMILY); 114406107daSMichal Simek 115406107daSMichal Simek /* take timebase-frequency from DTS */ 116406107daSMichal Simek ci->cpu_clock_freq = fcpu(cpu, "timebase-frequency"); 117406107daSMichal Simek } 118