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 (7539B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  linux/drivers/mtd/maps/pci.c
      4 *
      5 *  Copyright (C) 2001 Russell King, All rights reserved.
      6 *
      7 * Generic PCI memory map driver.  We support the following boards:
      8 *  - Intel IQ80310 ATU.
      9 *  - Intel EBSA285 (blank rom programming mode). Tested working 27/09/2001
     10 */
     11#include <linux/module.h>
     12#include <linux/kernel.h>
     13#include <linux/pci.h>
     14#include <linux/slab.h>
     15
     16#include <linux/mtd/mtd.h>
     17#include <linux/mtd/map.h>
     18#include <linux/mtd/partitions.h>
     19
     20struct map_pci_info;
     21
     22struct mtd_pci_info {
     23	int  (*init)(struct pci_dev *dev, struct map_pci_info *map);
     24	void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
     25	unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
     26	const char *map_name;
     27};
     28
     29struct map_pci_info {
     30	struct map_info map;
     31	void __iomem *base;
     32	void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
     33	unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
     34	struct pci_dev *dev;
     35};
     36
     37static map_word mtd_pci_read8(struct map_info *_map, unsigned long ofs)
     38{
     39	struct map_pci_info *map = (struct map_pci_info *)_map;
     40	map_word val;
     41	val.x[0]= readb(map->base + map->translate(map, ofs));
     42	return val;
     43}
     44
     45static map_word mtd_pci_read32(struct map_info *_map, unsigned long ofs)
     46{
     47	struct map_pci_info *map = (struct map_pci_info *)_map;
     48	map_word val;
     49	val.x[0] = readl(map->base + map->translate(map, ofs));
     50	return val;
     51}
     52
     53static void mtd_pci_copyfrom(struct map_info *_map, void *to, unsigned long from, ssize_t len)
     54{
     55	struct map_pci_info *map = (struct map_pci_info *)_map;
     56	memcpy_fromio(to, map->base + map->translate(map, from), len);
     57}
     58
     59static void mtd_pci_write8(struct map_info *_map, map_word val, unsigned long ofs)
     60{
     61	struct map_pci_info *map = (struct map_pci_info *)_map;
     62	writeb(val.x[0], map->base + map->translate(map, ofs));
     63}
     64
     65static void mtd_pci_write32(struct map_info *_map, map_word val, unsigned long ofs)
     66{
     67	struct map_pci_info *map = (struct map_pci_info *)_map;
     68	writel(val.x[0], map->base + map->translate(map, ofs));
     69}
     70
     71static void mtd_pci_copyto(struct map_info *_map, unsigned long to, const void *from, ssize_t len)
     72{
     73	struct map_pci_info *map = (struct map_pci_info *)_map;
     74	memcpy_toio(map->base + map->translate(map, to), from, len);
     75}
     76
     77static const struct map_info mtd_pci_map = {
     78	.phys =		NO_XIP,
     79	.copy_from =	mtd_pci_copyfrom,
     80	.copy_to =	mtd_pci_copyto,
     81};
     82
     83/*
     84 * Intel IOP80310 Flash driver
     85 */
     86
     87static int
     88intel_iq80310_init(struct pci_dev *dev, struct map_pci_info *map)
     89{
     90	u32 win_base;
     91
     92	map->map.bankwidth = 1;
     93	map->map.read = mtd_pci_read8;
     94	map->map.write = mtd_pci_write8;
     95
     96	map->map.size     = 0x00800000;
     97	map->base         = ioremap(pci_resource_start(dev, 0),
     98					    pci_resource_len(dev, 0));
     99
    100	if (!map->base)
    101		return -ENOMEM;
    102
    103	/*
    104	 * We want to base the memory window at Xscale
    105	 * bus address 0, not 0x1000.
    106	 */
    107	pci_read_config_dword(dev, 0x44, &win_base);
    108	pci_write_config_dword(dev, 0x44, 0);
    109
    110	map->map.map_priv_2 = win_base;
    111
    112	return 0;
    113}
    114
    115static void
    116intel_iq80310_exit(struct pci_dev *dev, struct map_pci_info *map)
    117{
    118	if (map->base)
    119		iounmap(map->base);
    120	pci_write_config_dword(dev, 0x44, map->map.map_priv_2);
    121}
    122
    123static unsigned long
    124intel_iq80310_translate(struct map_pci_info *map, unsigned long ofs)
    125{
    126	unsigned long page_addr = ofs & 0x00400000;
    127
    128	/*
    129	 * This mundges the flash location so we avoid
    130	 * the first 80 bytes (they appear to read nonsense).
    131	 */
    132	if (page_addr) {
    133		writel(0x00000008, map->base + 0x1558);
    134		writel(0x00000000, map->base + 0x1550);
    135	} else {
    136		writel(0x00000007, map->base + 0x1558);
    137		writel(0x00800000, map->base + 0x1550);
    138		ofs += 0x00800000;
    139	}
    140
    141	return ofs;
    142}
    143
    144static struct mtd_pci_info intel_iq80310_info = {
    145	.init =		intel_iq80310_init,
    146	.exit =		intel_iq80310_exit,
    147	.translate =	intel_iq80310_translate,
    148	.map_name =	"cfi_probe",
    149};
    150
    151/*
    152 * Intel DC21285 driver
    153 */
    154
    155static int
    156intel_dc21285_init(struct pci_dev *dev, struct map_pci_info *map)
    157{
    158	unsigned long base, len;
    159
    160	base = pci_resource_start(dev, PCI_ROM_RESOURCE);
    161	len  = pci_resource_len(dev, PCI_ROM_RESOURCE);
    162
    163	if (!len || !base) {
    164		/*
    165		 * No ROM resource
    166		 */
    167		base = pci_resource_start(dev, 2);
    168		len  = pci_resource_len(dev, 2);
    169
    170		/*
    171		 * We need to re-allocate PCI BAR2 address range to the
    172		 * PCI ROM BAR, and disable PCI BAR2.
    173		 */
    174	} else {
    175		/*
    176		 * Hmm, if an address was allocated to the ROM resource, but
    177		 * not enabled, should we be allocating a new resource for it
    178		 * or simply enabling it?
    179		 */
    180		pci_enable_rom(dev);
    181		printk("%s: enabling expansion ROM\n", pci_name(dev));
    182	}
    183
    184	if (!len || !base)
    185		return -ENXIO;
    186
    187	map->map.bankwidth = 4;
    188	map->map.read = mtd_pci_read32;
    189	map->map.write = mtd_pci_write32;
    190	map->map.size     = len;
    191	map->base         = ioremap(base, len);
    192
    193	if (!map->base)
    194		return -ENOMEM;
    195
    196	return 0;
    197}
    198
    199static void
    200intel_dc21285_exit(struct pci_dev *dev, struct map_pci_info *map)
    201{
    202	if (map->base)
    203		iounmap(map->base);
    204
    205	/*
    206	 * We need to undo the PCI BAR2/PCI ROM BAR address alteration.
    207	 */
    208	pci_disable_rom(dev);
    209}
    210
    211static unsigned long
    212intel_dc21285_translate(struct map_pci_info *map, unsigned long ofs)
    213{
    214	return ofs & 0x00ffffc0 ? ofs : (ofs ^ (1 << 5));
    215}
    216
    217static struct mtd_pci_info intel_dc21285_info = {
    218	.init =		intel_dc21285_init,
    219	.exit =		intel_dc21285_exit,
    220	.translate =	intel_dc21285_translate,
    221	.map_name =	"jedec_probe",
    222};
    223
    224/*
    225 * PCI device ID table
    226 */
    227
    228static const struct pci_device_id mtd_pci_ids[] = {
    229	{
    230		.vendor =	PCI_VENDOR_ID_INTEL,
    231		.device =	0x530d,
    232		.subvendor =	PCI_ANY_ID,
    233		.subdevice =	PCI_ANY_ID,
    234		.class =	PCI_CLASS_MEMORY_OTHER << 8,
    235		.class_mask =	0xffff00,
    236		.driver_data =	(unsigned long)&intel_iq80310_info,
    237	},
    238	{
    239		.vendor =	PCI_VENDOR_ID_DEC,
    240		.device =	PCI_DEVICE_ID_DEC_21285,
    241		.subvendor =	0,	/* DC21285 defaults to 0 on reset */
    242		.subdevice =	0,	/* DC21285 defaults to 0 on reset */
    243		.driver_data =	(unsigned long)&intel_dc21285_info,
    244	},
    245	{ 0, }
    246};
    247
    248/*
    249 * Generic code follows.
    250 */
    251
    252static int mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
    253{
    254	struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data;
    255	struct map_pci_info *map = NULL;
    256	struct mtd_info *mtd = NULL;
    257	int err;
    258
    259	err = pci_enable_device(dev);
    260	if (err)
    261		goto out;
    262
    263	err = pci_request_regions(dev, "pci mtd");
    264	if (err)
    265		goto out;
    266
    267	map = kmalloc(sizeof(*map), GFP_KERNEL);
    268	err = -ENOMEM;
    269	if (!map)
    270		goto release;
    271
    272	map->map       = mtd_pci_map;
    273	map->map.name  = pci_name(dev);
    274	map->dev       = dev;
    275	map->exit      = info->exit;
    276	map->translate = info->translate;
    277
    278	err = info->init(dev, map);
    279	if (err)
    280		goto release;
    281
    282	mtd = do_map_probe(info->map_name, &map->map);
    283	err = -ENODEV;
    284	if (!mtd)
    285		goto release;
    286
    287	mtd->owner = THIS_MODULE;
    288	mtd_device_register(mtd, NULL, 0);
    289
    290	pci_set_drvdata(dev, mtd);
    291
    292	return 0;
    293
    294release:
    295	if (map) {
    296		map->exit(dev, map);
    297		kfree(map);
    298	}
    299
    300	pci_release_regions(dev);
    301out:
    302	return err;
    303}
    304
    305static void mtd_pci_remove(struct pci_dev *dev)
    306{
    307	struct mtd_info *mtd = pci_get_drvdata(dev);
    308	struct map_pci_info *map = mtd->priv;
    309
    310	mtd_device_unregister(mtd);
    311	map_destroy(mtd);
    312	map->exit(dev, map);
    313	kfree(map);
    314
    315	pci_release_regions(dev);
    316}
    317
    318static struct pci_driver mtd_pci_driver = {
    319	.name =		"MTD PCI",
    320	.probe =	mtd_pci_probe,
    321	.remove =	mtd_pci_remove,
    322	.id_table =	mtd_pci_ids,
    323};
    324
    325module_pci_driver(mtd_pci_driver);
    326
    327MODULE_LICENSE("GPL");
    328MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
    329MODULE_DESCRIPTION("Generic PCI map driver");
    330MODULE_DEVICE_TABLE(pci, mtd_pci_ids);