1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * arch/sh/kernel/cpu/sh4/probe.c 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * CPU Subtype Probing for SH-4. 5*1da177e4SLinus Torvalds * 6*1da177e4SLinus Torvalds * Copyright (C) 2001, 2002, 2003, 2004 Paul Mundt 7*1da177e4SLinus Torvalds * Copyright (C) 2003 Richard Curnow 8*1da177e4SLinus Torvalds * 9*1da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 10*1da177e4SLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 11*1da177e4SLinus Torvalds * for more details. 12*1da177e4SLinus Torvalds */ 13*1da177e4SLinus Torvalds 14*1da177e4SLinus Torvalds #include <linux/init.h> 15*1da177e4SLinus Torvalds #include <asm/processor.h> 16*1da177e4SLinus Torvalds #include <asm/cache.h> 17*1da177e4SLinus Torvalds #include <asm/io.h> 18*1da177e4SLinus Torvalds 19*1da177e4SLinus Torvalds int __init detect_cpu_and_cache_system(void) 20*1da177e4SLinus Torvalds { 21*1da177e4SLinus Torvalds unsigned long pvr, prr, cvr; 22*1da177e4SLinus Torvalds unsigned long size; 23*1da177e4SLinus Torvalds 24*1da177e4SLinus Torvalds static unsigned long sizes[16] = { 25*1da177e4SLinus Torvalds [1] = (1 << 12), 26*1da177e4SLinus Torvalds [2] = (1 << 13), 27*1da177e4SLinus Torvalds [4] = (1 << 14), 28*1da177e4SLinus Torvalds [8] = (1 << 15), 29*1da177e4SLinus Torvalds [9] = (1 << 16) 30*1da177e4SLinus Torvalds }; 31*1da177e4SLinus Torvalds 32*1da177e4SLinus Torvalds pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffff; 33*1da177e4SLinus Torvalds prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff; 34*1da177e4SLinus Torvalds cvr = (ctrl_inl(CCN_CVR)); 35*1da177e4SLinus Torvalds 36*1da177e4SLinus Torvalds /* 37*1da177e4SLinus Torvalds * Setup some sane SH-4 defaults for the icache 38*1da177e4SLinus Torvalds */ 39*1da177e4SLinus Torvalds cpu_data->icache.way_incr = (1 << 13); 40*1da177e4SLinus Torvalds cpu_data->icache.entry_shift = 5; 41*1da177e4SLinus Torvalds cpu_data->icache.entry_mask = 0x1fe0; 42*1da177e4SLinus Torvalds cpu_data->icache.sets = 256; 43*1da177e4SLinus Torvalds cpu_data->icache.ways = 1; 44*1da177e4SLinus Torvalds cpu_data->icache.linesz = L1_CACHE_BYTES; 45*1da177e4SLinus Torvalds 46*1da177e4SLinus Torvalds /* 47*1da177e4SLinus Torvalds * And again for the dcache .. 48*1da177e4SLinus Torvalds */ 49*1da177e4SLinus Torvalds cpu_data->dcache.way_incr = (1 << 14); 50*1da177e4SLinus Torvalds cpu_data->dcache.entry_shift = 5; 51*1da177e4SLinus Torvalds cpu_data->dcache.entry_mask = 0x3fe0; 52*1da177e4SLinus Torvalds cpu_data->dcache.sets = 512; 53*1da177e4SLinus Torvalds cpu_data->dcache.ways = 1; 54*1da177e4SLinus Torvalds cpu_data->dcache.linesz = L1_CACHE_BYTES; 55*1da177e4SLinus Torvalds 56*1da177e4SLinus Torvalds /* Set the FPU flag, virtually all SH-4's have one */ 57*1da177e4SLinus Torvalds cpu_data->flags |= CPU_HAS_FPU; 58*1da177e4SLinus Torvalds 59*1da177e4SLinus Torvalds /* 60*1da177e4SLinus Torvalds * Probe the underlying processor version/revision and 61*1da177e4SLinus Torvalds * adjust cpu_data setup accordingly. 62*1da177e4SLinus Torvalds */ 63*1da177e4SLinus Torvalds switch (pvr) { 64*1da177e4SLinus Torvalds case 0x205: 65*1da177e4SLinus Torvalds cpu_data->type = CPU_SH7750; 66*1da177e4SLinus Torvalds cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_PERF_COUNTER; 67*1da177e4SLinus Torvalds break; 68*1da177e4SLinus Torvalds case 0x206: 69*1da177e4SLinus Torvalds cpu_data->type = CPU_SH7750S; 70*1da177e4SLinus Torvalds cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_PERF_COUNTER; 71*1da177e4SLinus Torvalds break; 72*1da177e4SLinus Torvalds case 0x1100: 73*1da177e4SLinus Torvalds cpu_data->type = CPU_SH7751; 74*1da177e4SLinus Torvalds break; 75*1da177e4SLinus Torvalds case 0x2000: 76*1da177e4SLinus Torvalds cpu_data->type = CPU_SH73180; 77*1da177e4SLinus Torvalds cpu_data->icache.ways = 4; 78*1da177e4SLinus Torvalds cpu_data->dcache.ways = 4; 79*1da177e4SLinus Torvalds cpu_data->flags &= ~CPU_HAS_FPU; 80*1da177e4SLinus Torvalds break; 81*1da177e4SLinus Torvalds case 0x8000: 82*1da177e4SLinus Torvalds cpu_data->type = CPU_ST40RA; 83*1da177e4SLinus Torvalds break; 84*1da177e4SLinus Torvalds case 0x8100: 85*1da177e4SLinus Torvalds cpu_data->type = CPU_ST40GX1; 86*1da177e4SLinus Torvalds break; 87*1da177e4SLinus Torvalds case 0x700: 88*1da177e4SLinus Torvalds cpu_data->type = CPU_SH4_501; 89*1da177e4SLinus Torvalds cpu_data->icache.ways = 2; 90*1da177e4SLinus Torvalds cpu_data->dcache.ways = 2; 91*1da177e4SLinus Torvalds 92*1da177e4SLinus Torvalds /* No FPU on the SH4-500 series.. */ 93*1da177e4SLinus Torvalds cpu_data->flags &= ~CPU_HAS_FPU; 94*1da177e4SLinus Torvalds break; 95*1da177e4SLinus Torvalds case 0x600: 96*1da177e4SLinus Torvalds cpu_data->type = CPU_SH4_202; 97*1da177e4SLinus Torvalds cpu_data->icache.ways = 2; 98*1da177e4SLinus Torvalds cpu_data->dcache.ways = 2; 99*1da177e4SLinus Torvalds break; 100*1da177e4SLinus Torvalds case 0x500 ... 0x501: 101*1da177e4SLinus Torvalds switch (prr) { 102*1da177e4SLinus Torvalds case 0x10: cpu_data->type = CPU_SH7750R; break; 103*1da177e4SLinus Torvalds case 0x11: cpu_data->type = CPU_SH7751R; break; 104*1da177e4SLinus Torvalds case 0x50: cpu_data->type = CPU_SH7760; break; 105*1da177e4SLinus Torvalds } 106*1da177e4SLinus Torvalds 107*1da177e4SLinus Torvalds cpu_data->icache.ways = 2; 108*1da177e4SLinus Torvalds cpu_data->dcache.ways = 2; 109*1da177e4SLinus Torvalds 110*1da177e4SLinus Torvalds break; 111*1da177e4SLinus Torvalds default: 112*1da177e4SLinus Torvalds cpu_data->type = CPU_SH_NONE; 113*1da177e4SLinus Torvalds break; 114*1da177e4SLinus Torvalds } 115*1da177e4SLinus Torvalds 116*1da177e4SLinus Torvalds /* 117*1da177e4SLinus Torvalds * On anything that's not a direct-mapped cache, look to the CVR 118*1da177e4SLinus Torvalds * for I/D-cache specifics. 119*1da177e4SLinus Torvalds */ 120*1da177e4SLinus Torvalds if (cpu_data->icache.ways > 1) { 121*1da177e4SLinus Torvalds size = sizes[(cvr >> 20) & 0xf]; 122*1da177e4SLinus Torvalds cpu_data->icache.way_incr = (size >> 1); 123*1da177e4SLinus Torvalds cpu_data->icache.sets = (size >> 6); 124*1da177e4SLinus Torvalds cpu_data->icache.entry_mask = 125*1da177e4SLinus Torvalds (cpu_data->icache.way_incr - (1 << 5)); 126*1da177e4SLinus Torvalds } 127*1da177e4SLinus Torvalds 128*1da177e4SLinus Torvalds if (cpu_data->dcache.ways > 1) { 129*1da177e4SLinus Torvalds size = sizes[(cvr >> 16) & 0xf]; 130*1da177e4SLinus Torvalds cpu_data->dcache.way_incr = (size >> 1); 131*1da177e4SLinus Torvalds cpu_data->dcache.sets = (size >> 6); 132*1da177e4SLinus Torvalds cpu_data->dcache.entry_mask = 133*1da177e4SLinus Torvalds (cpu_data->dcache.way_incr - (1 << 5)); 134*1da177e4SLinus Torvalds } 135*1da177e4SLinus Torvalds 136*1da177e4SLinus Torvalds return 0; 137*1da177e4SLinus Torvalds } 138*1da177e4SLinus Torvalds 139