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-sh4.c (2385B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Generic SH-4 / SH-4A PCIC operations (SH7751, SH7780).
      4 *
      5 * Copyright (C) 2002 - 2009  Paul Mundt
      6 */
      7#include <linux/pci.h>
      8#include <linux/io.h>
      9#include <linux/spinlock.h>
     10#include <asm/addrspace.h>
     11#include "pci-sh4.h"
     12
     13/*
     14 * Direct access to PCI hardware...
     15 */
     16#define CONFIG_CMD(bus, devfn, where) \
     17	(0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
     18
     19/*
     20 * Functions for accessing PCI configuration space with type 1 accesses
     21 */
     22static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
     23			   int where, int size, u32 *val)
     24{
     25	struct pci_channel *chan = bus->sysdata;
     26	unsigned long flags;
     27	u32 data;
     28
     29	/*
     30	 * PCIPDR may only be accessed as 32 bit words,
     31	 * so we must do byte alignment by hand
     32	 */
     33	raw_spin_lock_irqsave(&pci_config_lock, flags);
     34	pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
     35	data = pci_read_reg(chan, SH4_PCIPDR);
     36	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
     37
     38	switch (size) {
     39	case 1:
     40		*val = (data >> ((where & 3) << 3)) & 0xff;
     41		break;
     42	case 2:
     43		*val = (data >> ((where & 2) << 3)) & 0xffff;
     44		break;
     45	case 4:
     46		*val = data;
     47		break;
     48	default:
     49		return PCIBIOS_FUNC_NOT_SUPPORTED;
     50	}
     51
     52	return PCIBIOS_SUCCESSFUL;
     53}
     54
     55/*
     56 * Since SH4 only does 32bit access we'll have to do a read,
     57 * mask,write operation.
     58 * We'll allow an odd byte offset, though it should be illegal.
     59 */
     60static int sh4_pci_write(struct pci_bus *bus, unsigned int devfn,
     61			 int where, int size, u32 val)
     62{
     63	struct pci_channel *chan = bus->sysdata;
     64	unsigned long flags;
     65	int shift;
     66	u32 data;
     67
     68	raw_spin_lock_irqsave(&pci_config_lock, flags);
     69	pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
     70	data = pci_read_reg(chan, SH4_PCIPDR);
     71	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
     72
     73	switch (size) {
     74	case 1:
     75		shift = (where & 3) << 3;
     76		data &= ~(0xff << shift);
     77		data |= ((val & 0xff) << shift);
     78		break;
     79	case 2:
     80		shift = (where & 2) << 3;
     81		data &= ~(0xffff << shift);
     82		data |= ((val & 0xffff) << shift);
     83		break;
     84	case 4:
     85		data = val;
     86		break;
     87	default:
     88		return PCIBIOS_FUNC_NOT_SUPPORTED;
     89	}
     90
     91	pci_write_reg(chan, data, SH4_PCIPDR);
     92
     93	return PCIBIOS_SUCCESSFUL;
     94}
     95
     96struct pci_ops sh4_pci_ops = {
     97	.read		= sh4_pci_read,
     98	.write		= sh4_pci_write,
     99};
    100
    101int __attribute__((weak)) pci_fixup_pcic(struct pci_channel *chan)
    102{
    103	/* Nothing to do. */
    104	return 0;
    105}