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 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 */ 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 531da177e4SLinus Torvalds /* 5426fad19dSPaul Mundt * Setup some generic flags we can probe on SH-4A parts 5572c35543SPaul Mundt */ 5672c35543SPaul Mundt if (((pvr >> 16) & 0xff) == 0x10) { 5772c35543SPaul Mundt if ((cvr & 0x10000000) == 0) 58cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_DSP; 5972c35543SPaul Mundt 60cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_LLSC; 6172c35543SPaul Mundt } 6272c35543SPaul Mundt 6372c35543SPaul Mundt /* FPU detection works for everyone */ 6472c35543SPaul Mundt if ((cvr & 0x20000000) == 1) 65cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU; 6672c35543SPaul Mundt 6772c35543SPaul Mundt /* Mask off the upper chip ID */ 6872c35543SPaul Mundt pvr &= 0xffff; 6972c35543SPaul Mundt 7072c35543SPaul Mundt /* 711da177e4SLinus Torvalds * Probe the underlying processor version/revision and 721da177e4SLinus Torvalds * adjust cpu_data setup accordingly. 731da177e4SLinus Torvalds */ 741da177e4SLinus Torvalds switch (pvr) { 751da177e4SLinus Torvalds case 0x205: 76cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7750; 77cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | 789b3a53abSStuart Menefy CPU_HAS_PERF_COUNTER; 791da177e4SLinus Torvalds break; 801da177e4SLinus Torvalds case 0x206: 81cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7750S; 82cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | 839b3a53abSStuart Menefy CPU_HAS_PERF_COUNTER; 841da177e4SLinus Torvalds break; 851da177e4SLinus Torvalds case 0x1100: 86cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7751; 87cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU; 881da177e4SLinus Torvalds break; 895b19c908SPaul Mundt case 0x2001: 905b19c908SPaul Mundt case 0x2004: 91cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7770; 92cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 4; 93cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 4; 94749cf486SPaul Mundt 95cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_LLSC; 965b19c908SPaul Mundt break; 975b19c908SPaul Mundt case 0x2006: 985b19c908SPaul Mundt case 0x200A: 995b19c908SPaul Mundt if (prr == 0x61) 100cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7781; 1017d740a06SYoshihiro Shimoda else if (prr == 0xa1) 1027d740a06SYoshihiro Shimoda boot_cpu_data.type = CPU_SH7763; 1035b19c908SPaul Mundt else 104cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7780; 105749cf486SPaul Mundt 106cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 4; 107cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 4; 108749cf486SPaul Mundt 109cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER | 110315bb968SPaul Mundt CPU_HAS_LLSC; 1115b19c908SPaul Mundt break; 112e5723e0eSPaul Mundt case 0x3000: 113e5723e0eSPaul Mundt case 0x3003: 11441504c39SPaul Mundt case 0x3009: 115cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7343; 116cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 4; 117cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 4; 118cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_LLSC; 119e5723e0eSPaul Mundt break; 12032351a28SPaul Mundt case 0x3004: 12132351a28SPaul Mundt case 0x3007: 122cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7785; 123cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 4; 124cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 4; 125cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER | 12632351a28SPaul Mundt CPU_HAS_LLSC; 12732351a28SPaul Mundt break; 12841504c39SPaul Mundt case 0x3008: 129cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 4; 130cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 4; 131cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_LLSC; 132*178dd0cdSPaul Mundt 133*178dd0cdSPaul Mundt switch (prr) { 134*178dd0cdSPaul Mundt case 0x50: 135*178dd0cdSPaul Mundt boot_cpu_data.type = CPU_SH7723; 136*178dd0cdSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_L2_CACHE; 137*178dd0cdSPaul Mundt break; 138*178dd0cdSPaul Mundt case 0x70: 1399109a30eSMagnus Damm boot_cpu_data.type = CPU_SH7366; 140*178dd0cdSPaul Mundt break; 141*178dd0cdSPaul Mundt case 0xa0: 142*178dd0cdSPaul Mundt case 0xa1: 143*178dd0cdSPaul Mundt boot_cpu_data.type = CPU_SH7722; 144*178dd0cdSPaul Mundt break; 1459109a30eSMagnus Damm } 14641504c39SPaul Mundt break; 1472b1bd1acSPaul Mundt case 0x4000: /* 1st cut */ 1482b1bd1acSPaul Mundt case 0x4001: /* 2nd cut */ 149cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SHX3; 150cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 4; 151cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 4; 152cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER | 1532b1bd1acSPaul Mundt CPU_HAS_LLSC; 1542b1bd1acSPaul Mundt break; 1551da177e4SLinus Torvalds case 0x700: 156cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH4_501; 157cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 2; 158cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 2; 1591da177e4SLinus Torvalds break; 1601da177e4SLinus Torvalds case 0x600: 161cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH4_202; 162cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 2; 163cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 2; 164cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU; 1651da177e4SLinus Torvalds break; 1661da177e4SLinus Torvalds case 0x500 ... 0x501: 1671da177e4SLinus Torvalds switch (prr) { 16873388cc7SPaul Mundt case 0x10: 169cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7750R; 17073388cc7SPaul Mundt break; 17173388cc7SPaul Mundt case 0x11: 172cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7751R; 17373388cc7SPaul Mundt break; 17473388cc7SPaul Mundt case 0x50 ... 0x5f: 175cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7760; 17673388cc7SPaul Mundt break; 1771da177e4SLinus Torvalds } 1781da177e4SLinus Torvalds 179cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 2; 180cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 2; 1811da177e4SLinus Torvalds 182cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU; 183749cf486SPaul Mundt 1841da177e4SLinus Torvalds break; 1851da177e4SLinus Torvalds default: 186cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH_NONE; 1871da177e4SLinus Torvalds break; 1881da177e4SLinus Torvalds } 1891da177e4SLinus Torvalds 190b638d0b9SRichard Curnow #ifdef CONFIG_SH_DIRECT_MAPPED 191cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 1; 192cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 1; 19311c19656SPaul Mundt #endif 19411c19656SPaul Mundt 19511c19656SPaul Mundt #ifdef CONFIG_CPU_HAS_PTEA 196cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_PTEA; 197b638d0b9SRichard Curnow #endif 198b638d0b9SRichard Curnow 1991da177e4SLinus Torvalds /* 2001da177e4SLinus Torvalds * On anything that's not a direct-mapped cache, look to the CVR 2011da177e4SLinus Torvalds * for I/D-cache specifics. 2021da177e4SLinus Torvalds */ 203cb7af21fSPaul Mundt if (boot_cpu_data.icache.ways > 1) { 2041da177e4SLinus Torvalds size = sizes[(cvr >> 20) & 0xf]; 205cb7af21fSPaul Mundt boot_cpu_data.icache.way_incr = (size >> 1); 206cb7af21fSPaul Mundt boot_cpu_data.icache.sets = (size >> 6); 207d15f4560SPaul Mundt 2081da177e4SLinus Torvalds } 2091da177e4SLinus Torvalds 210d15f4560SPaul Mundt /* And the rest of the D-cache */ 211cb7af21fSPaul Mundt if (boot_cpu_data.dcache.ways > 1) { 2121da177e4SLinus Torvalds size = sizes[(cvr >> 16) & 0xf]; 213cb7af21fSPaul Mundt boot_cpu_data.dcache.way_incr = (size >> 1); 214cb7af21fSPaul Mundt boot_cpu_data.dcache.sets = (size >> 6); 2151da177e4SLinus Torvalds } 2161da177e4SLinus Torvalds 21772c35543SPaul Mundt /* 21872c35543SPaul Mundt * Setup the L2 cache desc 21972c35543SPaul Mundt * 22072c35543SPaul Mundt * SH-4A's have an optional PIPT L2. 22172c35543SPaul Mundt */ 222cb7af21fSPaul Mundt if (boot_cpu_data.flags & CPU_HAS_L2_CACHE) { 22372c35543SPaul Mundt /* 22472c35543SPaul Mundt * Size calculation is much more sensible 22572c35543SPaul Mundt * than it is for the L1. 22672c35543SPaul Mundt * 22772c35543SPaul Mundt * Sizes are 128KB, 258KB, 512KB, and 1MB. 22872c35543SPaul Mundt */ 22972c35543SPaul Mundt size = (cvr & 0xf) << 17; 23072c35543SPaul Mundt 23172c35543SPaul Mundt BUG_ON(!size); 23272c35543SPaul Mundt 233cb7af21fSPaul Mundt boot_cpu_data.scache.way_incr = (1 << 16); 234cb7af21fSPaul Mundt boot_cpu_data.scache.entry_shift = 5; 235cb7af21fSPaul Mundt boot_cpu_data.scache.ways = 4; 236cb7af21fSPaul Mundt boot_cpu_data.scache.linesz = L1_CACHE_BYTES; 23711c19656SPaul Mundt 238cb7af21fSPaul Mundt boot_cpu_data.scache.entry_mask = 239cb7af21fSPaul Mundt (boot_cpu_data.scache.way_incr - 240cb7af21fSPaul Mundt boot_cpu_data.scache.linesz); 24111c19656SPaul Mundt 242cb7af21fSPaul Mundt boot_cpu_data.scache.sets = size / 243cb7af21fSPaul Mundt (boot_cpu_data.scache.linesz * 244cb7af21fSPaul Mundt boot_cpu_data.scache.ways); 24511c19656SPaul Mundt 246cb7af21fSPaul Mundt boot_cpu_data.scache.way_size = 247cb7af21fSPaul Mundt (boot_cpu_data.scache.sets * 248cb7af21fSPaul Mundt boot_cpu_data.scache.linesz); 24972c35543SPaul Mundt } 25072c35543SPaul Mundt 2511da177e4SLinus Torvalds return 0; 2521da177e4SLinus Torvalds } 253