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

pci.c (6457B)


      1/*
      2 * pci.c -- PCI bus support for ColdFire processors
      3 *
      4 * (C) Copyright 2012, Greg Ungerer <gerg@uclinux.com>
      5 *
      6 * This file is subject to the terms and conditions of the GNU General Public
      7 * License.  See the file COPYING in the main directory of this archive
      8 * for more details.
      9 */
     10
     11#include <linux/types.h>
     12#include <linux/module.h>
     13#include <linux/init.h>
     14#include <linux/kernel.h>
     15#include <linux/interrupt.h>
     16#include <linux/irq.h>
     17#include <linux/io.h>
     18#include <linux/pci.h>
     19#include <linux/delay.h>
     20#include <asm/coldfire.h>
     21#include <asm/mcfsim.h>
     22#include <asm/m54xxpci.h>
     23
     24/*
     25 * Memory and IO mappings. We use a 1:1 mapping for local host memory to
     26 * PCI bus memory (no reason not to really). IO space is mapped in its own
     27 * separate address region. The device configuration space is mapped over
     28 * the IO map space when we enable it in the PCICAR register.
     29 */
     30static struct pci_bus *rootbus;
     31static unsigned long iospace;
     32
     33/*
     34 * We need to be careful probing on bus 0 (directly connected to host
     35 * bridge). We should only access the well defined possible devices in
     36 * use, ignore aliases and the like.
     37 */
     38static unsigned char mcf_host_slot2sid[32] = {
     39	0, 0, 0, 0, 0, 0, 0, 0,
     40	0, 0, 0, 0, 0, 0, 0, 0,
     41	0, 1, 2, 0, 3, 4, 0, 0,
     42	0, 0, 0, 0, 0, 0, 0, 0,
     43};
     44
     45static unsigned char mcf_host_irq[] = {
     46	0, 69, 69, 71, 71,
     47};
     48
     49/*
     50 * Configuration space access functions. Configuration space access is
     51 * through the IO mapping window, enabling it via the PCICAR register.
     52 */
     53static unsigned long mcf_mk_pcicar(int bus, unsigned int devfn, int where)
     54{
     55	return (bus << PCICAR_BUSN) | (devfn << PCICAR_DEVFNN) | (where & 0xfc);
     56}
     57
     58static int mcf_pci_readconfig(struct pci_bus *bus, unsigned int devfn,
     59	int where, int size, u32 *value)
     60{
     61	unsigned long addr;
     62
     63	*value = 0xffffffff;
     64
     65	if (bus->number == 0) {
     66		if (mcf_host_slot2sid[PCI_SLOT(devfn)] == 0)
     67			return PCIBIOS_SUCCESSFUL;
     68	}
     69
     70	addr = mcf_mk_pcicar(bus->number, devfn, where);
     71	__raw_writel(PCICAR_E | addr, PCICAR);
     72	__raw_readl(PCICAR);
     73	addr = iospace + (where & 0x3);
     74
     75	switch (size) {
     76	case 1:
     77		*value = __raw_readb(addr);
     78		break;
     79	case 2:
     80		*value = le16_to_cpu(__raw_readw(addr));
     81		break;
     82	default:
     83		*value = le32_to_cpu(__raw_readl(addr));
     84		break;
     85	}
     86
     87	__raw_writel(0, PCICAR);
     88	__raw_readl(PCICAR);
     89	return PCIBIOS_SUCCESSFUL;
     90}
     91
     92static int mcf_pci_writeconfig(struct pci_bus *bus, unsigned int devfn,
     93	int where, int size, u32 value)
     94{
     95	unsigned long addr;
     96
     97	if (bus->number == 0) {
     98		if (mcf_host_slot2sid[PCI_SLOT(devfn)] == 0)
     99			return PCIBIOS_SUCCESSFUL;
    100	}
    101
    102	addr = mcf_mk_pcicar(bus->number, devfn, where);
    103	__raw_writel(PCICAR_E | addr, PCICAR);
    104	__raw_readl(PCICAR);
    105	addr = iospace + (where & 0x3);
    106
    107	switch (size) {
    108	case 1:
    109		 __raw_writeb(value, addr);
    110		break;
    111	case 2:
    112		__raw_writew(cpu_to_le16(value), addr);
    113		break;
    114	default:
    115		__raw_writel(cpu_to_le32(value), addr);
    116		break;
    117	}
    118
    119	__raw_writel(0, PCICAR);
    120	__raw_readl(PCICAR);
    121	return PCIBIOS_SUCCESSFUL;
    122}
    123
    124static struct pci_ops mcf_pci_ops = {
    125	.read	= mcf_pci_readconfig,
    126	.write	= mcf_pci_writeconfig,
    127};
    128
    129/*
    130 * Initialize the PCI bus registers, and scan the bus.
    131 */
    132static struct resource mcf_pci_mem = {
    133	.name	= "PCI Memory space",
    134	.start	= PCI_MEM_PA,
    135	.end	= PCI_MEM_PA + PCI_MEM_SIZE - 1,
    136	.flags	= IORESOURCE_MEM,
    137};
    138
    139static struct resource mcf_pci_io = {
    140	.name	= "PCI IO space",
    141	.start	= 0x400,
    142	.end	= 0x10000 - 1,
    143	.flags	= IORESOURCE_IO,
    144};
    145
    146static struct resource busn_resource = {
    147	.name	= "PCI busn",
    148	.start	= 0,
    149	.end	= 255,
    150	.flags	= IORESOURCE_BUS,
    151};
    152
    153/*
    154 * Interrupt mapping and setting.
    155 */
    156static int mcf_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
    157{
    158	int sid;
    159
    160	sid = mcf_host_slot2sid[slot];
    161	if (sid)
    162		return mcf_host_irq[sid];
    163	return 0;
    164}
    165
    166static int __init mcf_pci_init(void)
    167{
    168	struct pci_host_bridge *bridge;
    169	int ret;
    170
    171	bridge = pci_alloc_host_bridge(0);
    172	if (!bridge)
    173		return -ENOMEM;
    174
    175	pr_info("ColdFire: PCI bus initialization...\n");
    176
    177	/* Reset the external PCI bus */
    178	__raw_writel(PCIGSCR_RESET, PCIGSCR);
    179	__raw_writel(0, PCITCR);
    180
    181	request_resource(&iomem_resource, &mcf_pci_mem);
    182	request_resource(&iomem_resource, &mcf_pci_io);
    183
    184	/* Configure PCI arbiter */
    185	__raw_writel(PACR_INTMPRI | PACR_INTMINTE | PACR_EXTMPRI(0x1f) |
    186		PACR_EXTMINTE(0x1f), PACR);
    187
    188	/* Set required multi-function pins for PCI bus use */
    189	__raw_writew(0x3ff, MCFGPIO_PAR_PCIBG);
    190	__raw_writew(0x3ff, MCFGPIO_PAR_PCIBR);
    191
    192	/* Set up config space for local host bus controller */
    193	__raw_writel(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
    194		PCI_COMMAND_INVALIDATE, PCISCR);
    195	__raw_writel(PCICR1_LT(32) | PCICR1_CL(8), PCICR1);
    196	__raw_writel(0, PCICR2);
    197
    198	/*
    199	 * Set up the initiator windows for memory and IO mapping.
    200	 * These give the CPU bus access onto the PCI bus. One for each of
    201	 * PCI memory and IO address spaces.
    202	 */
    203	__raw_writel(WXBTAR(PCI_MEM_PA, PCI_MEM_BA, PCI_MEM_SIZE),
    204		PCIIW0BTAR);
    205	__raw_writel(WXBTAR(PCI_IO_PA, PCI_IO_BA, PCI_IO_SIZE),
    206		PCIIW1BTAR);
    207	__raw_writel(PCIIWCR_W0_MEM /*| PCIIWCR_W0_MRDL*/ | PCIIWCR_W0_E |
    208		PCIIWCR_W1_IO | PCIIWCR_W1_E, PCIIWCR);
    209
    210	/*
    211	 * Set up the target windows for access from the PCI bus back to the
    212	 * CPU bus. All we need is access to system RAM (for mastering).
    213	 */
    214	__raw_writel(CONFIG_RAMBASE, PCIBAR1);
    215	__raw_writel(CONFIG_RAMBASE | PCITBATR1_E, PCITBATR1);
    216
    217	/* Keep a virtual mapping to IO/config space active */
    218	iospace = (unsigned long) ioremap(PCI_IO_PA, PCI_IO_SIZE);
    219	if (iospace == 0) {
    220		pci_free_host_bridge(bridge);
    221		return -ENODEV;
    222	}
    223	pr_info("Coldfire: PCI IO/config window mapped to 0x%x\n",
    224		(u32) iospace);
    225
    226	/* Turn of PCI reset, and wait for devices to settle */
    227	__raw_writel(0, PCIGSCR);
    228	set_current_state(TASK_UNINTERRUPTIBLE);
    229	schedule_timeout(msecs_to_jiffies(200));
    230
    231
    232	pci_add_resource(&bridge->windows, &ioport_resource);
    233	pci_add_resource(&bridge->windows, &iomem_resource);
    234	pci_add_resource(&bridge->windows, &busn_resource);
    235	bridge->dev.parent = NULL;
    236	bridge->sysdata = NULL;
    237	bridge->busnr = 0;
    238	bridge->ops = &mcf_pci_ops;
    239	bridge->swizzle_irq = pci_common_swizzle;
    240	bridge->map_irq = mcf_pci_map_irq;
    241
    242	ret = pci_scan_root_bus_bridge(bridge);
    243	if (ret) {
    244		pci_free_host_bridge(bridge);
    245		return ret;
    246	}
    247
    248	rootbus = bridge->bus;
    249
    250	rootbus->resource[0] = &mcf_pci_io;
    251	rootbus->resource[1] = &mcf_pci_mem;
    252
    253	pci_bus_size_bridges(rootbus);
    254	pci_bus_assign_resources(rootbus);
    255	pci_bus_add_devices(rootbus);
    256	return 0;
    257}
    258
    259subsys_initcall(mcf_pci_init);