xref: /linux/arch/microblaze/kernel/cpu/pvr.c (revision ead5d1f4d877e92c051e1a1ade623d0d30e71619)
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/exceptions.h>
16b0c62724SMichal Simek #include <asm/pvr.h>
17*9e190c54SStefan Asserhall #include <linux/irqflags.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 
cpu_has_pvr(void)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 
5716497004SMichal Simek 	get_single_pvr(0, 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 
get_pvr(struct pvr_s * p)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