1*6ecc0a4dSKuninori Morimoto // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * arch/sh/kernel/cpu/sh4/probe.c 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * CPU Subtype Probing for SH-4. 61da177e4SLinus Torvalds * 726fad19dSPaul Mundt * Copyright (C) 2001 - 2007 Paul Mundt 81da177e4SLinus Torvalds * Copyright (C) 2003 Richard Curnow 91da177e4SLinus Torvalds */ 101da177e4SLinus Torvalds #include <linux/init.h> 1111c19656SPaul Mundt #include <linux/io.h> 121da177e4SLinus Torvalds #include <asm/processor.h> 131da177e4SLinus Torvalds #include <asm/cache.h> 141da177e4SLinus Torvalds 154603f53aSPaul Gortmaker void cpu_probe(void) 161da177e4SLinus Torvalds { 171da177e4SLinus Torvalds unsigned long pvr, prr, cvr; 181da177e4SLinus Torvalds unsigned long size; 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds static unsigned long sizes[16] = { 211da177e4SLinus Torvalds [1] = (1 << 12), 221da177e4SLinus Torvalds [2] = (1 << 13), 231da177e4SLinus Torvalds [4] = (1 << 14), 241da177e4SLinus Torvalds [8] = (1 << 15), 251da177e4SLinus Torvalds [9] = (1 << 16) 261da177e4SLinus Torvalds }; 271da177e4SLinus Torvalds 289d56dd3bSPaul Mundt pvr = (__raw_readl(CCN_PVR) >> 8) & 0xffffff; 299d56dd3bSPaul Mundt prr = (__raw_readl(CCN_PRR) >> 4) & 0xff; 309d56dd3bSPaul Mundt cvr = (__raw_readl(CCN_CVR)); 311da177e4SLinus Torvalds 321da177e4SLinus Torvalds /* 331da177e4SLinus Torvalds * Setup some sane SH-4 defaults for the icache 341da177e4SLinus Torvalds */ 35cb7af21fSPaul Mundt boot_cpu_data.icache.way_incr = (1 << 13); 36cb7af21fSPaul Mundt boot_cpu_data.icache.entry_shift = 5; 37cb7af21fSPaul Mundt boot_cpu_data.icache.sets = 256; 38cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 1; 39cb7af21fSPaul Mundt boot_cpu_data.icache.linesz = L1_CACHE_BYTES; 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds /* 421da177e4SLinus Torvalds * And again for the dcache .. 431da177e4SLinus Torvalds */ 44cb7af21fSPaul Mundt boot_cpu_data.dcache.way_incr = (1 << 14); 45cb7af21fSPaul Mundt boot_cpu_data.dcache.entry_shift = 5; 46cb7af21fSPaul Mundt boot_cpu_data.dcache.sets = 512; 47cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 1; 48cb7af21fSPaul Mundt boot_cpu_data.dcache.linesz = L1_CACHE_BYTES; 491da177e4SLinus Torvalds 50068f5914SPaul Mundt /* We don't know the chip cut */ 51068f5914SPaul Mundt boot_cpu_data.cut_major = boot_cpu_data.cut_minor = -1; 52068f5914SPaul Mundt 531da177e4SLinus Torvalds /* 5426fad19dSPaul Mundt * Setup some generic flags we can probe on SH-4A parts 5572c35543SPaul Mundt */ 56068f5914SPaul Mundt if (((pvr >> 16) & 0xff) == 0x10) { 57e82da214SPaul Mundt boot_cpu_data.family = CPU_FAMILY_SH4A; 58e82da214SPaul Mundt 59e82da214SPaul Mundt if ((cvr & 0x10000000) == 0) { 60cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_DSP; 61e82da214SPaul Mundt boot_cpu_data.family = CPU_FAMILY_SH4AL_DSP; 62e82da214SPaul Mundt } 6372c35543SPaul Mundt 640bf8513eSPaul Mundt boot_cpu_data.flags |= CPU_HAS_LLSC | CPU_HAS_PERF_COUNTER; 65068f5914SPaul Mundt boot_cpu_data.cut_major = pvr & 0x7f; 660bf8513eSPaul Mundt 670bf8513eSPaul Mundt boot_cpu_data.icache.ways = 4; 680bf8513eSPaul Mundt boot_cpu_data.dcache.ways = 4; 690bf8513eSPaul Mundt } else { 700bf8513eSPaul Mundt /* And some SH-4 defaults.. */ 71bdc27300SPaul Mundt boot_cpu_data.flags |= CPU_HAS_PTEA | CPU_HAS_FPU; 72e82da214SPaul Mundt boot_cpu_data.family = CPU_FAMILY_SH4; 7372c35543SPaul Mundt } 7472c35543SPaul Mundt 75bdc27300SPaul Mundt /* FPU detection works for almost everyone */ 760bf8513eSPaul Mundt if ((cvr & 0x20000000)) 77cb7af21fSPaul Mundt boot_cpu_data.flags |= CPU_HAS_FPU; 7872c35543SPaul Mundt 7972c35543SPaul Mundt /* Mask off the upper chip ID */ 8072c35543SPaul Mundt pvr &= 0xffff; 8172c35543SPaul Mundt 8272c35543SPaul Mundt /* 831da177e4SLinus Torvalds * Probe the underlying processor version/revision and 841da177e4SLinus Torvalds * adjust cpu_data setup accordingly. 851da177e4SLinus Torvalds */ 861da177e4SLinus Torvalds switch (pvr) { 871da177e4SLinus Torvalds case 0x205: 88cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7750; 890bf8513eSPaul Mundt boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | 909b3a53abSStuart Menefy CPU_HAS_PERF_COUNTER; 911da177e4SLinus Torvalds break; 921da177e4SLinus Torvalds case 0x206: 93cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7750S; 940bf8513eSPaul Mundt boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | 959b3a53abSStuart Menefy CPU_HAS_PERF_COUNTER; 961da177e4SLinus Torvalds break; 971da177e4SLinus Torvalds case 0x1100: 98cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7751; 991da177e4SLinus Torvalds break; 1005b19c908SPaul Mundt case 0x2001: 1015b19c908SPaul Mundt case 0x2004: 102cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7770; 1035b19c908SPaul Mundt break; 1045b19c908SPaul Mundt case 0x2006: 1055b19c908SPaul Mundt case 0x200A: 1065b19c908SPaul Mundt if (prr == 0x61) 107cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7781; 1087d740a06SYoshihiro Shimoda else if (prr == 0xa1) 1097d740a06SYoshihiro Shimoda boot_cpu_data.type = CPU_SH7763; 1105b19c908SPaul Mundt else 111cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7780; 112749cf486SPaul Mundt 1135b19c908SPaul Mundt break; 114e5723e0eSPaul Mundt case 0x3000: 115e5723e0eSPaul Mundt case 0x3003: 11641504c39SPaul Mundt case 0x3009: 117cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7343; 118e5723e0eSPaul Mundt break; 11932351a28SPaul Mundt case 0x3004: 12032351a28SPaul Mundt case 0x3007: 121cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7785; 12232351a28SPaul Mundt break; 12355ba99ebSKuninori Morimoto case 0x4004: 1247f33306eSMatt Fleming case 0x4005: 12555ba99ebSKuninori Morimoto boot_cpu_data.type = CPU_SH7786; 1260bf8513eSPaul Mundt boot_cpu_data.flags |= CPU_HAS_PTEAEX | CPU_HAS_L2_CACHE; 12755ba99ebSKuninori Morimoto break; 12841504c39SPaul Mundt case 0x3008: 129178dd0cdSPaul Mundt switch (prr) { 130178dd0cdSPaul Mundt case 0x50: 131b76baf4cSMagnus Damm case 0x51: 132178dd0cdSPaul Mundt boot_cpu_data.type = CPU_SH7723; 1330bf8513eSPaul Mundt boot_cpu_data.flags |= CPU_HAS_L2_CACHE; 134178dd0cdSPaul Mundt break; 135178dd0cdSPaul Mundt case 0x70: 1369109a30eSMagnus Damm boot_cpu_data.type = CPU_SH7366; 137178dd0cdSPaul Mundt break; 138178dd0cdSPaul Mundt case 0xa0: 139178dd0cdSPaul Mundt case 0xa1: 140178dd0cdSPaul Mundt boot_cpu_data.type = CPU_SH7722; 141178dd0cdSPaul Mundt break; 1429109a30eSMagnus Damm } 14341504c39SPaul Mundt break; 1440207a2efSKuninori Morimoto case 0x300b: 145c01f0f1aSYoshihiro Shimoda switch (prr) { 146c01f0f1aSYoshihiro Shimoda case 0x20: 1470207a2efSKuninori Morimoto boot_cpu_data.type = CPU_SH7724; 1480bf8513eSPaul Mundt boot_cpu_data.flags |= CPU_HAS_L2_CACHE; 1490207a2efSKuninori Morimoto break; 150e81e5ce2SYoshihiro Shimoda case 0x10: 151538e7906SYoshihiro Shimoda case 0x11: 152c01f0f1aSYoshihiro Shimoda boot_cpu_data.type = CPU_SH7757; 153c01f0f1aSYoshihiro Shimoda break; 154fac6c2a8SMagnus Damm case 0xd0: 155fac6c2a8SMagnus Damm case 0x40: /* yon-ten-go */ 156fac6c2a8SMagnus Damm boot_cpu_data.type = CPU_SH7372; 157fac6c2a8SMagnus Damm break; 158fea88a0cSNobuhiro Iwamatsu case 0xE0: /* 0x4E0 */ 159fea88a0cSNobuhiro Iwamatsu boot_cpu_data.type = CPU_SH7734; /* SH7733/SH7734 */ 160fea88a0cSNobuhiro Iwamatsu break; 161fac6c2a8SMagnus Damm 162c01f0f1aSYoshihiro Shimoda } 163c01f0f1aSYoshihiro Shimoda break; 1642b1bd1acSPaul Mundt case 0x4000: /* 1st cut */ 1652b1bd1acSPaul Mundt case 0x4001: /* 2nd cut */ 166cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SHX3; 1672b1bd1acSPaul Mundt break; 1681da177e4SLinus Torvalds case 0x700: 169cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH4_501; 170bdc27300SPaul Mundt boot_cpu_data.flags &= ~CPU_HAS_FPU; 171cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 2; 172cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 2; 1731da177e4SLinus Torvalds break; 1741da177e4SLinus Torvalds case 0x600: 175cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH4_202; 176cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 2; 177cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 2; 1781da177e4SLinus Torvalds break; 1791da177e4SLinus Torvalds case 0x500 ... 0x501: 1801da177e4SLinus Torvalds switch (prr) { 18173388cc7SPaul Mundt case 0x10: 182cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7750R; 18373388cc7SPaul Mundt break; 18473388cc7SPaul Mundt case 0x11: 185cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7751R; 18673388cc7SPaul Mundt break; 18773388cc7SPaul Mundt case 0x50 ... 0x5f: 188cb7af21fSPaul Mundt boot_cpu_data.type = CPU_SH7760; 18973388cc7SPaul Mundt break; 1901da177e4SLinus Torvalds } 1911da177e4SLinus Torvalds 192cb7af21fSPaul Mundt boot_cpu_data.icache.ways = 2; 193cb7af21fSPaul Mundt boot_cpu_data.dcache.ways = 2; 1941da177e4SLinus Torvalds 1951da177e4SLinus Torvalds break; 1961da177e4SLinus Torvalds } 1971da177e4SLinus Torvalds 1981da177e4SLinus Torvalds /* 1991da177e4SLinus Torvalds * On anything that's not a direct-mapped cache, look to the CVR 2001da177e4SLinus Torvalds * for I/D-cache specifics. 2011da177e4SLinus Torvalds */ 202cb7af21fSPaul Mundt if (boot_cpu_data.icache.ways > 1) { 2031da177e4SLinus Torvalds size = sizes[(cvr >> 20) & 0xf]; 204cb7af21fSPaul Mundt boot_cpu_data.icache.way_incr = (size >> 1); 205cb7af21fSPaul Mundt boot_cpu_data.icache.sets = (size >> 6); 206d15f4560SPaul Mundt 2071da177e4SLinus Torvalds } 2081da177e4SLinus Torvalds 209d15f4560SPaul Mundt /* And the rest of the D-cache */ 210cb7af21fSPaul Mundt if (boot_cpu_data.dcache.ways > 1) { 2111da177e4SLinus Torvalds size = sizes[(cvr >> 16) & 0xf]; 212cb7af21fSPaul Mundt boot_cpu_data.dcache.way_incr = (size >> 1); 213cb7af21fSPaul Mundt boot_cpu_data.dcache.sets = (size >> 6); 2141da177e4SLinus Torvalds } 2151da177e4SLinus Torvalds 21672c35543SPaul Mundt /* 21772c35543SPaul Mundt * SH-4A's have an optional PIPT L2. 21872c35543SPaul Mundt */ 219cb7af21fSPaul Mundt if (boot_cpu_data.flags & CPU_HAS_L2_CACHE) { 2207863d3f7SPaul Mundt /* 2217863d3f7SPaul Mundt * Verify that it really has something hooked up, this 2227863d3f7SPaul Mundt * is the safety net for CPUs that have optional L2 2237863d3f7SPaul Mundt * support yet do not implement it. 2247863d3f7SPaul Mundt */ 2257863d3f7SPaul Mundt if ((cvr & 0xf) == 0) 2267863d3f7SPaul Mundt boot_cpu_data.flags &= ~CPU_HAS_L2_CACHE; 2277863d3f7SPaul Mundt else { 2287863d3f7SPaul Mundt /* 2297863d3f7SPaul Mundt * Silicon and specifications have clearly never 2307863d3f7SPaul Mundt * met.. 2317863d3f7SPaul Mundt */ 232440fc172SPaul Mundt cvr ^= 0xf; 233440fc172SPaul Mundt 23472c35543SPaul Mundt /* 23572c35543SPaul Mundt * Size calculation is much more sensible 23672c35543SPaul Mundt * than it is for the L1. 23772c35543SPaul Mundt * 23888f73d22SPaul Mundt * Sizes are 128KB, 256KB, 512KB, and 1MB. 23972c35543SPaul Mundt */ 24072c35543SPaul Mundt size = (cvr & 0xf) << 17; 24172c35543SPaul Mundt 242cb7af21fSPaul Mundt boot_cpu_data.scache.way_incr = (1 << 16); 243cb7af21fSPaul Mundt boot_cpu_data.scache.entry_shift = 5; 244cb7af21fSPaul Mundt boot_cpu_data.scache.ways = 4; 245cb7af21fSPaul Mundt boot_cpu_data.scache.linesz = L1_CACHE_BYTES; 24611c19656SPaul Mundt 247cb7af21fSPaul Mundt boot_cpu_data.scache.entry_mask = 248cb7af21fSPaul Mundt (boot_cpu_data.scache.way_incr - 249cb7af21fSPaul Mundt boot_cpu_data.scache.linesz); 25011c19656SPaul Mundt 251cb7af21fSPaul Mundt boot_cpu_data.scache.sets = size / 252cb7af21fSPaul Mundt (boot_cpu_data.scache.linesz * 253cb7af21fSPaul Mundt boot_cpu_data.scache.ways); 25411c19656SPaul Mundt 255cb7af21fSPaul Mundt boot_cpu_data.scache.way_size = 256cb7af21fSPaul Mundt (boot_cpu_data.scache.sets * 257cb7af21fSPaul Mundt boot_cpu_data.scache.linesz); 25872c35543SPaul Mundt } 2597863d3f7SPaul Mundt } 2601da177e4SLinus Torvalds } 261