^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * MTD map driver for BIOS Flash on Intel SCB2 boards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2002 Sun Microsystems, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Tim Hockin <thockin@sun.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * A few notes on this MTD map:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This was developed with a small number of SCB2 boards to test on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Hopefully, Intel has not introducted too many unaccounted variables in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * making of this board.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * The BIOS marks its own memory region as 'reserved' in the e820 map. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * try to request it here, but if it fails, we carry on anyway.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * This is how the chip is attached, so said the schematic:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * * a 4 MiB (32 Mib) 16 bit chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * * a 1 MiB memory region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * * A20 and A21 pulled up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * * D8-D15 ignored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * What this means is that, while we are addressing bytes linearly, we are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * really addressing words, and discarding the other byte. This means that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * the chip MUST BE at least 2 MiB. This also means that every block is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * actually half as big as the chip reports. It also means that accesses of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * logical address 0 hit higher-address sections of the chip, not physical 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * One can only hope that these 4MiB x16 chips were a lot cheaper than 1MiB x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * chips.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * This driver assumes the chip is not write-protected by an external signal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * As of the this writing, that is true, but may change, just to spite me.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * The actual BIOS layout has been mostly reverse engineered. Intel BIOS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * updates for this board include 10 related (*.bio - &.bi9) binary files and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * another separate (*.bbo) binary file. The 10 files are 64k of data + a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * small header. If the headers are stripped off, the 10 64k files can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * concatenated into a 640k image. This is your BIOS image, proper. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * separate .bbo file also has a small header. It is the 'Boot Block'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * recovery BIOS. Once the header is stripped, no further prep is needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * As best I can tell, the BIOS is arranged as such:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * offset 0x00000 to 0x4ffff (320k): unknown - SCSI BIOS, etc?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * offset 0x50000 to 0xeffff (640k): BIOS proper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * offset 0xf0000 ty 0xfffff (64k): Boot Block region
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * Intel's BIOS update program flashes the BIOS and Boot Block in separate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * steps. Probably a wise thing to do.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include <linux/mtd/mtd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include <linux/mtd/map.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #include <linux/mtd/cfi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #include <linux/pci_ids.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define MODNAME "scb2_flash"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define SCB2_ADDR 0xfff00000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define SCB2_WINDOW 0x00100000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static void __iomem *scb2_ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static struct mtd_info *scb2_mtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static struct map_info scb2_map = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .name = "SCB2 BIOS Flash",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .size = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) .bankwidth = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static int region_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static int scb2_fixup_mtd(struct mtd_info *mtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) struct map_info *map = mtd->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct cfi_private *cfi = map->fldrv_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* barf if this doesn't look right */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (cfi->cfiq->InterfaceDesc != CFI_INTERFACE_X16_ASYNC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) printk(KERN_ERR MODNAME ": unsupported InterfaceDesc: %#x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) cfi->cfiq->InterfaceDesc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* I wasn't here. I didn't see. dwmw2. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* the chip is sometimes bigger than the map - what a waste */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) mtd->size = map->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * We only REALLY get half the chip, due to the way it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * wired up - D8-D15 are tossed away. We read linear bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * but in reality we are getting 1/2 of each 16-bit read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * which LOOKS linear to us. Because CFI code accounts for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * things like lock/unlock/erase by eraseregions, we need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * fudge them to reflect this. Erases go like this:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * * send an erase to an address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * * the chip samples the address and erases the block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * * add the block erasesize to the address and repeat
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * -- the problem is that addresses are 16-bit addressable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * -- we end up erasing every-other block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) mtd->erasesize /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) for (i = 0; i < mtd->numeraseregions; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct mtd_erase_region_info *region = &mtd->eraseregions[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) region->erasesize /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * If the chip is bigger than the map, it is wired with the high
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * address lines pulled up. This makes us access the top portion of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * the chip, so all our erase-region info is wrong. Start cutting from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * the bottom.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) for (i = 0; !done && i < mtd->numeraseregions; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct mtd_erase_region_info *region = &mtd->eraseregions[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (region->numblocks * region->erasesize > mtd->size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) region->numblocks = ((unsigned long)mtd->size /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) region->erasesize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) region->numblocks = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) region->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* CSB5's 'Function Control Register' has bits for decoding @ >= 0xffc00000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define CSB5_FCR 0x41
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define CSB5_FCR_DECODE_ALL 0x0e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static int scb2_flash_probe(struct pci_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* enable decoding of the flash region in the south bridge */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) pci_read_config_byte(dev, CSB5_FCR, ®);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) pci_write_config_byte(dev, CSB5_FCR, reg | CSB5_FCR_DECODE_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (!request_mem_region(SCB2_ADDR, SCB2_WINDOW, scb2_map.name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * The BIOS seems to mark the flash region as 'reserved'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * in the e820 map. Warn and go about our business.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) printk(KERN_WARNING MODNAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) ": warning - can't reserve rom window, continuing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) region_fail = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* remap the IO window (w/o caching) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) scb2_ioaddr = ioremap(SCB2_ADDR, SCB2_WINDOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (!scb2_ioaddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) printk(KERN_ERR MODNAME ": Failed to ioremap window!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (!region_fail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) release_mem_region(SCB2_ADDR, SCB2_WINDOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) scb2_map.phys = SCB2_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) scb2_map.virt = scb2_ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) scb2_map.size = SCB2_WINDOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) simple_map_init(&scb2_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /* try to find a chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) scb2_mtd = do_map_probe("cfi_probe", &scb2_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (!scb2_mtd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) printk(KERN_ERR MODNAME ": flash probe failed!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) iounmap(scb2_ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (!region_fail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) release_mem_region(SCB2_ADDR, SCB2_WINDOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) scb2_mtd->owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (scb2_fixup_mtd(scb2_mtd) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) mtd_device_unregister(scb2_mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) map_destroy(scb2_mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) iounmap(scb2_ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (!region_fail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) release_mem_region(SCB2_ADDR, SCB2_WINDOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) printk(KERN_NOTICE MODNAME ": chip size 0x%llx at offset 0x%llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) (unsigned long long)scb2_mtd->size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) (unsigned long long)(SCB2_WINDOW - scb2_mtd->size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) mtd_device_register(scb2_mtd, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static void scb2_flash_remove(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (!scb2_mtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* disable flash writes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) mtd_lock(scb2_mtd, 0, scb2_mtd->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) mtd_device_unregister(scb2_mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) map_destroy(scb2_mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) iounmap(scb2_ioaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) scb2_ioaddr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) if (!region_fail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) release_mem_region(SCB2_ADDR, SCB2_WINDOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static struct pci_device_id scb2_flash_pci_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .vendor = PCI_VENDOR_ID_SERVERWORKS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) .device = PCI_DEVICE_ID_SERVERWORKS_CSB5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .subvendor = PCI_ANY_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .subdevice = PCI_ANY_ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) { 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static struct pci_driver scb2_flash_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .name = "Intel SCB2 BIOS Flash",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .id_table = scb2_flash_pci_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .probe = scb2_flash_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .remove = scb2_flash_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) module_pci_driver(scb2_flash_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) MODULE_AUTHOR("Tim Hockin <thockin@sun.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) MODULE_DESCRIPTION("MTD map driver for Intel SCB2 BIOS Flash");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) MODULE_DEVICE_TABLE(pci, scb2_flash_pci_ids);