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

cr_pll.c (4130B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (c) Intel Corp. 2007.
      4 * All Rights Reserved.
      5 *
      6 * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
      7 * develop this driver.
      8 *
      9 * This file is part of the Carillo Ranch video subsystem driver.
     10 *
     11 * Authors:
     12 *   Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
     13 *   Alan Hourihane <alanh-at-tungstengraphics-dot-com>
     14 */
     15
     16#include <linux/module.h>
     17#include <linux/kernel.h>
     18#include <linux/pci.h>
     19#include <linux/errno.h>
     20#include <linux/fb.h>
     21#include "vermilion.h"
     22
     23/* The PLL Clock register sits on Host bridge */
     24#define CRVML_DEVICE_MCH   0x5001
     25#define CRVML_REG_MCHBAR   0x44
     26#define CRVML_REG_MCHEN    0x54
     27#define CRVML_MCHEN_BIT    (1 << 28)
     28#define CRVML_MCHMAP_SIZE  4096
     29#define CRVML_REG_CLOCK    0xc3c
     30#define CRVML_CLOCK_SHIFT  8
     31#define CRVML_CLOCK_MASK   0x00000f00
     32
     33static struct pci_dev *mch_dev;
     34static u32 mch_bar;
     35static void __iomem *mch_regs_base;
     36static u32 saved_clock;
     37
     38static const unsigned crvml_clocks[] = {
     39	6750,
     40	13500,
     41	27000,
     42	29700,
     43	37125,
     44	54000,
     45	59400,
     46	74250,
     47	120000
     48	    /*
     49	     * There are more clocks, but they are disabled on the CR board.
     50	     */
     51};
     52
     53static const u32 crvml_clock_bits[] = {
     54	0x0a,
     55	0x09,
     56	0x08,
     57	0x07,
     58	0x06,
     59	0x05,
     60	0x04,
     61	0x03,
     62	0x0b
     63};
     64
     65static const unsigned crvml_num_clocks = ARRAY_SIZE(crvml_clocks);
     66
     67static int crvml_sys_restore(struct vml_sys *sys)
     68{
     69	void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
     70
     71	iowrite32(saved_clock, clock_reg);
     72	ioread32(clock_reg);
     73
     74	return 0;
     75}
     76
     77static int crvml_sys_save(struct vml_sys *sys)
     78{
     79	void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
     80
     81	saved_clock = ioread32(clock_reg);
     82
     83	return 0;
     84}
     85
     86static int crvml_nearest_index(const struct vml_sys *sys, int clock)
     87{
     88	int i;
     89	int cur_index = 0;
     90	int cur_diff;
     91	int diff;
     92
     93	cur_diff = clock - crvml_clocks[0];
     94	cur_diff = (cur_diff < 0) ? -cur_diff : cur_diff;
     95	for (i = 1; i < crvml_num_clocks; ++i) {
     96		diff = clock - crvml_clocks[i];
     97		diff = (diff < 0) ? -diff : diff;
     98		if (diff < cur_diff) {
     99			cur_index = i;
    100			cur_diff = diff;
    101		}
    102	}
    103	return cur_index;
    104}
    105
    106static int crvml_nearest_clock(const struct vml_sys *sys, int clock)
    107{
    108	return crvml_clocks[crvml_nearest_index(sys, clock)];
    109}
    110
    111static int crvml_set_clock(struct vml_sys *sys, int clock)
    112{
    113	void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
    114	int index;
    115	u32 clock_val;
    116
    117	index = crvml_nearest_index(sys, clock);
    118
    119	if (crvml_clocks[index] != clock)
    120		return -EINVAL;
    121
    122	clock_val = ioread32(clock_reg) & ~CRVML_CLOCK_MASK;
    123	clock_val = crvml_clock_bits[index] << CRVML_CLOCK_SHIFT;
    124	iowrite32(clock_val, clock_reg);
    125	ioread32(clock_reg);
    126
    127	return 0;
    128}
    129
    130static struct vml_sys cr_pll_ops = {
    131	.name = "Carillo Ranch",
    132	.save = crvml_sys_save,
    133	.restore = crvml_sys_restore,
    134	.set_clock = crvml_set_clock,
    135	.nearest_clock = crvml_nearest_clock,
    136};
    137
    138static int __init cr_pll_init(void)
    139{
    140	int err;
    141	u32 dev_en;
    142
    143	mch_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
    144					CRVML_DEVICE_MCH, NULL);
    145	if (!mch_dev) {
    146		printk(KERN_ERR
    147		       "Could not find Carillo Ranch MCH device.\n");
    148		return -ENODEV;
    149	}
    150
    151	pci_read_config_dword(mch_dev, CRVML_REG_MCHEN, &dev_en);
    152	if (!(dev_en & CRVML_MCHEN_BIT)) {
    153		printk(KERN_ERR
    154		       "Carillo Ranch MCH device was not enabled.\n");
    155		pci_dev_put(mch_dev);
    156		return -ENODEV;
    157	}
    158
    159	pci_read_config_dword(mch_dev, CRVML_REG_MCHBAR,
    160			      &mch_bar);
    161	mch_regs_base =
    162	    ioremap(mch_bar, CRVML_MCHMAP_SIZE);
    163	if (!mch_regs_base) {
    164		printk(KERN_ERR
    165		       "Carillo Ranch MCH device was not enabled.\n");
    166		pci_dev_put(mch_dev);
    167		return -ENODEV;
    168	}
    169
    170	err = vmlfb_register_subsys(&cr_pll_ops);
    171	if (err) {
    172		printk(KERN_ERR
    173		       "Carillo Ranch failed to initialize vml_sys.\n");
    174		iounmap(mch_regs_base);
    175		pci_dev_put(mch_dev);
    176		return err;
    177	}
    178
    179	return 0;
    180}
    181
    182static void __exit cr_pll_exit(void)
    183{
    184	vmlfb_unregister_subsys(&cr_pll_ops);
    185
    186	iounmap(mch_regs_base);
    187	pci_dev_put(mch_dev);
    188}
    189
    190module_init(cr_pll_init);
    191module_exit(cr_pll_exit);
    192
    193MODULE_AUTHOR("Tungsten Graphics Inc.");
    194MODULE_DESCRIPTION("Carillo Ranch PLL Driver");
    195MODULE_LICENSE("GPL");