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 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) { 6072c35543SPaul Mundt if ((cvr & 0x10000000) == 0) 61cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_DSP; 6272c35543SPaul Mundt 63cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_LLSC; 64068f5914SPaul Mundt boot_cpu_data.cut_major = pvr & 0x7f; 6572c35543SPaul Mundt } 6672c35543SPaul Mundt 6772c35543SPaul Mundt /* FPU detection works for everyone */ 6872c35543SPaul Mundt if ((cvr & 0x20000000) == 1) 69cb7af21fSPaul Mundt boot_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: 80cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7750; 81cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | 829b3a53abSStuart Menefy CPU_HAS_PERF_COUNTER; 831da177e4SLinus Torvalds break; 841da177e4SLinus Torvalds case 0x206: 85cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7750S; 86cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | 879b3a53abSStuart Menefy CPU_HAS_PERF_COUNTER; 881da177e4SLinus Torvalds break; 891da177e4SLinus Torvalds case 0x1100: 90cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7751; 91cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU; 921da177e4SLinus Torvalds break; 935b19c908SPaul Mundt case 0x2001: 945b19c908SPaul Mundt case 0x2004: 95cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7770; 96cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 4; 97cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 4; 98749cf486SPaul Mundt 99cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_LLSC; 1005b19c908SPaul Mundt break; 1015b19c908SPaul Mundt case 0x2006: 1025b19c908SPaul Mundt case 0x200A: 1035b19c908SPaul Mundt if (prr == 0x61) 104cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7781; 1057d740a06SYoshihiro Shimoda else if (prr == 0xa1) 1067d740a06SYoshihiro Shimoda boot_cpu_data.type = CPU_SH7763; 1075b19c908SPaul Mundt else 108cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7780; 109749cf486SPaul Mundt 110cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 4; 111cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 4; 112749cf486SPaul Mundt 113cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER | 114315bb968SPaul Mundt CPU_HAS_LLSC; 1155b19c908SPaul Mundt break; 116e5723e0eSPaul Mundt case 0x3000: 117e5723e0eSPaul Mundt case 0x3003: 11841504c39SPaul Mundt case 0x3009: 119cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7343; 120cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 4; 121cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 4; 122cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_LLSC; 123e5723e0eSPaul Mundt break; 12432351a28SPaul Mundt case 0x3004: 12532351a28SPaul Mundt case 0x3007: 126cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7785; 127cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 4; 128cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 4; 129cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER | 13032351a28SPaul Mundt CPU_HAS_LLSC; 13132351a28SPaul Mundt break; 13255ba99ebSKuninori Morimoto case 0x4004: 13355ba99ebSKuninori Morimoto boot_cpu_data.type = CPU_SH7786; 13455ba99ebSKuninori Morimoto boot_cpu_data.icache.ways = 4; 13555ba99ebSKuninori Morimoto boot_cpu_data.dcache.ways = 4; 13655ba99ebSKuninori Morimoto boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER | 137*7863d3f7SPaul Mundt CPU_HAS_LLSC | CPU_HAS_PTEAEX | CPU_HAS_L2_CACHE; 13855ba99ebSKuninori Morimoto break; 13941504c39SPaul Mundt case 0x3008: 140cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 4; 141cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 4; 142cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_LLSC; 143178dd0cdSPaul Mundt 144178dd0cdSPaul Mundt switch (prr) { 145178dd0cdSPaul Mundt case 0x50: 146b76baf4cSMagnus Damm case 0x51: 147178dd0cdSPaul Mundt boot_cpu_data.type = CPU_SH7723; 148178dd0cdSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_L2_CACHE; 149178dd0cdSPaul Mundt break; 150178dd0cdSPaul Mundt case 0x70: 1519109a30eSMagnus Damm boot_cpu_data.type = CPU_SH7366; 152178dd0cdSPaul Mundt break; 153178dd0cdSPaul Mundt case 0xa0: 154178dd0cdSPaul Mundt case 0xa1: 155178dd0cdSPaul Mundt boot_cpu_data.type = CPU_SH7722; 156178dd0cdSPaul Mundt break; 1579109a30eSMagnus Damm } 15841504c39SPaul Mundt break; 1590207a2efSKuninori Morimoto case 0x300b: 1600207a2efSKuninori Morimoto boot_cpu_data.type = CPU_SH7724; 1610207a2efSKuninori Morimoto boot_cpu_data.icache.ways = 4; 1620207a2efSKuninori Morimoto boot_cpu_data.dcache.ways = 4; 16398fbe45bSKuninori Morimoto boot_cpu_data.flags |= CPU_HAS_LLSC | CPU_HAS_FPU | CPU_HAS_L2_CACHE; 1640207a2efSKuninori Morimoto break; 1652b1bd1acSPaul Mundt case 0x4000: /* 1st cut */ 1662b1bd1acSPaul Mundt case 0x4001: /* 2nd cut */ 167cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SHX3; 168cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 4; 169cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 4; 170cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER | 1712b1bd1acSPaul Mundt CPU_HAS_LLSC; 1722b1bd1acSPaul Mundt break; 1731da177e4SLinus Torvalds case 0x700: 174cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH4_501; 175cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 2; 176cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 2; 1771da177e4SLinus Torvalds break; 1781da177e4SLinus Torvalds case 0x600: 179cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH4_202; 180cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 2; 181cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 2; 182cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU; 1831da177e4SLinus Torvalds break; 1841da177e4SLinus Torvalds case 0x500 ... 0x501: 1851da177e4SLinus Torvalds switch (prr) { 18673388cc7SPaul Mundt case 0x10: 187cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7750R; 18873388cc7SPaul Mundt break; 18973388cc7SPaul Mundt case 0x11: 190cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7751R; 19173388cc7SPaul Mundt break; 19273388cc7SPaul Mundt case 0x50 ... 0x5f: 193cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7760; 19473388cc7SPaul Mundt break; 1951da177e4SLinus Torvalds } 1961da177e4SLinus Torvalds 197cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 2; 198cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 2; 1991da177e4SLinus Torvalds 200cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU; 201749cf486SPaul Mundt 2021da177e4SLinus Torvalds break; 2031da177e4SLinus Torvalds default: 204cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH_NONE; 2051da177e4SLinus Torvalds break; 2061da177e4SLinus Torvalds } 2071da177e4SLinus Torvalds 20811c19656SPaul Mundt #ifdef CONFIG_CPU_HAS_PTEA 209cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_PTEA; 210b638d0b9SRichard Curnow #endif 211b638d0b9SRichard Curnow 2121da177e4SLinus Torvalds /* 2131da177e4SLinus Torvalds * On anything that's not a direct-mapped cache, look to the CVR 2141da177e4SLinus Torvalds * for I/D-cache specifics. 2151da177e4SLinus Torvalds */ 216cb7af21fSPaul Mundt if (boot_cpu_data.icache.ways > 1) { 2171da177e4SLinus Torvalds size = sizes[(cvr >> 20) & 0xf]; 218cb7af21fSPaul Mundt boot_cpu_data.icache.way_incr = (size >> 1); 219cb7af21fSPaul Mundt boot_cpu_data.icache.sets = (size >> 6); 220d15f4560SPaul Mundt 2211da177e4SLinus Torvalds } 2221da177e4SLinus Torvalds 223d15f4560SPaul Mundt /* And the rest of the D-cache */ 224cb7af21fSPaul Mundt if (boot_cpu_data.dcache.ways > 1) { 2251da177e4SLinus Torvalds size = sizes[(cvr >> 16) & 0xf]; 226cb7af21fSPaul Mundt boot_cpu_data.dcache.way_incr = (size >> 1); 227cb7af21fSPaul Mundt boot_cpu_data.dcache.sets = (size >> 6); 2281da177e4SLinus Torvalds } 2291da177e4SLinus Torvalds 23072c35543SPaul Mundt /* 23172c35543SPaul Mundt * SH-4A's have an optional PIPT L2. 23272c35543SPaul Mundt */ 233cb7af21fSPaul Mundt if (boot_cpu_data.flags & CPU_HAS_L2_CACHE) { 234*7863d3f7SPaul Mundt /* 235*7863d3f7SPaul Mundt * Verify that it really has something hooked up, this 236*7863d3f7SPaul Mundt * is the safety net for CPUs that have optional L2 237*7863d3f7SPaul Mundt * support yet do not implement it. 238*7863d3f7SPaul Mundt */ 239*7863d3f7SPaul Mundt if ((cvr & 0xf) == 0) 240*7863d3f7SPaul Mundt boot_cpu_data.flags &= ~CPU_HAS_L2_CACHE; 241*7863d3f7SPaul Mundt else { 242*7863d3f7SPaul Mundt /* 243*7863d3f7SPaul Mundt * Silicon and specifications have clearly never 244*7863d3f7SPaul Mundt * met.. 245*7863d3f7SPaul Mundt */ 246440fc172SPaul Mundt cvr ^= 0xf; 247440fc172SPaul Mundt 24872c35543SPaul Mundt /* 24972c35543SPaul Mundt * Size calculation is much more sensible 25072c35543SPaul Mundt * than it is for the L1. 25172c35543SPaul Mundt * 25272c35543SPaul Mundt * Sizes are 128KB, 258KB, 512KB, and 1MB. 25372c35543SPaul Mundt */ 25472c35543SPaul Mundt size = (cvr & 0xf) << 17; 25572c35543SPaul Mundt 256cb7af21fSPaul Mundt boot_cpu_data.scache.way_incr = (1 << 16); 257cb7af21fSPaul Mundt boot_cpu_data.scache.entry_shift = 5; 258cb7af21fSPaul Mundt boot_cpu_data.scache.ways = 4; 259cb7af21fSPaul Mundt boot_cpu_data.scache.linesz = L1_CACHE_BYTES; 26011c19656SPaul Mundt 261cb7af21fSPaul Mundt boot_cpu_data.scache.entry_mask = 262cb7af21fSPaul Mundt (boot_cpu_data.scache.way_incr - 263cb7af21fSPaul Mundt boot_cpu_data.scache.linesz); 26411c19656SPaul Mundt 265cb7af21fSPaul Mundt boot_cpu_data.scache.sets = size / 266cb7af21fSPaul Mundt (boot_cpu_data.scache.linesz * 267cb7af21fSPaul Mundt boot_cpu_data.scache.ways); 26811c19656SPaul Mundt 269cb7af21fSPaul Mundt boot_cpu_data.scache.way_size = 270cb7af21fSPaul Mundt (boot_cpu_data.scache.sets * 271cb7af21fSPaul Mundt boot_cpu_data.scache.linesz); 27272c35543SPaul Mundt } 273*7863d3f7SPaul Mundt } 27472c35543SPaul Mundt 2751da177e4SLinus Torvalds return 0; 2761da177e4SLinus Torvalds } 277