11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * arch/sh/kernel/cpu/sh4/probe.c 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * CPU Subtype Probing for SH-4. 51da177e4SLinus Torvalds * 6e5723e0eSPaul Mundt * Copyright (C) 2001 - 2006 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> 14*11c19656SPaul Mundt #include <linux/io.h> 151da177e4SLinus Torvalds #include <asm/processor.h> 161da177e4SLinus Torvalds #include <asm/cache.h> 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds int __init detect_cpu_and_cache_system(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 3172c35543SPaul Mundt pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffffff; 321da177e4SLinus Torvalds prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff; 331da177e4SLinus Torvalds cvr = (ctrl_inl(CCN_CVR)); 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds /* 361da177e4SLinus Torvalds * Setup some sane SH-4 defaults for the icache 371da177e4SLinus Torvalds */ 38*11c19656SPaul Mundt current_cpu_data.icache.way_incr = (1 << 13); 39*11c19656SPaul Mundt current_cpu_data.icache.entry_shift = 5; 40*11c19656SPaul Mundt current_cpu_data.icache.sets = 256; 41*11c19656SPaul Mundt current_cpu_data.icache.ways = 1; 42*11c19656SPaul Mundt current_cpu_data.icache.linesz = L1_CACHE_BYTES; 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds /* 451da177e4SLinus Torvalds * And again for the dcache .. 461da177e4SLinus Torvalds */ 47*11c19656SPaul Mundt current_cpu_data.dcache.way_incr = (1 << 14); 48*11c19656SPaul Mundt current_cpu_data.dcache.entry_shift = 5; 49*11c19656SPaul Mundt current_cpu_data.dcache.sets = 512; 50*11c19656SPaul Mundt current_cpu_data.dcache.ways = 1; 51*11c19656SPaul Mundt current_cpu_data.dcache.linesz = L1_CACHE_BYTES; 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds /* 5472c35543SPaul Mundt * Setup some generic flags we can probe 5572c35543SPaul Mundt * (L2 and DSP detection only work on SH-4A) 5672c35543SPaul Mundt */ 5772c35543SPaul Mundt if (((pvr >> 16) & 0xff) == 0x10) { 5872c35543SPaul Mundt if ((cvr & 0x02000000) == 0) 59*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_L2_CACHE; 6072c35543SPaul Mundt if ((cvr & 0x10000000) == 0) 61*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_DSP; 6272c35543SPaul Mundt 63*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_LLSC; 6472c35543SPaul Mundt } 6572c35543SPaul Mundt 6672c35543SPaul Mundt /* FPU detection works for everyone */ 6772c35543SPaul Mundt if ((cvr & 0x20000000) == 1) 68*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_FPU; 6972c35543SPaul Mundt 7072c35543SPaul Mundt /* Mask off the upper chip ID */ 7172c35543SPaul Mundt pvr &= 0xffff; 7272c35543SPaul Mundt 7372c35543SPaul Mundt /* 741da177e4SLinus Torvalds * Probe the underlying processor version/revision and 751da177e4SLinus Torvalds * adjust cpu_data setup accordingly. 761da177e4SLinus Torvalds */ 771da177e4SLinus Torvalds switch (pvr) { 781da177e4SLinus Torvalds case 0x205: 79*11c19656SPaul Mundt current_cpu_data.type = CPU_SH7750; 80*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | 819b3a53abSStuart Menefy CPU_HAS_PERF_COUNTER; 821da177e4SLinus Torvalds break; 831da177e4SLinus Torvalds case 0x206: 84*11c19656SPaul Mundt current_cpu_data.type = CPU_SH7750S; 85*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | 869b3a53abSStuart Menefy CPU_HAS_PERF_COUNTER; 871da177e4SLinus Torvalds break; 881da177e4SLinus Torvalds case 0x1100: 89*11c19656SPaul Mundt current_cpu_data.type = CPU_SH7751; 90*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_FPU; 911da177e4SLinus Torvalds break; 921da177e4SLinus Torvalds case 0x2000: 93*11c19656SPaul Mundt current_cpu_data.type = CPU_SH73180; 94*11c19656SPaul Mundt current_cpu_data.icache.ways = 4; 95*11c19656SPaul Mundt current_cpu_data.dcache.ways = 4; 96*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_LLSC; 971da177e4SLinus Torvalds break; 985b19c908SPaul Mundt case 0x2001: 995b19c908SPaul Mundt case 0x2004: 100*11c19656SPaul Mundt current_cpu_data.type = CPU_SH7770; 101*11c19656SPaul Mundt current_cpu_data.icache.ways = 4; 102*11c19656SPaul Mundt current_cpu_data.dcache.ways = 4; 103749cf486SPaul Mundt 104*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_LLSC; 1055b19c908SPaul Mundt break; 1065b19c908SPaul Mundt case 0x2006: 1075b19c908SPaul Mundt case 0x200A: 1085b19c908SPaul Mundt if (prr == 0x61) 109*11c19656SPaul Mundt current_cpu_data.type = CPU_SH7781; 1105b19c908SPaul Mundt else 111*11c19656SPaul Mundt current_cpu_data.type = CPU_SH7780; 112749cf486SPaul Mundt 113*11c19656SPaul Mundt current_cpu_data.icache.ways = 4; 114*11c19656SPaul Mundt current_cpu_data.dcache.ways = 4; 115749cf486SPaul Mundt 116*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER | 117315bb968SPaul Mundt CPU_HAS_LLSC; 1185b19c908SPaul Mundt break; 119e5723e0eSPaul Mundt case 0x3000: 120e5723e0eSPaul Mundt case 0x3003: 12141504c39SPaul Mundt case 0x3009: 122*11c19656SPaul Mundt current_cpu_data.type = CPU_SH7343; 123*11c19656SPaul Mundt current_cpu_data.icache.ways = 4; 124*11c19656SPaul Mundt current_cpu_data.dcache.ways = 4; 125*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_LLSC; 126e5723e0eSPaul Mundt break; 12741504c39SPaul Mundt case 0x3008: 12841504c39SPaul Mundt if (prr == 0xa0) { 129*11c19656SPaul Mundt current_cpu_data.type = CPU_SH7722; 130*11c19656SPaul Mundt current_cpu_data.icache.ways = 4; 131*11c19656SPaul Mundt current_cpu_data.dcache.ways = 4; 132*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_LLSC; 13341504c39SPaul Mundt } 13441504c39SPaul Mundt break; 1351da177e4SLinus Torvalds case 0x8000: 136*11c19656SPaul Mundt current_cpu_data.type = CPU_ST40RA; 137*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_FPU; 1381da177e4SLinus Torvalds break; 1391da177e4SLinus Torvalds case 0x8100: 140*11c19656SPaul Mundt current_cpu_data.type = CPU_ST40GX1; 141*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_FPU; 1421da177e4SLinus Torvalds break; 1431da177e4SLinus Torvalds case 0x700: 144*11c19656SPaul Mundt current_cpu_data.type = CPU_SH4_501; 145*11c19656SPaul Mundt current_cpu_data.icache.ways = 2; 146*11c19656SPaul Mundt current_cpu_data.dcache.ways = 2; 1471da177e4SLinus Torvalds break; 1481da177e4SLinus Torvalds case 0x600: 149*11c19656SPaul Mundt current_cpu_data.type = CPU_SH4_202; 150*11c19656SPaul Mundt current_cpu_data.icache.ways = 2; 151*11c19656SPaul Mundt current_cpu_data.dcache.ways = 2; 152*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_FPU; 1531da177e4SLinus Torvalds break; 1541da177e4SLinus Torvalds case 0x500 ... 0x501: 1551da177e4SLinus Torvalds switch (prr) { 15673388cc7SPaul Mundt case 0x10: 157*11c19656SPaul Mundt current_cpu_data.type = CPU_SH7750R; 15873388cc7SPaul Mundt break; 15973388cc7SPaul Mundt case 0x11: 160*11c19656SPaul Mundt current_cpu_data.type = CPU_SH7751R; 16173388cc7SPaul Mundt break; 16273388cc7SPaul Mundt case 0x50 ... 0x5f: 163*11c19656SPaul Mundt current_cpu_data.type = CPU_SH7760; 16473388cc7SPaul Mundt break; 1651da177e4SLinus Torvalds } 1661da177e4SLinus Torvalds 167*11c19656SPaul Mundt current_cpu_data.icache.ways = 2; 168*11c19656SPaul Mundt current_cpu_data.dcache.ways = 2; 1691da177e4SLinus Torvalds 170*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_FPU; 171749cf486SPaul Mundt 1721da177e4SLinus Torvalds break; 1731da177e4SLinus Torvalds default: 174*11c19656SPaul Mundt current_cpu_data.type = CPU_SH_NONE; 1751da177e4SLinus Torvalds break; 1761da177e4SLinus Torvalds } 1771da177e4SLinus Torvalds 178b638d0b9SRichard Curnow #ifdef CONFIG_SH_DIRECT_MAPPED 179*11c19656SPaul Mundt current_cpu_data.icache.ways = 1; 180*11c19656SPaul Mundt current_cpu_data.dcache.ways = 1; 181*11c19656SPaul Mundt #endif 182*11c19656SPaul Mundt 183*11c19656SPaul Mundt #ifdef CONFIG_CPU_HAS_PTEA 184*11c19656SPaul Mundt current_cpu_data.flags |= CPU_HAS_PTEA; 185b638d0b9SRichard Curnow #endif 186b638d0b9SRichard Curnow 1871da177e4SLinus Torvalds /* 1881da177e4SLinus Torvalds * On anything that's not a direct-mapped cache, look to the CVR 1891da177e4SLinus Torvalds * for I/D-cache specifics. 1901da177e4SLinus Torvalds */ 191*11c19656SPaul Mundt if (current_cpu_data.icache.ways > 1) { 1921da177e4SLinus Torvalds size = sizes[(cvr >> 20) & 0xf]; 193*11c19656SPaul Mundt current_cpu_data.icache.way_incr = (size >> 1); 194*11c19656SPaul Mundt current_cpu_data.icache.sets = (size >> 6); 195d15f4560SPaul Mundt 1961da177e4SLinus Torvalds } 1971da177e4SLinus Torvalds 198d15f4560SPaul Mundt /* Setup the rest of the I-cache info */ 199*11c19656SPaul Mundt current_cpu_data.icache.entry_mask = current_cpu_data.icache.way_incr - 200*11c19656SPaul Mundt current_cpu_data.icache.linesz; 201d15f4560SPaul Mundt 202*11c19656SPaul Mundt current_cpu_data.icache.way_size = current_cpu_data.icache.sets * 203*11c19656SPaul Mundt current_cpu_data.icache.linesz; 204b638d0b9SRichard Curnow 205d15f4560SPaul Mundt /* And the rest of the D-cache */ 206*11c19656SPaul Mundt if (current_cpu_data.dcache.ways > 1) { 2071da177e4SLinus Torvalds size = sizes[(cvr >> 16) & 0xf]; 208*11c19656SPaul Mundt current_cpu_data.dcache.way_incr = (size >> 1); 209*11c19656SPaul Mundt current_cpu_data.dcache.sets = (size >> 6); 2101da177e4SLinus Torvalds } 2111da177e4SLinus Torvalds 212*11c19656SPaul Mundt current_cpu_data.dcache.entry_mask = current_cpu_data.dcache.way_incr - 213*11c19656SPaul Mundt current_cpu_data.dcache.linesz; 214d15f4560SPaul Mundt 215*11c19656SPaul Mundt current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets * 216*11c19656SPaul Mundt current_cpu_data.dcache.linesz; 217b638d0b9SRichard Curnow 21872c35543SPaul Mundt /* 21972c35543SPaul Mundt * Setup the L2 cache desc 22072c35543SPaul Mundt * 22172c35543SPaul Mundt * SH-4A's have an optional PIPT L2. 22272c35543SPaul Mundt */ 223*11c19656SPaul Mundt if (current_cpu_data.flags & CPU_HAS_L2_CACHE) { 22472c35543SPaul Mundt /* 22572c35543SPaul Mundt * Size calculation is much more sensible 22672c35543SPaul Mundt * than it is for the L1. 22772c35543SPaul Mundt * 22872c35543SPaul Mundt * Sizes are 128KB, 258KB, 512KB, and 1MB. 22972c35543SPaul Mundt */ 23072c35543SPaul Mundt size = (cvr & 0xf) << 17; 23172c35543SPaul Mundt 23272c35543SPaul Mundt BUG_ON(!size); 23372c35543SPaul Mundt 234*11c19656SPaul Mundt current_cpu_data.scache.way_incr = (1 << 16); 235*11c19656SPaul Mundt current_cpu_data.scache.entry_shift = 5; 236*11c19656SPaul Mundt current_cpu_data.scache.ways = 4; 237*11c19656SPaul Mundt current_cpu_data.scache.linesz = L1_CACHE_BYTES; 238*11c19656SPaul Mundt 239*11c19656SPaul Mundt current_cpu_data.scache.entry_mask = 240*11c19656SPaul Mundt (current_cpu_data.scache.way_incr - 241*11c19656SPaul Mundt current_cpu_data.scache.linesz); 242*11c19656SPaul Mundt 243*11c19656SPaul Mundt current_cpu_data.scache.sets = size / 244*11c19656SPaul Mundt (current_cpu_data.scache.linesz * 245*11c19656SPaul Mundt current_cpu_data.scache.ways); 246*11c19656SPaul Mundt 247*11c19656SPaul Mundt current_cpu_data.scache.way_size = 248*11c19656SPaul Mundt (current_cpu_data.scache.sets * 249*11c19656SPaul Mundt current_cpu_data.scache.linesz); 25072c35543SPaul Mundt } 25172c35543SPaul Mundt 2521da177e4SLinus Torvalds return 0; 2531da177e4SLinus Torvalds } 254