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

ops-msc.c (3331B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 1999, 2000, 2004, 2005	 MIPS Technologies, Inc.
      4 *    All rights reserved.
      5 *    Authors: Carsten Langgaard <carstenl@mips.com>
      6 *	       Maciej W. Rozycki <macro@mips.com>
      7 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
      8 *
      9 * MIPS boards specific PCI support.
     10 */
     11#include <linux/types.h>
     12#include <linux/pci.h>
     13#include <linux/kernel.h>
     14
     15#include <asm/mips-boards/msc01_pci.h>
     16
     17#define PCI_ACCESS_READ	 0
     18#define PCI_ACCESS_WRITE 1
     19
     20/*
     21 *  PCI configuration cycle AD bus definition
     22 */
     23/* Type 0 */
     24#define PCI_CFG_TYPE0_REG_SHF		0
     25#define PCI_CFG_TYPE0_FUNC_SHF		8
     26
     27/* Type 1 */
     28#define PCI_CFG_TYPE1_REG_SHF		0
     29#define PCI_CFG_TYPE1_FUNC_SHF		8
     30#define PCI_CFG_TYPE1_DEV_SHF		11
     31#define PCI_CFG_TYPE1_BUS_SHF		16
     32
     33static int msc_pcibios_config_access(unsigned char access_type,
     34	struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
     35{
     36	unsigned char busnum = bus->number;
     37	u32 intr;
     38
     39	/* Clear status register bits. */
     40	MSC_WRITE(MSC01_PCI_INTSTAT,
     41		  (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT));
     42
     43	MSC_WRITE(MSC01_PCI_CFGADDR,
     44		  ((busnum << MSC01_PCI_CFGADDR_BNUM_SHF) |
     45		   (PCI_SLOT(devfn) << MSC01_PCI_CFGADDR_DNUM_SHF) |
     46		   (PCI_FUNC(devfn) << MSC01_PCI_CFGADDR_FNUM_SHF) |
     47		   ((where / 4) << MSC01_PCI_CFGADDR_RNUM_SHF)));
     48
     49	/* Perform access */
     50	if (access_type == PCI_ACCESS_WRITE)
     51		MSC_WRITE(MSC01_PCI_CFGDATA, *data);
     52	else
     53		MSC_READ(MSC01_PCI_CFGDATA, *data);
     54
     55	/* Detect Master/Target abort */
     56	MSC_READ(MSC01_PCI_INTSTAT, intr);
     57	if (intr & (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT)) {
     58		/* Error occurred */
     59
     60		/* Clear bits */
     61		MSC_WRITE(MSC01_PCI_INTSTAT,
     62			  (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT));
     63
     64		return -1;
     65	}
     66
     67	return 0;
     68}
     69
     70
     71/*
     72 * We can't address 8 and 16 bit words directly.  Instead we have to
     73 * read/write a 32bit word and mask/modify the data we actually want.
     74 */
     75static int msc_pcibios_read(struct pci_bus *bus, unsigned int devfn,
     76			     int where, int size, u32 * val)
     77{
     78	u32 data = 0;
     79
     80	if ((size == 2) && (where & 1))
     81		return PCIBIOS_BAD_REGISTER_NUMBER;
     82	else if ((size == 4) && (where & 3))
     83		return PCIBIOS_BAD_REGISTER_NUMBER;
     84
     85	if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
     86				      &data))
     87		return -1;
     88
     89	if (size == 1)
     90		*val = (data >> ((where & 3) << 3)) & 0xff;
     91	else if (size == 2)
     92		*val = (data >> ((where & 3) << 3)) & 0xffff;
     93	else
     94		*val = data;
     95
     96	return PCIBIOS_SUCCESSFUL;
     97}
     98
     99static int msc_pcibios_write(struct pci_bus *bus, unsigned int devfn,
    100			      int where, int size, u32 val)
    101{
    102	u32 data = 0;
    103
    104	if ((size == 2) && (where & 1))
    105		return PCIBIOS_BAD_REGISTER_NUMBER;
    106	else if ((size == 4) && (where & 3))
    107		return PCIBIOS_BAD_REGISTER_NUMBER;
    108
    109	if (size == 4)
    110		data = val;
    111	else {
    112		if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
    113					      where, &data))
    114			return -1;
    115
    116		if (size == 1)
    117			data = (data & ~(0xff << ((where & 3) << 3))) |
    118				(val << ((where & 3) << 3));
    119		else if (size == 2)
    120			data = (data & ~(0xffff << ((where & 3) << 3))) |
    121				(val << ((where & 3) << 3));
    122	}
    123
    124	if (msc_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
    125				       &data))
    126		return -1;
    127
    128	return PCIBIOS_SUCCESSFUL;
    129}
    130
    131struct pci_ops msc_pci_ops = {
    132	.read = msc_pcibios_read,
    133	.write = msc_pcibios_write
    134};