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 141da177e4SLinus Torvalds #include <linux/init.h> 151da177e4SLinus Torvalds #include <asm/processor.h> 161da177e4SLinus Torvalds #include <asm/cache.h> 171da177e4SLinus Torvalds #include <asm/io.h> 181da177e4SLinus Torvalds 191da177e4SLinus Torvalds int __init detect_cpu_and_cache_system(void) 201da177e4SLinus Torvalds { 211da177e4SLinus Torvalds unsigned long pvr, prr, cvr; 221da177e4SLinus Torvalds unsigned long size; 231da177e4SLinus Torvalds 241da177e4SLinus Torvalds static unsigned long sizes[16] = { 251da177e4SLinus Torvalds [1] = (1 << 12), 261da177e4SLinus Torvalds [2] = (1 << 13), 271da177e4SLinus Torvalds [4] = (1 << 14), 281da177e4SLinus Torvalds [8] = (1 << 15), 291da177e4SLinus Torvalds [9] = (1 << 16) 301da177e4SLinus Torvalds }; 311da177e4SLinus Torvalds 3272c35543SPaul Mundt pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffffff; 331da177e4SLinus Torvalds prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff; 341da177e4SLinus Torvalds cvr = (ctrl_inl(CCN_CVR)); 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds /* 371da177e4SLinus Torvalds * Setup some sane SH-4 defaults for the icache 381da177e4SLinus Torvalds */ 391da177e4SLinus Torvalds cpu_data->icache.way_incr = (1 << 13); 401da177e4SLinus Torvalds cpu_data->icache.entry_shift = 5; 411da177e4SLinus Torvalds cpu_data->icache.sets = 256; 421da177e4SLinus Torvalds cpu_data->icache.ways = 1; 431da177e4SLinus Torvalds cpu_data->icache.linesz = L1_CACHE_BYTES; 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds /* 461da177e4SLinus Torvalds * And again for the dcache .. 471da177e4SLinus Torvalds */ 481da177e4SLinus Torvalds cpu_data->dcache.way_incr = (1 << 14); 491da177e4SLinus Torvalds cpu_data->dcache.entry_shift = 5; 501da177e4SLinus Torvalds cpu_data->dcache.sets = 512; 511da177e4SLinus Torvalds cpu_data->dcache.ways = 1; 521da177e4SLinus Torvalds cpu_data->dcache.linesz = L1_CACHE_BYTES; 531da177e4SLinus Torvalds 541da177e4SLinus Torvalds /* 5572c35543SPaul Mundt * Setup some generic flags we can probe 5672c35543SPaul Mundt * (L2 and DSP detection only work on SH-4A) 5772c35543SPaul Mundt */ 5872c35543SPaul Mundt if (((pvr >> 16) & 0xff) == 0x10) { 5972c35543SPaul Mundt if ((cvr & 0x02000000) == 0) 6072c35543SPaul Mundt cpu_data->flags |= CPU_HAS_L2_CACHE; 6172c35543SPaul Mundt if ((cvr & 0x10000000) == 0) 6272c35543SPaul Mundt cpu_data->flags |= CPU_HAS_DSP; 6372c35543SPaul Mundt 6472c35543SPaul Mundt cpu_data->flags |= CPU_HAS_LLSC; 6572c35543SPaul Mundt } 6672c35543SPaul Mundt 6772c35543SPaul Mundt /* FPU detection works for everyone */ 6872c35543SPaul Mundt if ((cvr & 0x20000000) == 1) 6972c35543SPaul Mundt cpu_data->flags |= CPU_HAS_FPU; 7072c35543SPaul Mundt 7172c35543SPaul Mundt /* Mask off the upper chip ID */ 7272c35543SPaul Mundt pvr &= 0xffff; 7372c35543SPaul Mundt 7472c35543SPaul Mundt /* 751da177e4SLinus Torvalds * Probe the underlying processor version/revision and 761da177e4SLinus Torvalds * adjust cpu_data setup accordingly. 771da177e4SLinus Torvalds */ 781da177e4SLinus Torvalds switch (pvr) { 791da177e4SLinus Torvalds case 0x205: 801da177e4SLinus Torvalds cpu_data->type = CPU_SH7750; 81749cf486SPaul Mundt cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | 829b3a53abSStuart Menefy CPU_HAS_PERF_COUNTER; 831da177e4SLinus Torvalds break; 841da177e4SLinus Torvalds case 0x206: 851da177e4SLinus Torvalds cpu_data->type = CPU_SH7750S; 86749cf486SPaul Mundt cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | 879b3a53abSStuart Menefy CPU_HAS_PERF_COUNTER; 881da177e4SLinus Torvalds break; 891da177e4SLinus Torvalds case 0x1100: 901da177e4SLinus Torvalds cpu_data->type = CPU_SH7751; 919b3a53abSStuart Menefy cpu_data->flags |= CPU_HAS_FPU; 921da177e4SLinus Torvalds break; 931da177e4SLinus Torvalds case 0x2000: 941da177e4SLinus Torvalds cpu_data->type = CPU_SH73180; 951da177e4SLinus Torvalds cpu_data->icache.ways = 4; 961da177e4SLinus Torvalds cpu_data->dcache.ways = 4; 97315bb968SPaul Mundt cpu_data->flags |= CPU_HAS_LLSC; 981da177e4SLinus Torvalds break; 995b19c908SPaul Mundt case 0x2001: 1005b19c908SPaul Mundt case 0x2004: 1015b19c908SPaul Mundt cpu_data->type = CPU_SH7770; 1025b19c908SPaul Mundt cpu_data->icache.ways = 4; 1035b19c908SPaul Mundt cpu_data->dcache.ways = 4; 104749cf486SPaul Mundt 105315bb968SPaul Mundt cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_LLSC; 1065b19c908SPaul Mundt break; 1075b19c908SPaul Mundt case 0x2006: 1085b19c908SPaul Mundt case 0x200A: 1095b19c908SPaul Mundt if (prr == 0x61) 1105b19c908SPaul Mundt cpu_data->type = CPU_SH7781; 1115b19c908SPaul Mundt else 1125b19c908SPaul Mundt cpu_data->type = CPU_SH7780; 113749cf486SPaul Mundt 1145b19c908SPaul Mundt cpu_data->icache.ways = 4; 1155b19c908SPaul Mundt cpu_data->dcache.ways = 4; 116749cf486SPaul Mundt 117315bb968SPaul Mundt cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER | 118315bb968SPaul Mundt CPU_HAS_LLSC; 1195b19c908SPaul Mundt break; 120e5723e0eSPaul Mundt case 0x3000: 121e5723e0eSPaul Mundt case 0x3003: 122*41504c39SPaul Mundt case 0x3009: 123e5723e0eSPaul Mundt cpu_data->type = CPU_SH7343; 124e5723e0eSPaul Mundt cpu_data->icache.ways = 4; 125e5723e0eSPaul Mundt cpu_data->dcache.ways = 4; 126315bb968SPaul Mundt cpu_data->flags |= CPU_HAS_LLSC; 127e5723e0eSPaul Mundt break; 128*41504c39SPaul Mundt case 0x3008: 129*41504c39SPaul Mundt if (prr == 0xa0) { 130*41504c39SPaul Mundt cpu_data->type = CPU_SH7722; 131*41504c39SPaul Mundt cpu_data->icache.ways = 4; 132*41504c39SPaul Mundt cpu_data->dcache.ways = 4; 133*41504c39SPaul Mundt cpu_data->flags |= CPU_HAS_LLSC; 134*41504c39SPaul Mundt } 135*41504c39SPaul Mundt break; 1361da177e4SLinus Torvalds case 0x8000: 1371da177e4SLinus Torvalds cpu_data->type = CPU_ST40RA; 1389b3a53abSStuart Menefy cpu_data->flags |= CPU_HAS_FPU; 1391da177e4SLinus Torvalds break; 1401da177e4SLinus Torvalds case 0x8100: 1411da177e4SLinus Torvalds cpu_data->type = CPU_ST40GX1; 1429b3a53abSStuart Menefy cpu_data->flags |= CPU_HAS_FPU; 1431da177e4SLinus Torvalds break; 1441da177e4SLinus Torvalds case 0x700: 1451da177e4SLinus Torvalds cpu_data->type = CPU_SH4_501; 1461da177e4SLinus Torvalds cpu_data->icache.ways = 2; 1471da177e4SLinus Torvalds cpu_data->dcache.ways = 2; 1481da177e4SLinus Torvalds break; 1491da177e4SLinus Torvalds case 0x600: 1501da177e4SLinus Torvalds cpu_data->type = CPU_SH4_202; 1511da177e4SLinus Torvalds cpu_data->icache.ways = 2; 1521da177e4SLinus Torvalds cpu_data->dcache.ways = 2; 1539b3a53abSStuart Menefy cpu_data->flags |= CPU_HAS_FPU; 1541da177e4SLinus Torvalds break; 1551da177e4SLinus Torvalds case 0x500 ... 0x501: 1561da177e4SLinus Torvalds switch (prr) { 15773388cc7SPaul Mundt case 0x10: 15873388cc7SPaul Mundt cpu_data->type = CPU_SH7750R; 15973388cc7SPaul Mundt break; 16073388cc7SPaul Mundt case 0x11: 16173388cc7SPaul Mundt cpu_data->type = CPU_SH7751R; 16273388cc7SPaul Mundt break; 16373388cc7SPaul Mundt case 0x50 ... 0x5f: 16473388cc7SPaul Mundt cpu_data->type = CPU_SH7760; 16573388cc7SPaul Mundt break; 1661da177e4SLinus Torvalds } 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds cpu_data->icache.ways = 2; 1691da177e4SLinus Torvalds cpu_data->dcache.ways = 2; 1701da177e4SLinus Torvalds 1719b3a53abSStuart Menefy cpu_data->flags |= CPU_HAS_FPU; 172749cf486SPaul Mundt 1731da177e4SLinus Torvalds break; 1741da177e4SLinus Torvalds default: 1751da177e4SLinus Torvalds cpu_data->type = CPU_SH_NONE; 1761da177e4SLinus Torvalds break; 1771da177e4SLinus Torvalds } 1781da177e4SLinus Torvalds 179b638d0b9SRichard Curnow #ifdef CONFIG_SH_DIRECT_MAPPED 180b638d0b9SRichard Curnow cpu_data->icache.ways = 1; 181b638d0b9SRichard Curnow cpu_data->dcache.ways = 1; 182b638d0b9SRichard Curnow #endif 183b638d0b9SRichard Curnow 1849b3a53abSStuart Menefy #ifdef CONFIG_CPU_HAS_PTEA 1859b3a53abSStuart Menefy cpu_data->flags |= CPU_HAS_PTEA; 1869b3a53abSStuart Menefy #endif 1879b3a53abSStuart Menefy 1881da177e4SLinus Torvalds /* 1891da177e4SLinus Torvalds * On anything that's not a direct-mapped cache, look to the CVR 1901da177e4SLinus Torvalds * for I/D-cache specifics. 1911da177e4SLinus Torvalds */ 1921da177e4SLinus Torvalds if (cpu_data->icache.ways > 1) { 1931da177e4SLinus Torvalds size = sizes[(cvr >> 20) & 0xf]; 1941da177e4SLinus Torvalds cpu_data->icache.way_incr = (size >> 1); 1951da177e4SLinus Torvalds cpu_data->icache.sets = (size >> 6); 196d15f4560SPaul Mundt 1971da177e4SLinus Torvalds } 1981da177e4SLinus Torvalds 199d15f4560SPaul Mundt /* Setup the rest of the I-cache info */ 200d15f4560SPaul Mundt cpu_data->icache.entry_mask = cpu_data->icache.way_incr - 201d15f4560SPaul Mundt cpu_data->icache.linesz; 202d15f4560SPaul Mundt 203b638d0b9SRichard Curnow cpu_data->icache.way_size = cpu_data->icache.sets * 204b638d0b9SRichard Curnow cpu_data->icache.linesz; 205b638d0b9SRichard Curnow 206d15f4560SPaul Mundt /* And the rest of the D-cache */ 2071da177e4SLinus Torvalds if (cpu_data->dcache.ways > 1) { 2081da177e4SLinus Torvalds size = sizes[(cvr >> 16) & 0xf]; 2091da177e4SLinus Torvalds cpu_data->dcache.way_incr = (size >> 1); 2101da177e4SLinus Torvalds cpu_data->dcache.sets = (size >> 6); 2111da177e4SLinus Torvalds } 2121da177e4SLinus Torvalds 213d15f4560SPaul Mundt cpu_data->dcache.entry_mask = cpu_data->dcache.way_incr - 214d15f4560SPaul Mundt cpu_data->dcache.linesz; 215d15f4560SPaul Mundt 216b638d0b9SRichard Curnow cpu_data->dcache.way_size = cpu_data->dcache.sets * 217b638d0b9SRichard Curnow cpu_data->dcache.linesz; 218b638d0b9SRichard Curnow 21972c35543SPaul Mundt /* 22072c35543SPaul Mundt * Setup the L2 cache desc 22172c35543SPaul Mundt * 22272c35543SPaul Mundt * SH-4A's have an optional PIPT L2. 22372c35543SPaul Mundt */ 22472c35543SPaul Mundt if (cpu_data->flags & CPU_HAS_L2_CACHE) { 22572c35543SPaul Mundt /* 22672c35543SPaul Mundt * Size calculation is much more sensible 22772c35543SPaul Mundt * than it is for the L1. 22872c35543SPaul Mundt * 22972c35543SPaul Mundt * Sizes are 128KB, 258KB, 512KB, and 1MB. 23072c35543SPaul Mundt */ 23172c35543SPaul Mundt size = (cvr & 0xf) << 17; 23272c35543SPaul Mundt 23372c35543SPaul Mundt BUG_ON(!size); 23472c35543SPaul Mundt 23572c35543SPaul Mundt cpu_data->scache.way_incr = (1 << 16); 23672c35543SPaul Mundt cpu_data->scache.entry_shift = 5; 23772c35543SPaul Mundt cpu_data->scache.ways = 4; 23872c35543SPaul Mundt cpu_data->scache.linesz = L1_CACHE_BYTES; 239d15f4560SPaul Mundt cpu_data->scache.entry_mask = 240d15f4560SPaul Mundt (cpu_data->scache.way_incr - cpu_data->scache.linesz); 24172c35543SPaul Mundt cpu_data->scache.sets = size / 24272c35543SPaul Mundt (cpu_data->scache.linesz * cpu_data->scache.ways); 243d15f4560SPaul Mundt cpu_data->scache.way_size = 244d15f4560SPaul Mundt (cpu_data->scache.sets * cpu_data->scache.linesz); 24572c35543SPaul Mundt } 24672c35543SPaul Mundt 2471da177e4SLinus Torvalds return 0; 2481da177e4SLinus Torvalds } 249