^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) * esb2rom.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Normal mappings of flash chips in physical memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * through the Intel ESB2 Southbridge.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This was derived from ichxrom.c in May 2006 by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Lew Glendenning <lglendenning@lnxi.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Eric Biederman, of course, was a major help in this effort.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/mtd/mtd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/mtd/map.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/mtd/cfi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/mtd/flashchip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/pci_ids.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define MOD_NAME KBUILD_BASENAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define ADDRESS_NAME_LEN 18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define BIOS_CNTL 0xDC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define BIOS_LOCK_ENABLE 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define BIOS_WRITE_ENABLE 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* This became a 16-bit register, and EN2 has disappeared */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define FWH_DEC_EN1 0xD8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define FWH_F8_EN 0x8000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define FWH_F0_EN 0x4000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define FWH_E8_EN 0x2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define FWH_E0_EN 0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define FWH_D8_EN 0x0800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define FWH_D0_EN 0x0400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define FWH_C8_EN 0x0200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define FWH_C0_EN 0x0100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define FWH_LEGACY_F_EN 0x0080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define FWH_LEGACY_E_EN 0x0040
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* reserved 0x0020 and 0x0010 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define FWH_70_EN 0x0008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define FWH_60_EN 0x0004
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define FWH_50_EN 0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define FWH_40_EN 0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* these are 32-bit values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define FWH_SEL1 0xD0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define FWH_SEL2 0xD4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define FWH_8MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) FWH_70_EN | FWH_60_EN | FWH_50_EN | FWH_40_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define FWH_7MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) FWH_70_EN | FWH_60_EN | FWH_50_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define FWH_6MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) FWH_70_EN | FWH_60_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define FWH_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) FWH_70_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define FWH_4MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) FWH_D8_EN | FWH_D0_EN | FWH_C8_EN | FWH_C0_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define FWH_3_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) FWH_D8_EN | FWH_D0_EN | FWH_C8_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define FWH_3MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) FWH_D8_EN | FWH_D0_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define FWH_2_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) FWH_D8_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define FWH_2MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN | FWH_E0_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define FWH_1_5MiB (FWH_F8_EN | FWH_F0_EN | FWH_E8_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define FWH_1MiB (FWH_F8_EN | FWH_F0_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define FWH_0_5MiB (FWH_F8_EN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct esb2rom_window {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) void __iomem* virt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) unsigned long phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) unsigned long size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct list_head maps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct resource rsrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct esb2rom_map_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct map_info map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct mtd_info *mtd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct resource rsrc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static struct esb2rom_window esb2rom_window = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .maps = LIST_HEAD_INIT(esb2rom_window.maps),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static void esb2rom_cleanup(struct esb2rom_window *window)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct esb2rom_map_info *map, *scratch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) u8 byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* Disable writes through the rom window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) pci_read_config_byte(window->pdev, BIOS_CNTL, &byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) pci_write_config_byte(window->pdev, BIOS_CNTL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) byte & ~BIOS_WRITE_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* Free all of the mtd devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) list_for_each_entry_safe(map, scratch, &window->maps, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (map->rsrc.parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) release_resource(&map->rsrc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) mtd_device_unregister(map->mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) map_destroy(map->mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) list_del(&map->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) kfree(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (window->rsrc.parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) release_resource(&window->rsrc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (window->virt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) iounmap(window->virt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) window->virt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) window->phys = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) window->size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) pci_dev_put(window->pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int __init esb2rom_init_one(struct pci_dev *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) const struct pci_device_id *ent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct esb2rom_window *window = &esb2rom_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct esb2rom_map_info *map = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) unsigned long map_top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) u8 byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) u16 word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* For now I just handle the ecb2 and I assume there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * are not a lot of resources up at the top of the address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * space. It is possible to handle other devices in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * top 16MiB but it is very painful. Also since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * you can only really attach a FWH to an ICHX there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * a number of simplifications you can make.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * Also you can page firmware hubs if an 8MiB window isn't enough
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * but don't currently handle that case either.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) window->pdev = pci_dev_get(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /* RLG: experiment 2. Force the window registers to the widest values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) pci_read_config_word(pdev, FWH_DEC_EN1, &word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) printk(KERN_DEBUG "Original FWH_DEC_EN1 : %x\n", word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) pci_write_config_byte(pdev, FWH_DEC_EN1, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) pci_read_config_byte(pdev, FWH_DEC_EN1, &byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) printk(KERN_DEBUG "New FWH_DEC_EN1 : %x\n", byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) pci_read_config_byte(pdev, FWH_DEC_EN2, &byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) printk(KERN_DEBUG "Original FWH_DEC_EN2 : %x\n", byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) pci_write_config_byte(pdev, FWH_DEC_EN2, 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) pci_read_config_byte(pdev, FWH_DEC_EN2, &byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) printk(KERN_DEBUG "New FWH_DEC_EN2 : %x\n", byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* Find a region continuous to the end of the ROM window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) window->phys = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) pci_read_config_word(pdev, FWH_DEC_EN1, &word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) printk(KERN_DEBUG "pci_read_config_word : %x\n", word);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if ((word & FWH_8MiB) == FWH_8MiB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) window->phys = 0xff400000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) else if ((word & FWH_7MiB) == FWH_7MiB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) window->phys = 0xff500000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) else if ((word & FWH_6MiB) == FWH_6MiB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) window->phys = 0xff600000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) else if ((word & FWH_5MiB) == FWH_5MiB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) window->phys = 0xFF700000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) else if ((word & FWH_4MiB) == FWH_4MiB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) window->phys = 0xffc00000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) else if ((word & FWH_3_5MiB) == FWH_3_5MiB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) window->phys = 0xffc80000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) else if ((word & FWH_3MiB) == FWH_3MiB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) window->phys = 0xffd00000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) else if ((word & FWH_2_5MiB) == FWH_2_5MiB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) window->phys = 0xffd80000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) else if ((word & FWH_2MiB) == FWH_2MiB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) window->phys = 0xffe00000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) else if ((word & FWH_1_5MiB) == FWH_1_5MiB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) window->phys = 0xffe80000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) else if ((word & FWH_1MiB) == FWH_1MiB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) window->phys = 0xfff00000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) else if ((word & FWH_0_5MiB) == FWH_0_5MiB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) window->phys = 0xfff80000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (window->phys == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) printk(KERN_ERR MOD_NAME ": Rom window is closed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* reserved 0x0020 and 0x0010 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) window->phys -= 0x400000UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) window->size = (0xffffffffUL - window->phys) + 1UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* Enable writes through the rom window */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) pci_read_config_byte(pdev, BIOS_CNTL, &byte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (!(byte & BIOS_WRITE_ENABLE) && (byte & (BIOS_LOCK_ENABLE))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* The BIOS will generate an error if I enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * this device, so don't even try.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable writes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) pci_write_config_byte(pdev, BIOS_CNTL, byte | BIOS_WRITE_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * Try to reserve the window mem region. If this fails then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * it is likely due to the window being "reserved" by the BIOS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) window->rsrc.name = MOD_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) window->rsrc.start = window->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) window->rsrc.end = window->phys + window->size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (request_resource(&iomem_resource, &window->rsrc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) window->rsrc.parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) printk(KERN_DEBUG MOD_NAME ": "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) "%s(): Unable to register resource %pR - kernel bug?\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) __func__, &window->rsrc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /* Map the firmware hub into my address space. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) window->virt = ioremap(window->phys, window->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (!window->virt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) window->phys, window->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* Get the first address to look for an rom chip at */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) map_top = window->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) if ((window->phys & 0x3fffff) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /* if not aligned on 4MiB, look 4MiB lower in address space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) map_top = window->phys + 0x400000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) #if 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /* The probe sequence run over the firmware hub lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * registers sets them to 0x7 (no access).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * (Insane hardware design, but most copied Intel's.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * ==> Probe at most the last 4M of the address space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (map_top < 0xffc00000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) map_top = 0xffc00000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* Loop through and look for rom chips */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) while ((map_top - 1) < 0xffffffffUL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) struct cfi_private *cfi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) unsigned long offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (!map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) map = kmalloc(sizeof(*map), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (!map) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) printk(KERN_ERR MOD_NAME ": kmalloc failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) memset(map, 0, sizeof(*map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) INIT_LIST_HEAD(&map->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) map->map.name = map->map_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) map->map.phys = map_top;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) offset = map_top - window->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) map->map.virt = (void __iomem *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) (((unsigned long)(window->virt)) + offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) map->map.size = 0xffffffffUL - map_top + 1UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* Set the name of the map to the address I am trying */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) sprintf(map->map_name, "%s @%08Lx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) MOD_NAME, (unsigned long long)map->map.phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* Firmware hubs only use vpp when being programmed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * in a factory setting. So in-place programming
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * needs to use a different method.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) for(map->map.bankwidth = 32; map->map.bankwidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) map->map.bankwidth >>= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) char **probe_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /* Skip bankwidths that are not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (!map_bankwidth_supported(map->map.bankwidth))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /* Setup the map methods */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) simple_map_init(&map->map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /* Try all of the probe methods */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) probe_type = rom_probe_types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) for(; *probe_type; probe_type++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) map->mtd = do_map_probe(*probe_type, &map->map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (map->mtd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) map_top += ROM_PROBE_STEP_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /* Trim the size if we are larger than the map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (map->mtd->size > map->map.size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) printk(KERN_WARNING MOD_NAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) " rom(%llu) larger than window(%lu). fixing...\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) (unsigned long long)map->mtd->size, map->map.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) map->mtd->size = map->map.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (window->rsrc.parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * Registering the MTD device in iomem may not be possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * if there is a BIOS "reserved" and BUSY range. If this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * fails then continue anyway.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) map->rsrc.name = map->map_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) map->rsrc.start = map->map.phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) map->rsrc.end = map->map.phys + map->mtd->size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (request_resource(&window->rsrc, &map->rsrc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) printk(KERN_ERR MOD_NAME
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) ": cannot reserve MTD resource\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) map->rsrc.parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /* Make the whole region visible in the map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) map->map.virt = window->virt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) map->map.phys = window->phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) cfi = map->map.fldrv_priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) for(i = 0; i < cfi->numchips; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) cfi->chips[i].start += offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* Now that the mtd devices is complete claim and export it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) map->mtd->owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if (mtd_device_register(map->mtd, NULL, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) map_destroy(map->mtd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) map->mtd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) /* Calculate the new value of map_top */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) map_top += map->mtd->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) /* File away the map structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) list_add(&map->list, &window->maps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) map = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) /* Free any left over map structures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) kfree(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /* See if I have any map structures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (list_empty(&window->maps)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) esb2rom_cleanup(window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static void esb2rom_remove_one(struct pci_dev *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct esb2rom_window *window = &esb2rom_window;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) esb2rom_cleanup(window);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static const struct pci_device_id esb2rom_pci_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) PCI_ANY_ID, PCI_ANY_ID, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) PCI_ANY_ID, PCI_ANY_ID, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) PCI_ANY_ID, PCI_ANY_ID, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) PCI_ANY_ID, PCI_ANY_ID, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) PCI_ANY_ID, PCI_ANY_ID, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) PCI_ANY_ID, PCI_ANY_ID, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) { 0, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) MODULE_DEVICE_TABLE(pci, esb2rom_pci_tbl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) static struct pci_driver esb2rom_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) .name = MOD_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) .id_table = esb2rom_pci_tbl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) .probe = esb2rom_init_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) .remove = esb2rom_remove_one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) static int __init init_esb2rom(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct pci_dev *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) const struct pci_device_id *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int retVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) pdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) for (id = esb2rom_pci_tbl; id->vendor; id++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) printk(KERN_DEBUG "device id = %x\n", id->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) pdev = pci_get_device(id->vendor, id->device, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) printk(KERN_DEBUG "matched device = %x\n", id->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (pdev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) printk(KERN_DEBUG "matched device id %x\n", id->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) retVal = esb2rom_init_one(pdev, &esb2rom_pci_tbl[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) pci_dev_put(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) printk(KERN_DEBUG "retVal = %d\n", retVal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) return retVal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return pci_register_driver(&esb2rom_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) static void __exit cleanup_esb2rom(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) esb2rom_remove_one(esb2rom_window.pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) module_init(init_esb2rom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) module_exit(cleanup_esb2rom);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) MODULE_AUTHOR("Lew Glendenning <lglendenning@lnxi.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) MODULE_DESCRIPTION("MTD map driver for BIOS chips on the ESB2 southbridge");