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); } 24406107daSMichal Simek #define err_printk(x) \ 25406107daSMichal Simek early_printk("ERROR: Microblaze " x " - different for PVR and DTS\n"); 26406107daSMichal Simek 27406107daSMichal Simek void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu) 28406107daSMichal Simek { 29406107daSMichal Simek struct pvr_s pvr; 30406107daSMichal Simek int temp; /* for saving temp value */ 31406107daSMichal Simek get_pvr(&pvr); 32406107daSMichal Simek 33fbeda677SMichal Simek CI(ver_code, VERSION); 34fbeda677SMichal Simek if (!ci->ver_code) { 35fbeda677SMichal Simek printk(KERN_ERR "ERROR: MB has broken PVR regs " 36fbeda677SMichal Simek "-> use DTS setting\n"); 37fbeda677SMichal Simek return; 38fbeda677SMichal Simek } 39fbeda677SMichal Simek 40406107daSMichal Simek temp = PVR_USE_BARREL(pvr) | PVR_USE_MSR_INSTR(pvr) |\ 41406107daSMichal Simek PVR_USE_PCMP_INSTR(pvr) | PVR_USE_DIV(pvr); 42406107daSMichal Simek if (ci->use_instr != temp) 43406107daSMichal Simek err_printk("BARREL, MSR, PCMP or DIV"); 44406107daSMichal Simek ci->use_instr = temp; 45406107daSMichal Simek 46406107daSMichal Simek temp = PVR_USE_HW_MUL(pvr) | PVR_USE_MUL64(pvr); 47406107daSMichal Simek if (ci->use_mult != temp) 48406107daSMichal Simek err_printk("HW_MUL"); 49406107daSMichal Simek ci->use_mult = temp; 50406107daSMichal Simek 51406107daSMichal Simek temp = PVR_USE_FPU(pvr) | PVR_USE_FPU2(pvr); 52406107daSMichal Simek if (ci->use_fpu != temp) 53406107daSMichal Simek err_printk("HW_FPU"); 54406107daSMichal Simek ci->use_fpu = temp; 55406107daSMichal Simek 56406107daSMichal Simek ci->use_exc = PVR_OPCODE_0x0_ILLEGAL(pvr) |\ 57406107daSMichal Simek PVR_UNALIGNED_EXCEPTION(pvr) |\ 58406107daSMichal Simek PVR_ILL_OPCODE_EXCEPTION(pvr) |\ 59406107daSMichal Simek PVR_IOPB_BUS_EXCEPTION(pvr) |\ 60406107daSMichal Simek PVR_DOPB_BUS_EXCEPTION(pvr) |\ 61406107daSMichal Simek PVR_DIV_ZERO_EXCEPTION(pvr) |\ 62406107daSMichal Simek PVR_FPU_EXCEPTION(pvr) |\ 63406107daSMichal Simek PVR_FSL_EXCEPTION(pvr); 64406107daSMichal Simek 65406107daSMichal Simek CI(pvr_user1, USER1); 66406107daSMichal Simek CI(pvr_user2, USER2); 67406107daSMichal Simek 68406107daSMichal Simek CI(mmu, USE_MMU); 69406107daSMichal Simek 70406107daSMichal Simek CI(use_icache, USE_ICACHE); 71406107daSMichal Simek CI(icache_tagbits, ICACHE_ADDR_TAG_BITS); 72406107daSMichal Simek CI(icache_write, ICACHE_ALLOW_WR); 73406107daSMichal Simek CI(icache_line, ICACHE_LINE_LEN); 74406107daSMichal Simek CI(icache_size, ICACHE_BYTE_SIZE); 75406107daSMichal Simek CI(icache_base, ICACHE_BASEADDR); 76406107daSMichal Simek CI(icache_high, ICACHE_HIGHADDR); 77406107daSMichal Simek 78406107daSMichal Simek CI(use_dcache, USE_DCACHE); 79406107daSMichal Simek CI(dcache_tagbits, DCACHE_ADDR_TAG_BITS); 80406107daSMichal Simek CI(dcache_write, DCACHE_ALLOW_WR); 81406107daSMichal Simek CI(dcache_line, DCACHE_LINE_LEN); 82406107daSMichal Simek CI(dcache_size, DCACHE_BYTE_SIZE); 83406107daSMichal Simek CI(dcache_base, DCACHE_BASEADDR); 84406107daSMichal Simek CI(dcache_high, DCACHE_HIGHADDR); 85406107daSMichal Simek 86406107daSMichal Simek CI(use_dopb, D_OPB); 87406107daSMichal Simek CI(use_iopb, I_OPB); 88406107daSMichal Simek CI(use_dlmb, D_LMB); 89406107daSMichal Simek CI(use_ilmb, I_LMB); 90406107daSMichal Simek CI(num_fsl, FSL_LINKS); 91406107daSMichal Simek 92406107daSMichal Simek CI(irq_edge, INTERRUPT_IS_EDGE); 93406107daSMichal Simek CI(irq_positive, EDGE_IS_POSITIVE); 94406107daSMichal Simek 95406107daSMichal Simek CI(area_optimised, AREA_OPTIMISED); 96406107daSMichal Simek 97406107daSMichal Simek CI(hw_debug, DEBUG_ENABLED); 98406107daSMichal Simek CI(num_pc_brk, NUMBER_OF_PC_BRK); 99406107daSMichal Simek CI(num_rd_brk, NUMBER_OF_RD_ADDR_BRK); 100406107daSMichal Simek CI(num_wr_brk, NUMBER_OF_WR_ADDR_BRK); 101406107daSMichal Simek 102406107daSMichal Simek CI(fpga_family_code, TARGET_FAMILY); 103406107daSMichal Simek 104406107daSMichal Simek /* take timebase-frequency from DTS */ 105406107daSMichal Simek ci->cpu_clock_freq = fcpu(cpu, "timebase-frequency"); 106406107daSMichal Simek } 107