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