1b0c62724SMichal Simek /* 2b0c62724SMichal Simek * Support for MicroBlaze PVR (processor version register) 3b0c62724SMichal Simek * 4b0c62724SMichal Simek * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> 5b0c62724SMichal Simek * Copyright (C) 2007-2009 PetaLogix 6b0c62724SMichal Simek * Copyright (C) 2007 John Williams <john.williams@petalogix.com> 7b0c62724SMichal Simek * 8b0c62724SMichal Simek * This file is subject to the terms and conditions of the GNU General Public 9b0c62724SMichal Simek * License. See the file "COPYING" in the main directory of this archive 10b0c62724SMichal Simek * for more details. 11b0c62724SMichal Simek */ 12b0c62724SMichal Simek 13b0c62724SMichal Simek #include <linux/kernel.h> 14b0c62724SMichal Simek #include <linux/compiler.h> 15b0c62724SMichal Simek #include <asm/system.h> 16b0c62724SMichal Simek #include <asm/exceptions.h> 17b0c62724SMichal Simek #include <asm/pvr.h> 18b0c62724SMichal Simek 19b0c62724SMichal Simek /* 20b0c62724SMichal Simek * Until we get an assembler that knows about the pvr registers, 21b0c62724SMichal Simek * this horrible cruft will have to do. 22b0c62724SMichal Simek * That hardcoded opcode is mfs r3, rpvrNN 23b0c62724SMichal Simek */ 24b0c62724SMichal Simek 25b0c62724SMichal Simek #define get_single_pvr(pvrid, val) \ 26b0c62724SMichal Simek { \ 27b0c62724SMichal Simek register unsigned tmp __asm__("r3"); \ 28b0c62724SMichal Simek tmp = 0x0; /* Prevent warning about unused */ \ 29b0c62724SMichal Simek __asm__ __volatile__ ( \ 30a7d83550SMichal Simek "mfs %0, rpvr" #pvrid ";" \ 31b0c62724SMichal Simek : "=r" (tmp) : : "memory"); \ 32b0c62724SMichal Simek val = tmp; \ 33b0c62724SMichal Simek } 34b0c62724SMichal Simek 35b0c62724SMichal Simek /* 36b0c62724SMichal Simek * Does the CPU support the PVR register? 37b0c62724SMichal Simek * return value: 38b0c62724SMichal Simek * 0: no PVR 39b0c62724SMichal Simek * 1: simple PVR 40b0c62724SMichal Simek * 2: full PVR 41b0c62724SMichal Simek * 42b0c62724SMichal Simek * This must work on all CPU versions, including those before the 43b0c62724SMichal Simek * PVR was even an option. 44b0c62724SMichal Simek */ 45b0c62724SMichal Simek 46b0c62724SMichal Simek int cpu_has_pvr(void) 47b0c62724SMichal Simek { 48a3cd613bSMichal Simek unsigned long flags; 49b0c62724SMichal Simek unsigned pvr0; 50b0c62724SMichal Simek 51b0c62724SMichal Simek local_save_flags(flags); 52b0c62724SMichal Simek 53b0c62724SMichal Simek /* PVR bit in MSR tells us if there is any support */ 54b0c62724SMichal Simek if (!(flags & PVR_MSR_BIT)) 55b0c62724SMichal Simek return 0; 56b0c62724SMichal Simek 57b0c62724SMichal Simek get_single_pvr(0x00, pvr0); 58b0c62724SMichal Simek pr_debug("%s: pvr0 is 0x%08x\n", __func__, pvr0); 59b0c62724SMichal Simek 60b0c62724SMichal Simek if (pvr0 & PVR0_PVR_FULL_MASK) 61b0c62724SMichal Simek return 1; 62b0c62724SMichal Simek 63b0c62724SMichal Simek /* for partial PVR use static cpuinfo */ 64b0c62724SMichal Simek return 2; 65b0c62724SMichal Simek } 66b0c62724SMichal Simek 67b0c62724SMichal Simek void get_pvr(struct pvr_s *p) 68b0c62724SMichal Simek { 69b0c62724SMichal Simek get_single_pvr(0, p->pvr[0]); 70b0c62724SMichal Simek get_single_pvr(1, p->pvr[1]); 71b0c62724SMichal Simek get_single_pvr(2, p->pvr[2]); 72b0c62724SMichal Simek get_single_pvr(3, p->pvr[3]); 73b0c62724SMichal Simek get_single_pvr(4, p->pvr[4]); 74b0c62724SMichal Simek get_single_pvr(5, p->pvr[5]); 75b0c62724SMichal Simek get_single_pvr(6, p->pvr[6]); 76b0c62724SMichal Simek get_single_pvr(7, p->pvr[7]); 77b0c62724SMichal Simek get_single_pvr(8, p->pvr[8]); 78b0c62724SMichal Simek get_single_pvr(9, p->pvr[9]); 79b0c62724SMichal Simek get_single_pvr(10, p->pvr[10]); 80b0c62724SMichal Simek get_single_pvr(11, p->pvr[11]); 81b0c62724SMichal Simek } 82