162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Support for MicroBlaze PVR (processor version register) 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> 562306a36Sopenharmony_ci * Copyright (C) 2007-2009 PetaLogix 662306a36Sopenharmony_ci * Copyright (C) 2007 John Williams <john.williams@petalogix.com> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 962306a36Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 1062306a36Sopenharmony_ci * for more details. 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/kernel.h> 1462306a36Sopenharmony_ci#include <linux/compiler.h> 1562306a36Sopenharmony_ci#include <asm/exceptions.h> 1662306a36Sopenharmony_ci#include <asm/pvr.h> 1762306a36Sopenharmony_ci#include <linux/irqflags.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* 2062306a36Sopenharmony_ci * Until we get an assembler that knows about the pvr registers, 2162306a36Sopenharmony_ci * this horrible cruft will have to do. 2262306a36Sopenharmony_ci * That hardcoded opcode is mfs r3, rpvrNN 2362306a36Sopenharmony_ci */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define get_single_pvr(pvrid, val) \ 2662306a36Sopenharmony_ci{ \ 2762306a36Sopenharmony_ci register unsigned tmp __asm__("r3"); \ 2862306a36Sopenharmony_ci tmp = 0x0; /* Prevent warning about unused */ \ 2962306a36Sopenharmony_ci __asm__ __volatile__ ( \ 3062306a36Sopenharmony_ci "mfs %0, rpvr" #pvrid ";" \ 3162306a36Sopenharmony_ci : "=r" (tmp) : : "memory"); \ 3262306a36Sopenharmony_ci val = tmp; \ 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* 3662306a36Sopenharmony_ci * Does the CPU support the PVR register? 3762306a36Sopenharmony_ci * return value: 3862306a36Sopenharmony_ci * 0: no PVR 3962306a36Sopenharmony_ci * 1: simple PVR 4062306a36Sopenharmony_ci * 2: full PVR 4162306a36Sopenharmony_ci * 4262306a36Sopenharmony_ci * This must work on all CPU versions, including those before the 4362306a36Sopenharmony_ci * PVR was even an option. 4462306a36Sopenharmony_ci */ 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ciint cpu_has_pvr(void) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci unsigned long flags; 4962306a36Sopenharmony_ci unsigned pvr0; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci local_save_flags(flags); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci /* PVR bit in MSR tells us if there is any support */ 5462306a36Sopenharmony_ci if (!(flags & PVR_MSR_BIT)) 5562306a36Sopenharmony_ci return 0; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci get_single_pvr(0, pvr0); 5862306a36Sopenharmony_ci pr_debug("%s: pvr0 is 0x%08x\n", __func__, pvr0); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci if (pvr0 & PVR0_PVR_FULL_MASK) 6162306a36Sopenharmony_ci return 1; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci /* for partial PVR use static cpuinfo */ 6462306a36Sopenharmony_ci return 2; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_civoid get_pvr(struct pvr_s *p) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci get_single_pvr(0, p->pvr[0]); 7062306a36Sopenharmony_ci get_single_pvr(1, p->pvr[1]); 7162306a36Sopenharmony_ci get_single_pvr(2, p->pvr[2]); 7262306a36Sopenharmony_ci get_single_pvr(3, p->pvr[3]); 7362306a36Sopenharmony_ci get_single_pvr(4, p->pvr[4]); 7462306a36Sopenharmony_ci get_single_pvr(5, p->pvr[5]); 7562306a36Sopenharmony_ci get_single_pvr(6, p->pvr[6]); 7662306a36Sopenharmony_ci get_single_pvr(7, p->pvr[7]); 7762306a36Sopenharmony_ci get_single_pvr(8, p->pvr[8]); 7862306a36Sopenharmony_ci get_single_pvr(9, p->pvr[9]); 7962306a36Sopenharmony_ci get_single_pvr(10, p->pvr[10]); 8062306a36Sopenharmony_ci get_single_pvr(11, p->pvr[11]); 8162306a36Sopenharmony_ci} 82