1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * PXA CPU information display 4 * 5 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com> 6 */ 7 8 #include <common.h> 9 #include <asm/io.h> 10 #include <errno.h> 11 #include <linux/compiler.h> 12 13 #ifdef CONFIG_CPU_PXA25X 14 #if ((CONFIG_SYS_INIT_SP_ADDR) != 0xfffff800) 15 #error "Init SP address must be set to 0xfffff800 for PXA250" 16 #endif 17 #endif 18 19 #define CPU_MASK_PXA_PRODID 0x000003f0 20 #define CPU_MASK_PXA_REVID 0x0000000f 21 22 #define CPU_MASK_PRODREV (CPU_MASK_PXA_PRODID | CPU_MASK_PXA_REVID) 23 24 #define CPU_VALUE_PXA25X 0x100 25 #define CPU_VALUE_PXA27X 0x110 26 27 static uint32_t pxa_get_cpuid(void) 28 { 29 uint32_t cpuid; 30 asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r"(cpuid)); 31 return cpuid; 32 } 33 34 int cpu_is_pxa25x(void) 35 { 36 uint32_t id = pxa_get_cpuid(); 37 id &= CPU_MASK_PXA_PRODID; 38 return id == CPU_VALUE_PXA25X; 39 } 40 41 int cpu_is_pxa27x(void) 42 { 43 uint32_t id = pxa_get_cpuid(); 44 id &= CPU_MASK_PXA_PRODID; 45 return id == CPU_VALUE_PXA27X; 46 } 47 48 int cpu_is_pxa27xm(void) 49 { 50 uint32_t id = pxa_get_cpuid(); 51 return ((id & CPU_MASK_PXA_PRODID) == CPU_VALUE_PXA27X) && 52 ((id & CPU_MASK_PXA_REVID) == 8); 53 } 54 55 uint32_t pxa_get_cpu_revision(void) 56 { 57 return pxa_get_cpuid() & CPU_MASK_PRODREV; 58 } 59 60 #ifdef CONFIG_DISPLAY_CPUINFO 61 static const char *pxa25x_get_revision(void) 62 { 63 static __maybe_unused const char * const revs_25x[] = { "A0" }; 64 static __maybe_unused const char * const revs_26x[] = { 65 "A0", "B0", "B1" 66 }; 67 static const char *unknown = "Unknown"; 68 uint32_t id; 69 70 if (!cpu_is_pxa25x()) 71 return unknown; 72 73 id = pxa_get_cpuid() & CPU_MASK_PXA_REVID; 74 75 /* PXA26x is a sick special case as it can't be told apart from PXA25x :-( */ 76 #ifdef CONFIG_CPU_PXA26X 77 switch (id) { 78 case 3: return revs_26x[0]; 79 case 5: return revs_26x[1]; 80 case 6: return revs_26x[2]; 81 } 82 #else 83 if (id == 6) 84 return revs_25x[0]; 85 #endif 86 return unknown; 87 } 88 89 static const char *pxa27x_get_revision(void) 90 { 91 static const char *const rev[] = { "A0", "A1", "B0", "B1", "C0", "C5" }; 92 static const char *unknown = "Unknown"; 93 uint32_t id; 94 95 if (!cpu_is_pxa27x()) 96 return unknown; 97 98 id = pxa_get_cpuid() & CPU_MASK_PXA_REVID; 99 100 if ((id == 5) || (id == 6) || (id > 8)) 101 return unknown; 102 103 /* Cap the special PXA270 C5 case. */ 104 if (id == 7) 105 id = 5; 106 107 /* Cap the special PXA270M A1 case. */ 108 if (id == 8) 109 id = 1; 110 111 return rev[id]; 112 } 113 114 static int print_cpuinfo_pxa2xx(void) 115 { 116 if (cpu_is_pxa25x()) { 117 puts("Marvell PXA25x rev. "); 118 puts(pxa25x_get_revision()); 119 } else if (cpu_is_pxa27x()) { 120 puts("Marvell PXA27x"); 121 if (cpu_is_pxa27xm()) puts("M"); 122 puts(" rev. "); 123 puts(pxa27x_get_revision()); 124 } else 125 return -EINVAL; 126 127 puts("\n"); 128 129 return 0; 130 } 131 132 int print_cpuinfo(void) 133 { 134 int ret; 135 136 puts("CPU: "); 137 138 ret = print_cpuinfo_pxa2xx(); 139 if (!ret) 140 return ret; 141 142 return ret; 143 } 144 #endif 145