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

pcie.c (6906B)


      1/*
      2 * arch/arm/mach-mv78xx0/pcie.c
      3 *
      4 * PCIe functions for Marvell MV78xx0 SoCs
      5 *
      6 * This file is licensed under the terms of the GNU General Public
      7 * License version 2.  This program is licensed "as is" without any
      8 * warranty of any kind, whether express or implied.
      9 */
     10
     11#include <linux/kernel.h>
     12#include <linux/pci.h>
     13#include <linux/mbus.h>
     14#include <video/vga.h>
     15#include <asm/irq.h>
     16#include <asm/mach/pci.h>
     17#include <plat/pcie.h>
     18#include "mv78xx0.h"
     19#include "common.h"
     20
     21#define MV78XX0_MBUS_PCIE_MEM_TARGET(port, lane) ((port) ? 8 : 4)
     22#define MV78XX0_MBUS_PCIE_MEM_ATTR(port, lane)   (0xf8 & ~(0x10 << (lane)))
     23#define MV78XX0_MBUS_PCIE_IO_TARGET(port, lane)  ((port) ? 8 : 4)
     24#define MV78XX0_MBUS_PCIE_IO_ATTR(port, lane)    (0xf0 & ~(0x10 << (lane)))
     25
     26struct pcie_port {
     27	u8			maj;
     28	u8			min;
     29	u8			root_bus_nr;
     30	void __iomem		*base;
     31	spinlock_t		conf_lock;
     32	char			mem_space_name[20];
     33	struct resource		res;
     34};
     35
     36static struct pcie_port pcie_port[8];
     37static int num_pcie_ports;
     38static struct resource pcie_io_space;
     39
     40void __init mv78xx0_pcie_id(u32 *dev, u32 *rev)
     41{
     42	*dev = orion_pcie_dev_id(PCIE00_VIRT_BASE);
     43	*rev = orion_pcie_rev(PCIE00_VIRT_BASE);
     44}
     45
     46u32 pcie_port_size[8] = {
     47	0,
     48	0x30000000,
     49	0x10000000,
     50	0x10000000,
     51	0x08000000,
     52	0x08000000,
     53	0x08000000,
     54	0x04000000,
     55};
     56
     57static void __init mv78xx0_pcie_preinit(void)
     58{
     59	int i;
     60	u32 size_each;
     61	u32 start;
     62
     63	pcie_io_space.name = "PCIe I/O Space";
     64	pcie_io_space.start = MV78XX0_PCIE_IO_PHYS_BASE(0);
     65	pcie_io_space.end =
     66		MV78XX0_PCIE_IO_PHYS_BASE(0) + MV78XX0_PCIE_IO_SIZE * 8 - 1;
     67	pcie_io_space.flags = IORESOURCE_MEM;
     68	if (request_resource(&iomem_resource, &pcie_io_space))
     69		panic("can't allocate PCIe I/O space");
     70
     71	if (num_pcie_ports > 7)
     72		panic("invalid number of PCIe ports");
     73
     74	size_each = pcie_port_size[num_pcie_ports];
     75
     76	start = MV78XX0_PCIE_MEM_PHYS_BASE;
     77	for (i = 0; i < num_pcie_ports; i++) {
     78		struct pcie_port *pp = pcie_port + i;
     79
     80		snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
     81			"PCIe %d.%d MEM", pp->maj, pp->min);
     82		pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
     83		pp->res.name = pp->mem_space_name;
     84		pp->res.flags = IORESOURCE_MEM;
     85		pp->res.start = start;
     86		pp->res.end = start + size_each - 1;
     87		start += size_each;
     88
     89		if (request_resource(&iomem_resource, &pp->res))
     90			panic("can't allocate PCIe MEM sub-space");
     91
     92		mvebu_mbus_add_window_by_id(MV78XX0_MBUS_PCIE_MEM_TARGET(pp->maj, pp->min),
     93					    MV78XX0_MBUS_PCIE_MEM_ATTR(pp->maj, pp->min),
     94					    pp->res.start, resource_size(&pp->res));
     95		mvebu_mbus_add_window_remap_by_id(MV78XX0_MBUS_PCIE_IO_TARGET(pp->maj, pp->min),
     96						  MV78XX0_MBUS_PCIE_IO_ATTR(pp->maj, pp->min),
     97						  i * SZ_64K, SZ_64K, 0);
     98	}
     99}
    100
    101static int __init mv78xx0_pcie_setup(int nr, struct pci_sys_data *sys)
    102{
    103	struct pcie_port *pp;
    104	struct resource realio;
    105
    106	if (nr >= num_pcie_ports)
    107		return 0;
    108
    109	pp = &pcie_port[nr];
    110	sys->private_data = pp;
    111	pp->root_bus_nr = sys->busnr;
    112
    113	/*
    114	 * Generic PCIe unit setup.
    115	 */
    116	orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
    117	orion_pcie_setup(pp->base);
    118
    119	realio.start = nr * SZ_64K;
    120	realio.end = realio.start + SZ_64K - 1;
    121	pci_remap_iospace(&realio, MV78XX0_PCIE_IO_PHYS_BASE(nr));
    122
    123	pci_add_resource_offset(&sys->resources, &pp->res, sys->mem_offset);
    124
    125	return 1;
    126}
    127
    128static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
    129{
    130	/*
    131	 * Don't go out when trying to access nonexisting devices
    132	 * on the local bus.
    133	 */
    134	if (bus == pp->root_bus_nr && dev > 1)
    135		return 0;
    136
    137	return 1;
    138}
    139
    140static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
    141			int size, u32 *val)
    142{
    143	struct pci_sys_data *sys = bus->sysdata;
    144	struct pcie_port *pp = sys->private_data;
    145	unsigned long flags;
    146	int ret;
    147
    148	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
    149		*val = 0xffffffff;
    150		return PCIBIOS_DEVICE_NOT_FOUND;
    151	}
    152
    153	spin_lock_irqsave(&pp->conf_lock, flags);
    154	ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
    155	spin_unlock_irqrestore(&pp->conf_lock, flags);
    156
    157	return ret;
    158}
    159
    160static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
    161			int where, int size, u32 val)
    162{
    163	struct pci_sys_data *sys = bus->sysdata;
    164	struct pcie_port *pp = sys->private_data;
    165	unsigned long flags;
    166	int ret;
    167
    168	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
    169		return PCIBIOS_DEVICE_NOT_FOUND;
    170
    171	spin_lock_irqsave(&pp->conf_lock, flags);
    172	ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
    173	spin_unlock_irqrestore(&pp->conf_lock, flags);
    174
    175	return ret;
    176}
    177
    178static struct pci_ops pcie_ops = {
    179	.read = pcie_rd_conf,
    180	.write = pcie_wr_conf,
    181};
    182
    183static void rc_pci_fixup(struct pci_dev *dev)
    184{
    185	/*
    186	 * Prevent enumeration of root complex.
    187	 */
    188	if (dev->bus->parent == NULL && dev->devfn == 0) {
    189		int i;
    190
    191		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
    192			dev->resource[i].start = 0;
    193			dev->resource[i].end   = 0;
    194			dev->resource[i].flags = 0;
    195		}
    196	}
    197}
    198DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
    199
    200static int __init mv78xx0_pcie_scan_bus(int nr, struct pci_host_bridge *bridge)
    201{
    202	struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
    203
    204	if (nr >= num_pcie_ports) {
    205		BUG();
    206		return -EINVAL;
    207	}
    208
    209	list_splice_init(&sys->resources, &bridge->windows);
    210	bridge->dev.parent = NULL;
    211	bridge->sysdata = sys;
    212	bridge->busnr = sys->busnr;
    213	bridge->ops = &pcie_ops;
    214
    215	return pci_scan_root_bus_bridge(bridge);
    216}
    217
    218static int __init mv78xx0_pcie_map_irq(const struct pci_dev *dev, u8 slot,
    219	u8 pin)
    220{
    221	struct pci_sys_data *sys = dev->bus->sysdata;
    222	struct pcie_port *pp = sys->private_data;
    223
    224	return IRQ_MV78XX0_PCIE_00 + (pp->maj << 2) + pp->min;
    225}
    226
    227static struct hw_pci mv78xx0_pci __initdata = {
    228	.nr_controllers	= 8,
    229	.preinit	= mv78xx0_pcie_preinit,
    230	.setup		= mv78xx0_pcie_setup,
    231	.scan		= mv78xx0_pcie_scan_bus,
    232	.map_irq	= mv78xx0_pcie_map_irq,
    233};
    234
    235static void __init add_pcie_port(int maj, int min, void __iomem *base)
    236{
    237	printk(KERN_INFO "MV78xx0 PCIe port %d.%d: ", maj, min);
    238
    239	if (orion_pcie_link_up(base)) {
    240		struct pcie_port *pp = &pcie_port[num_pcie_ports++];
    241
    242		printk("link up\n");
    243
    244		pp->maj = maj;
    245		pp->min = min;
    246		pp->root_bus_nr = -1;
    247		pp->base = base;
    248		spin_lock_init(&pp->conf_lock);
    249		memset(&pp->res, 0, sizeof(pp->res));
    250	} else {
    251		printk("link down, ignoring\n");
    252	}
    253}
    254
    255void __init mv78xx0_pcie_init(int init_port0, int init_port1)
    256{
    257	vga_base = MV78XX0_PCIE_MEM_PHYS_BASE;
    258
    259	if (init_port0) {
    260		add_pcie_port(0, 0, PCIE00_VIRT_BASE);
    261		if (!orion_pcie_x4_mode(PCIE00_VIRT_BASE)) {
    262			add_pcie_port(0, 1, PCIE01_VIRT_BASE);
    263			add_pcie_port(0, 2, PCIE02_VIRT_BASE);
    264			add_pcie_port(0, 3, PCIE03_VIRT_BASE);
    265		}
    266	}
    267
    268	if (init_port1) {
    269		add_pcie_port(1, 0, PCIE10_VIRT_BASE);
    270		if (!orion_pcie_x4_mode((void __iomem *)PCIE10_VIRT_BASE)) {
    271			add_pcie_port(1, 1, PCIE11_VIRT_BASE);
    272			add_pcie_port(1, 2, PCIE12_VIRT_BASE);
    273			add_pcie_port(1, 3, PCIE13_VIRT_BASE);
    274		}
    275	}
    276
    277	pci_common_init(&mv78xx0_pci);
    278}