cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bcu.c (4815B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  bcu.c, Bus Control Unit routines for the NEC VR4100 series.
      4 *
      5 *  Copyright (C) 2002	MontaVista Software Inc.
      6 *    Author: Yoichi Yuasa <source@mvista.com>
      7 *  Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@linux-mips.org>
      8 */
      9/*
     10 * Changes:
     11 *  MontaVista Software Inc. <source@mvista.com>
     12 *  - New creation, NEC VR4122 and VR4131 are supported.
     13 *  - Added support for NEC VR4111 and VR4121.
     14 *
     15 *  Yoichi Yuasa <yuasa@linux-mips.org>
     16 *  - Added support for NEC VR4133.
     17 */
     18#include <linux/export.h>
     19#include <linux/kernel.h>
     20#include <linux/smp.h>
     21#include <linux/types.h>
     22
     23#include <asm/cpu-type.h>
     24#include <asm/cpu.h>
     25#include <asm/io.h>
     26
     27#define CLKSPEEDREG_TYPE1	(void __iomem *)KSEG1ADDR(0x0b000014)
     28#define CLKSPEEDREG_TYPE2	(void __iomem *)KSEG1ADDR(0x0f000014)
     29 #define CLKSP(x)		((x) & 0x001f)
     30 #define CLKSP_VR4133(x)	((x) & 0x0007)
     31
     32 #define DIV2B			0x8000
     33 #define DIV3B			0x4000
     34 #define DIV4B			0x2000
     35
     36 #define DIVT(x)		(((x) & 0xf000) >> 12)
     37 #define DIVVT(x)		(((x) & 0x0f00) >> 8)
     38
     39 #define TDIVMODE(x)		(2 << (((x) & 0x1000) >> 12))
     40 #define VTDIVMODE(x)		(((x) & 0x0700) >> 8)
     41
     42static unsigned long vr41xx_vtclock;
     43static unsigned long vr41xx_tclock;
     44
     45unsigned long vr41xx_get_vtclock_frequency(void)
     46{
     47	return vr41xx_vtclock;
     48}
     49
     50EXPORT_SYMBOL_GPL(vr41xx_get_vtclock_frequency);
     51
     52unsigned long vr41xx_get_tclock_frequency(void)
     53{
     54	return vr41xx_tclock;
     55}
     56
     57EXPORT_SYMBOL_GPL(vr41xx_get_tclock_frequency);
     58
     59static inline uint16_t read_clkspeed(void)
     60{
     61	switch (current_cpu_type()) {
     62	case CPU_VR4111:
     63	case CPU_VR4121: return readw(CLKSPEEDREG_TYPE1);
     64	case CPU_VR4122:
     65	case CPU_VR4131:
     66	case CPU_VR4133: return readw(CLKSPEEDREG_TYPE2);
     67	default:
     68		printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
     69		break;
     70	}
     71
     72	return 0;
     73}
     74
     75static inline unsigned long calculate_pclock(uint16_t clkspeed)
     76{
     77	unsigned long pclock = 0;
     78
     79	switch (current_cpu_type()) {
     80	case CPU_VR4111:
     81	case CPU_VR4121:
     82		pclock = 18432000 * 64;
     83		pclock /= CLKSP(clkspeed);
     84		break;
     85	case CPU_VR4122:
     86		pclock = 18432000 * 98;
     87		pclock /= CLKSP(clkspeed);
     88		break;
     89	case CPU_VR4131:
     90		pclock = 18432000 * 108;
     91		pclock /= CLKSP(clkspeed);
     92		break;
     93	case CPU_VR4133:
     94		switch (CLKSP_VR4133(clkspeed)) {
     95		case 0:
     96			pclock = 133000000;
     97			break;
     98		case 1:
     99			pclock = 149000000;
    100			break;
    101		case 2:
    102			pclock = 165900000;
    103			break;
    104		case 3:
    105			pclock = 199100000;
    106			break;
    107		case 4:
    108			pclock = 265900000;
    109			break;
    110		default:
    111			printk(KERN_INFO "Unknown PClock speed for NEC VR4133\n");
    112			break;
    113		}
    114		break;
    115	default:
    116		printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
    117		break;
    118	}
    119
    120	printk(KERN_INFO "PClock: %ldHz\n", pclock);
    121
    122	return pclock;
    123}
    124
    125static inline unsigned long calculate_vtclock(uint16_t clkspeed, unsigned long pclock)
    126{
    127	unsigned long vtclock = 0;
    128
    129	switch (current_cpu_type()) {
    130	case CPU_VR4111:
    131		/* The NEC VR4111 doesn't have the VTClock. */
    132		break;
    133	case CPU_VR4121:
    134		vtclock = pclock;
    135		/* DIVVT == 9 Divide by 1.5 . VTClock = (PClock * 6) / 9 */
    136		if (DIVVT(clkspeed) == 9)
    137			vtclock = pclock * 6;
    138		/* DIVVT == 10 Divide by 2.5 . VTClock = (PClock * 4) / 10 */
    139		else if (DIVVT(clkspeed) == 10)
    140			vtclock = pclock * 4;
    141		vtclock /= DIVVT(clkspeed);
    142		printk(KERN_INFO "VTClock: %ldHz\n", vtclock);
    143		break;
    144	case CPU_VR4122:
    145		if(VTDIVMODE(clkspeed) == 7)
    146			vtclock = pclock / 1;
    147		else if(VTDIVMODE(clkspeed) == 1)
    148			vtclock = pclock / 2;
    149		else
    150			vtclock = pclock / VTDIVMODE(clkspeed);
    151		printk(KERN_INFO "VTClock: %ldHz\n", vtclock);
    152		break;
    153	case CPU_VR4131:
    154	case CPU_VR4133:
    155		vtclock = pclock / VTDIVMODE(clkspeed);
    156		printk(KERN_INFO "VTClock: %ldHz\n", vtclock);
    157		break;
    158	default:
    159		printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
    160		break;
    161	}
    162
    163	return vtclock;
    164}
    165
    166static inline unsigned long calculate_tclock(uint16_t clkspeed, unsigned long pclock,
    167					     unsigned long vtclock)
    168{
    169	unsigned long tclock = 0;
    170
    171	switch (current_cpu_type()) {
    172	case CPU_VR4111:
    173		if (!(clkspeed & DIV2B))
    174			tclock = pclock / 2;
    175		else if (!(clkspeed & DIV3B))
    176			tclock = pclock / 3;
    177		else if (!(clkspeed & DIV4B))
    178			tclock = pclock / 4;
    179		break;
    180	case CPU_VR4121:
    181		tclock = pclock / DIVT(clkspeed);
    182		break;
    183	case CPU_VR4122:
    184	case CPU_VR4131:
    185	case CPU_VR4133:
    186		tclock = vtclock / TDIVMODE(clkspeed);
    187		break;
    188	default:
    189		printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n");
    190		break;
    191	}
    192
    193	printk(KERN_INFO "TClock: %ldHz\n", tclock);
    194
    195	return tclock;
    196}
    197
    198void vr41xx_calculate_clock_frequency(void)
    199{
    200	unsigned long pclock;
    201	uint16_t clkspeed;
    202
    203	clkspeed = read_clkspeed();
    204
    205	pclock = calculate_pclock(clkspeed);
    206	vr41xx_vtclock = calculate_vtclock(clkspeed, pclock);
    207	vr41xx_tclock = calculate_tclock(clkspeed, pclock, vr41xx_vtclock);
    208}
    209
    210EXPORT_SYMBOL_GPL(vr41xx_calculate_clock_frequency);