1*e8de0fa8SMarek Vasut /* 2*e8de0fa8SMarek Vasut * PXA CPU information display 3*e8de0fa8SMarek Vasut * 4*e8de0fa8SMarek Vasut * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> 5*e8de0fa8SMarek Vasut * 6*e8de0fa8SMarek Vasut * This program is free software; you can redistribute it and/or 7*e8de0fa8SMarek Vasut * modify it under the terms of the GNU General Public License as 8*e8de0fa8SMarek Vasut * published by the Free Software Foundation; either version 2 of 9*e8de0fa8SMarek Vasut * the License, or (at your option) any later version. 10*e8de0fa8SMarek Vasut * 11*e8de0fa8SMarek Vasut * This program is distributed in the hope that it will be useful, 12*e8de0fa8SMarek Vasut * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*e8de0fa8SMarek Vasut * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*e8de0fa8SMarek Vasut * GNU General Public License for more details. 15*e8de0fa8SMarek Vasut * 16*e8de0fa8SMarek Vasut * You should have received a copy of the GNU General Public License 17*e8de0fa8SMarek Vasut * along with this program; if not, write to the Free Software 18*e8de0fa8SMarek Vasut * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 19*e8de0fa8SMarek Vasut * MA 02111-1307 USA 20*e8de0fa8SMarek Vasut */ 21*e8de0fa8SMarek Vasut 22*e8de0fa8SMarek Vasut #include <common.h> 23*e8de0fa8SMarek Vasut #include <asm/io.h> 24*e8de0fa8SMarek Vasut #include <errno.h> 25*e8de0fa8SMarek Vasut #include <linux/compiler.h> 26*e8de0fa8SMarek Vasut 27*e8de0fa8SMarek Vasut #define CPU_MASK_PXA_REVID 0x00f 28*e8de0fa8SMarek Vasut 29*e8de0fa8SMarek Vasut #define CPU_MASK_PXA_PRODID 0x3f0 30*e8de0fa8SMarek Vasut #define CPU_VALUE_PXA25X 0x100 31*e8de0fa8SMarek Vasut #define CPU_VALUE_PXA27X 0x110 32*e8de0fa8SMarek Vasut 33*e8de0fa8SMarek Vasut static uint32_t pxa_get_cpuid(void) 34*e8de0fa8SMarek Vasut { 35*e8de0fa8SMarek Vasut uint32_t cpuid; 36*e8de0fa8SMarek Vasut asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r"(cpuid)); 37*e8de0fa8SMarek Vasut return cpuid; 38*e8de0fa8SMarek Vasut } 39*e8de0fa8SMarek Vasut 40*e8de0fa8SMarek Vasut int cpu_is_pxa25x(void) 41*e8de0fa8SMarek Vasut { 42*e8de0fa8SMarek Vasut uint32_t id = pxa_get_cpuid(); 43*e8de0fa8SMarek Vasut id &= CPU_MASK_PXA_PRODID; 44*e8de0fa8SMarek Vasut return id == CPU_VALUE_PXA25X; 45*e8de0fa8SMarek Vasut } 46*e8de0fa8SMarek Vasut 47*e8de0fa8SMarek Vasut int cpu_is_pxa27x(void) 48*e8de0fa8SMarek Vasut { 49*e8de0fa8SMarek Vasut uint32_t id = pxa_get_cpuid(); 50*e8de0fa8SMarek Vasut id &= CPU_MASK_PXA_PRODID; 51*e8de0fa8SMarek Vasut return id == CPU_VALUE_PXA27X; 52*e8de0fa8SMarek Vasut } 53*e8de0fa8SMarek Vasut 54*e8de0fa8SMarek Vasut #ifdef CONFIG_DISPLAY_CPUINFO 55*e8de0fa8SMarek Vasut static const char *pxa25x_get_revision(void) 56*e8de0fa8SMarek Vasut { 57*e8de0fa8SMarek Vasut static __maybe_unused const char * const revs_25x[] = { "A0" }; 58*e8de0fa8SMarek Vasut static __maybe_unused const char * const revs_26x[] = { 59*e8de0fa8SMarek Vasut "A0", "B0", "B1" 60*e8de0fa8SMarek Vasut }; 61*e8de0fa8SMarek Vasut static const char *unknown = "Unknown"; 62*e8de0fa8SMarek Vasut uint32_t id; 63*e8de0fa8SMarek Vasut 64*e8de0fa8SMarek Vasut if (!cpu_is_pxa25x()) 65*e8de0fa8SMarek Vasut return unknown; 66*e8de0fa8SMarek Vasut 67*e8de0fa8SMarek Vasut id = pxa_get_cpuid() & CPU_MASK_PXA_REVID; 68*e8de0fa8SMarek Vasut 69*e8de0fa8SMarek Vasut /* PXA26x is a sick special case as it can't be told apart from PXA25x :-( */ 70*e8de0fa8SMarek Vasut #ifdef CONFIG_CPU_PXA26X 71*e8de0fa8SMarek Vasut switch (id) { 72*e8de0fa8SMarek Vasut case 3: return revs_26x[0]; 73*e8de0fa8SMarek Vasut case 5: return revs_26x[1]; 74*e8de0fa8SMarek Vasut case 6: return revs_26x[2]; 75*e8de0fa8SMarek Vasut } 76*e8de0fa8SMarek Vasut #else 77*e8de0fa8SMarek Vasut if (id == 6) 78*e8de0fa8SMarek Vasut return revs_25x[0]; 79*e8de0fa8SMarek Vasut #endif 80*e8de0fa8SMarek Vasut return unknown; 81*e8de0fa8SMarek Vasut } 82*e8de0fa8SMarek Vasut 83*e8de0fa8SMarek Vasut static const char *pxa27x_get_revision(void) 84*e8de0fa8SMarek Vasut { 85*e8de0fa8SMarek Vasut static const char *const rev[] = { "A0", "A1", "B0", "B1", "C0", "C5" }; 86*e8de0fa8SMarek Vasut static const char *unknown = "Unknown"; 87*e8de0fa8SMarek Vasut uint32_t id; 88*e8de0fa8SMarek Vasut 89*e8de0fa8SMarek Vasut if (!cpu_is_pxa27x()) 90*e8de0fa8SMarek Vasut return unknown; 91*e8de0fa8SMarek Vasut 92*e8de0fa8SMarek Vasut id = pxa_get_cpuid() & CPU_MASK_PXA_REVID; 93*e8de0fa8SMarek Vasut 94*e8de0fa8SMarek Vasut if ((id == 5) || (id == 6) || (id > 7)) 95*e8de0fa8SMarek Vasut return unknown; 96*e8de0fa8SMarek Vasut 97*e8de0fa8SMarek Vasut /* Cap the special PXA270 C5 case. */ 98*e8de0fa8SMarek Vasut if (id == 7) 99*e8de0fa8SMarek Vasut id = 5; 100*e8de0fa8SMarek Vasut 101*e8de0fa8SMarek Vasut return rev[id]; 102*e8de0fa8SMarek Vasut } 103*e8de0fa8SMarek Vasut 104*e8de0fa8SMarek Vasut static int print_cpuinfo_pxa2xx(void) 105*e8de0fa8SMarek Vasut { 106*e8de0fa8SMarek Vasut if (cpu_is_pxa25x()) { 107*e8de0fa8SMarek Vasut puts("Marvell PXA25x rev. "); 108*e8de0fa8SMarek Vasut puts(pxa25x_get_revision()); 109*e8de0fa8SMarek Vasut } else if (cpu_is_pxa27x()) { 110*e8de0fa8SMarek Vasut puts("Marvell PXA27x rev. "); 111*e8de0fa8SMarek Vasut puts(pxa27x_get_revision()); 112*e8de0fa8SMarek Vasut } else 113*e8de0fa8SMarek Vasut return -EINVAL; 114*e8de0fa8SMarek Vasut 115*e8de0fa8SMarek Vasut puts("\n"); 116*e8de0fa8SMarek Vasut 117*e8de0fa8SMarek Vasut return 0; 118*e8de0fa8SMarek Vasut } 119*e8de0fa8SMarek Vasut 120*e8de0fa8SMarek Vasut int print_cpuinfo(void) 121*e8de0fa8SMarek Vasut { 122*e8de0fa8SMarek Vasut int ret; 123*e8de0fa8SMarek Vasut 124*e8de0fa8SMarek Vasut puts("CPU: "); 125*e8de0fa8SMarek Vasut 126*e8de0fa8SMarek Vasut ret = print_cpuinfo_pxa2xx(); 127*e8de0fa8SMarek Vasut if (!ret) 128*e8de0fa8SMarek Vasut return ret; 129*e8de0fa8SMarek Vasut 130*e8de0fa8SMarek Vasut return ret; 131*e8de0fa8SMarek Vasut } 132*e8de0fa8SMarek Vasut #endif 133