11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * arch/sh/kernel/cpu/sh4/probe.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * CPU Subtype Probing for SH-4. 51da177e4SLinus Torvalds * 626fad19dSPaul Mundt * Copyright (C) 2001 - 2007 Paul Mundt 71da177e4SLinus Torvalds * Copyright (C) 2003 Richard Curnow 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 101da177e4SLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 111da177e4SLinus Torvalds * for more details. 121da177e4SLinus Torvalds */ 131da177e4SLinus Torvalds #include <linux/init.h> 1411c19656SPaul Mundt #include <linux/io.h> 151da177e4SLinus Torvalds #include <asm/processor.h> 161da177e4SLinus Torvalds #include <asm/cache.h> 171da177e4SLinus Torvalds 18a9079ca0SPaul Mundt void __cpuinit cpu_probe(void) 191da177e4SLinus Torvalds { 201da177e4SLinus Torvalds unsigned long pvr, prr, cvr; 211da177e4SLinus Torvalds unsigned long size; 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds static unsigned long sizes[16] = { 241da177e4SLinus Torvalds [1] = (1 << 12), 251da177e4SLinus Torvalds [2] = (1 << 13), 261da177e4SLinus Torvalds [4] = (1 << 14), 271da177e4SLinus Torvalds [8] = (1 << 15), 281da177e4SLinus Torvalds [9] = (1 << 16) 291da177e4SLinus Torvalds }; 301da177e4SLinus Torvalds 319d56dd3bSPaul Mundt pvr = (__raw_readl(CCN_PVR) >> 8) & 0xffffff; 329d56dd3bSPaul Mundt prr = (__raw_readl(CCN_PRR) >> 4) & 0xff; 339d56dd3bSPaul Mundt cvr = (__raw_readl(CCN_CVR)); 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds /* 361da177e4SLinus Torvalds * Setup some sane SH-4 defaults for the icache 371da177e4SLinus Torvalds */ 38cb7af21fSPaul Mundt boot_cpu_data.icache.way_incr = (1 << 13); 39cb7af21fSPaul Mundt boot_cpu_data.icache.entry_shift = 5; 40cb7af21fSPaul Mundt boot_cpu_data.icache.sets = 256; 41cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 1; 42cb7af21fSPaul Mundt boot_cpu_data.icache.linesz = L1_CACHE_BYTES; 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds /* 451da177e4SLinus Torvalds * And again for the dcache .. 461da177e4SLinus Torvalds */ 47cb7af21fSPaul Mundt boot_cpu_data.dcache.way_incr = (1 << 14); 48cb7af21fSPaul Mundt boot_cpu_data.dcache.entry_shift = 5; 49cb7af21fSPaul Mundt boot_cpu_data.dcache.sets = 512; 50cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 1; 51cb7af21fSPaul Mundt boot_cpu_data.dcache.linesz = L1_CACHE_BYTES; 521da177e4SLinus Torvalds 53068f5914SPaul Mundt /* We don't know the chip cut */ 54068f5914SPaul Mundt boot_cpu_data.cut_major = boot_cpu_data.cut_minor = -1; 55068f5914SPaul Mundt 561da177e4SLinus Torvalds /* 5726fad19dSPaul Mundt * Setup some generic flags we can probe on SH-4A parts 5872c35543SPaul Mundt */ 59068f5914SPaul Mundt if (((pvr >> 16) & 0xff) == 0x10) { 60e82da214SPaul Mundt boot_cpu_data.family = CPU_FAMILY_SH4A; 61e82da214SPaul Mundt 62e82da214SPaul Mundt if ((cvr & 0x10000000) == 0) { 63cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_DSP; 64e82da214SPaul Mundt boot_cpu_data.family = CPU_FAMILY_SH4AL_DSP; 65e82da214SPaul Mundt } 6672c35543SPaul Mundt 670bf8513eSPaul Mundt boot_cpu_data.flags |= CPU_HAS_LLSC | CPU_HAS_PERF_COUNTER; 68068f5914SPaul Mundt boot_cpu_data.cut_major = pvr & 0x7f; 690bf8513eSPaul Mundt 700bf8513eSPaul Mundt boot_cpu_data.icache.ways = 4; 710bf8513eSPaul Mundt boot_cpu_data.dcache.ways = 4; 720bf8513eSPaul Mundt } else { 730bf8513eSPaul Mundt /* And some SH-4 defaults.. */ 74bdc27300SPaul Mundt boot_cpu_data.flags |= CPU_HAS_PTEA | CPU_HAS_FPU; 75e82da214SPaul Mundt boot_cpu_data.family = CPU_FAMILY_SH4; 7672c35543SPaul Mundt } 7772c35543SPaul Mundt 78bdc27300SPaul Mundt /* FPU detection works for almost everyone */ 790bf8513eSPaul Mundt if ((cvr & 0x20000000)) 80cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU; 8172c35543SPaul Mundt 8272c35543SPaul Mundt /* Mask off the upper chip ID */ 8372c35543SPaul Mundt pvr &= 0xffff; 8472c35543SPaul Mundt 8572c35543SPaul Mundt /* 861da177e4SLinus Torvalds * Probe the underlying processor version/revision and 871da177e4SLinus Torvalds * adjust cpu_data setup accordingly. 881da177e4SLinus Torvalds */ 891da177e4SLinus Torvalds switch (pvr) { 901da177e4SLinus Torvalds case 0x205: 91cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7750; 920bf8513eSPaul Mundt boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | 939b3a53abSStuart Menefy CPU_HAS_PERF_COUNTER; 941da177e4SLinus Torvalds break; 951da177e4SLinus Torvalds case 0x206: 96cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7750S; 970bf8513eSPaul Mundt boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | 989b3a53abSStuart Menefy CPU_HAS_PERF_COUNTER; 991da177e4SLinus Torvalds break; 1001da177e4SLinus Torvalds case 0x1100: 101cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7751; 1021da177e4SLinus Torvalds break; 1035b19c908SPaul Mundt case 0x2001: 1045b19c908SPaul Mundt case 0x2004: 105cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7770; 1065b19c908SPaul Mundt break; 1075b19c908SPaul Mundt case 0x2006: 1085b19c908SPaul Mundt case 0x200A: 1095b19c908SPaul Mundt if (prr == 0x61) 110cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7781; 1117d740a06SYoshihiro Shimoda else if (prr == 0xa1) 1127d740a06SYoshihiro Shimoda boot_cpu_data.type = CPU_SH7763; 1135b19c908SPaul Mundt else 114cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7780; 115749cf486SPaul Mundt 1165b19c908SPaul Mundt break; 117e5723e0eSPaul Mundt case 0x3000: 118e5723e0eSPaul Mundt case 0x3003: 11941504c39SPaul Mundt case 0x3009: 120cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7343; 121e5723e0eSPaul Mundt break; 12232351a28SPaul Mundt case 0x3004: 12332351a28SPaul Mundt case 0x3007: 124cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7785; 12532351a28SPaul Mundt break; 12655ba99ebSKuninori Morimoto case 0x4004: 1277f33306eSMatt Fleming case 0x4005: 12855ba99ebSKuninori Morimoto boot_cpu_data.type = CPU_SH7786; 1290bf8513eSPaul Mundt boot_cpu_data.flags |= CPU_HAS_PTEAEX | CPU_HAS_L2_CACHE; 13055ba99ebSKuninori Morimoto break; 13141504c39SPaul Mundt case 0x3008: 132178dd0cdSPaul Mundt switch (prr) { 133178dd0cdSPaul Mundt case 0x50: 134b76baf4cSMagnus Damm case 0x51: 135178dd0cdSPaul Mundt boot_cpu_data.type = CPU_SH7723; 1360bf8513eSPaul Mundt boot_cpu_data.flags |= CPU_HAS_L2_CACHE; 137178dd0cdSPaul Mundt break; 138178dd0cdSPaul Mundt case 0x70: 1399109a30eSMagnus Damm boot_cpu_data.type = CPU_SH7366; 140178dd0cdSPaul Mundt break; 141178dd0cdSPaul Mundt case 0xa0: 142178dd0cdSPaul Mundt case 0xa1: 143178dd0cdSPaul Mundt boot_cpu_data.type = CPU_SH7722; 144178dd0cdSPaul Mundt break; 1459109a30eSMagnus Damm } 14641504c39SPaul Mundt break; 1470207a2efSKuninori Morimoto case 0x300b: 148c01f0f1aSYoshihiro Shimoda switch (prr) { 149c01f0f1aSYoshihiro Shimoda case 0x20: 1500207a2efSKuninori Morimoto boot_cpu_data.type = CPU_SH7724; 1510bf8513eSPaul Mundt boot_cpu_data.flags |= CPU_HAS_L2_CACHE; 1520207a2efSKuninori Morimoto break; 153*e81e5ce2SYoshihiro Shimoda case 0x10: 154c01f0f1aSYoshihiro Shimoda boot_cpu_data.type = CPU_SH7757; 155c01f0f1aSYoshihiro Shimoda break; 156c01f0f1aSYoshihiro Shimoda } 157c01f0f1aSYoshihiro Shimoda break; 1582b1bd1acSPaul Mundt case 0x4000: /* 1st cut */ 1592b1bd1acSPaul Mundt case 0x4001: /* 2nd cut */ 160cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SHX3; 1612b1bd1acSPaul Mundt break; 1621da177e4SLinus Torvalds case 0x700: 163cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH4_501; 164bdc27300SPaul Mundt boot_cpu_data.flags &= ~CPU_HAS_FPU; 165cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 2; 166cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 2; 1671da177e4SLinus Torvalds break; 1681da177e4SLinus Torvalds case 0x600: 169cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH4_202; 170cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 2; 171cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 2; 1721da177e4SLinus Torvalds break; 1731da177e4SLinus Torvalds case 0x500 ... 0x501: 1741da177e4SLinus Torvalds switch (prr) { 17573388cc7SPaul Mundt case 0x10: 176cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7750R; 17773388cc7SPaul Mundt break; 17873388cc7SPaul Mundt case 0x11: 179cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7751R; 18073388cc7SPaul Mundt break; 18173388cc7SPaul Mundt case 0x50 ... 0x5f: 182cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7760; 18373388cc7SPaul Mundt break; 1841da177e4SLinus Torvalds } 1851da177e4SLinus Torvalds 186cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 2; 187cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 2; 1881da177e4SLinus Torvalds 1891da177e4SLinus Torvalds break; 1901da177e4SLinus Torvalds } 1911da177e4SLinus Torvalds 1921da177e4SLinus Torvalds /* 1931da177e4SLinus Torvalds * On anything that's not a direct-mapped cache, look to the CVR 1941da177e4SLinus Torvalds * for I/D-cache specifics. 1951da177e4SLinus Torvalds */ 196cb7af21fSPaul Mundt if (boot_cpu_data.icache.ways > 1) { 1971da177e4SLinus Torvalds size = sizes[(cvr >> 20) & 0xf]; 198cb7af21fSPaul Mundt boot_cpu_data.icache.way_incr = (size >> 1); 199cb7af21fSPaul Mundt boot_cpu_data.icache.sets = (size >> 6); 200d15f4560SPaul Mundt 2011da177e4SLinus Torvalds } 2021da177e4SLinus Torvalds 203d15f4560SPaul Mundt /* And the rest of the D-cache */ 204cb7af21fSPaul Mundt if (boot_cpu_data.dcache.ways > 1) { 2051da177e4SLinus Torvalds size = sizes[(cvr >> 16) & 0xf]; 206cb7af21fSPaul Mundt boot_cpu_data.dcache.way_incr = (size >> 1); 207cb7af21fSPaul Mundt boot_cpu_data.dcache.sets = (size >> 6); 2081da177e4SLinus Torvalds } 2091da177e4SLinus Torvalds 21072c35543SPaul Mundt /* 21172c35543SPaul Mundt * SH-4A's have an optional PIPT L2. 21272c35543SPaul Mundt */ 213cb7af21fSPaul Mundt if (boot_cpu_data.flags & CPU_HAS_L2_CACHE) { 2147863d3f7SPaul Mundt /* 2157863d3f7SPaul Mundt * Verify that it really has something hooked up, this 2167863d3f7SPaul Mundt * is the safety net for CPUs that have optional L2 2177863d3f7SPaul Mundt * support yet do not implement it. 2187863d3f7SPaul Mundt */ 2197863d3f7SPaul Mundt if ((cvr & 0xf) == 0) 2207863d3f7SPaul Mundt boot_cpu_data.flags &= ~CPU_HAS_L2_CACHE; 2217863d3f7SPaul Mundt else { 2227863d3f7SPaul Mundt /* 2237863d3f7SPaul Mundt * Silicon and specifications have clearly never 2247863d3f7SPaul Mundt * met.. 2257863d3f7SPaul Mundt */ 226440fc172SPaul Mundt cvr ^= 0xf; 227440fc172SPaul Mundt 22872c35543SPaul Mundt /* 22972c35543SPaul Mundt * Size calculation is much more sensible 23072c35543SPaul Mundt * than it is for the L1. 23172c35543SPaul Mundt * 23288f73d22SPaul Mundt * Sizes are 128KB, 256KB, 512KB, and 1MB. 23372c35543SPaul Mundt */ 23472c35543SPaul Mundt size = (cvr & 0xf) << 17; 23572c35543SPaul Mundt 236cb7af21fSPaul Mundt boot_cpu_data.scache.way_incr = (1 << 16); 237cb7af21fSPaul Mundt boot_cpu_data.scache.entry_shift = 5; 238cb7af21fSPaul Mundt boot_cpu_data.scache.ways = 4; 239cb7af21fSPaul Mundt boot_cpu_data.scache.linesz = L1_CACHE_BYTES; 24011c19656SPaul Mundt 241cb7af21fSPaul Mundt boot_cpu_data.scache.entry_mask = 242cb7af21fSPaul Mundt (boot_cpu_data.scache.way_incr - 243cb7af21fSPaul Mundt boot_cpu_data.scache.linesz); 24411c19656SPaul Mundt 245cb7af21fSPaul Mundt boot_cpu_data.scache.sets = size / 246cb7af21fSPaul Mundt (boot_cpu_data.scache.linesz * 247cb7af21fSPaul Mundt boot_cpu_data.scache.ways); 24811c19656SPaul Mundt 249cb7af21fSPaul Mundt boot_cpu_data.scache.way_size = 250cb7af21fSPaul Mundt (boot_cpu_data.scache.sets * 251cb7af21fSPaul Mundt boot_cpu_data.scache.linesz); 25272c35543SPaul Mundt } 2537863d3f7SPaul Mundt } 2541da177e4SLinus Torvalds } 255