linux/drivers/mtd/maps/l440gx.c
<<
>>
Prefs
   1/*
   2 * $Id: l440gx.c,v 1.18 2005/11/07 11:14:27 gleixner Exp $
   3 *
   4 * BIOS Flash chip on Intel 440GX board.
   5 *
   6 * Bugs this currently does not work under linuxBIOS.
   7 */
   8
   9#include <linux/module.h>
  10#include <linux/pci.h>
  11#include <linux/kernel.h>
  12#include <linux/init.h>
  13#include <asm/io.h>
  14#include <linux/mtd/mtd.h>
  15#include <linux/mtd/map.h>
  16
  17#define PIIXE_IOBASE_RESOURCE   11
  18
  19#define WINDOW_ADDR 0xfff00000
  20#define WINDOW_SIZE 0x00100000
  21#define BUSWIDTH 1
  22
  23static u32 iobase;
  24#define IOBASE iobase
  25#define TRIBUF_PORT (IOBASE+0x37)
  26#define VPP_PORT (IOBASE+0x28)
  27
  28static struct mtd_info *mymtd;
  29
  30
  31/* Is this really the vpp port? */
  32static void l440gx_set_vpp(struct map_info *map, int vpp)
  33{
  34        unsigned long l;
  35
  36        l = inl(VPP_PORT);
  37        if (vpp) {
  38                l |= 1;
  39        } else {
  40                l &= ~1;
  41        }
  42        outl(l, VPP_PORT);
  43}
  44
  45static struct map_info l440gx_map = {
  46        .name = "L440GX BIOS",
  47        .size = WINDOW_SIZE,
  48        .bankwidth = BUSWIDTH,
  49        .phys = WINDOW_ADDR,
  50#if 0
  51        /* FIXME verify that this is the
  52         * appripriate code for vpp enable/disable
  53         */
  54        .set_vpp = l440gx_set_vpp
  55#endif
  56};
  57
  58static int __init init_l440gx(void)
  59{
  60        struct pci_dev *dev, *pm_dev;
  61        struct resource *pm_iobase;
  62        __u16 word;
  63
  64        dev = pci_get_device(PCI_VENDOR_ID_INTEL,
  65                PCI_DEVICE_ID_INTEL_82371AB_0, NULL);
  66
  67        pm_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
  68                PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
  69
  70        pci_dev_put(dev);
  71
  72        if (!dev || !pm_dev) {
  73                printk(KERN_NOTICE "L440GX flash mapping: failed to find PIIX4 ISA bridge, cannot continue\n");
  74                pci_dev_put(pm_dev);
  75                return -ENODEV;
  76        }
  77
  78        l440gx_map.virt = ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
  79
  80        if (!l440gx_map.virt) {
  81                printk(KERN_WARNING "Failed to ioremap L440GX flash region\n");
  82                pci_dev_put(pm_dev);
  83                return -ENOMEM;
  84        }
  85        simple_map_init(&l440gx_map);
  86        printk(KERN_NOTICE "window_addr = 0x%08lx\n", (unsigned long)l440gx_map.virt);
  87
  88        /* Setup the pm iobase resource
  89         * This code should move into some kind of generic bridge
  90         * driver but for the moment I'm content with getting the
  91         * allocation correct.
  92         */
  93        pm_iobase = &pm_dev->resource[PIIXE_IOBASE_RESOURCE];
  94        if (!(pm_iobase->flags & IORESOURCE_IO)) {
  95                pm_iobase->name = "pm iobase";
  96                pm_iobase->start = 0;
  97                pm_iobase->end = 63;
  98                pm_iobase->flags = IORESOURCE_IO;
  99
 100                /* Put the current value in the resource */
 101                pci_read_config_dword(pm_dev, 0x40, &iobase);
 102                iobase &= ~1;
 103                pm_iobase->start += iobase & ~1;
 104                pm_iobase->end += iobase & ~1;
 105
 106                pci_dev_put(pm_dev);
 107
 108                /* Allocate the resource region */
 109                if (pci_assign_resource(pm_dev, PIIXE_IOBASE_RESOURCE) != 0) {
 110                        pci_dev_put(dev);
 111                        pci_dev_put(pm_dev);
 112                        printk(KERN_WARNING "Could not allocate pm iobase resource\n");
 113                        iounmap(l440gx_map.virt);
 114                        return -ENXIO;
 115                }
 116        }
 117        /* Set the iobase */
 118        iobase = pm_iobase->start;
 119        pci_write_config_dword(pm_dev, 0x40, iobase | 1);
 120
 121
 122        /* Set XBCS# */
 123        pci_read_config_word(dev, 0x4e, &word);
 124        word |= 0x4;
 125        pci_write_config_word(dev, 0x4e, word);
 126
 127        /* Supply write voltage to the chip */
 128        l440gx_set_vpp(&l440gx_map, 1);
 129
 130        /* Enable the gate on the WE line */
 131        outb(inb(TRIBUF_PORT) & ~1, TRIBUF_PORT);
 132
 133        printk(KERN_NOTICE "Enabled WE line to L440GX BIOS flash chip.\n");
 134
 135        mymtd = do_map_probe("jedec_probe", &l440gx_map);
 136        if (!mymtd) {
 137                printk(KERN_NOTICE "JEDEC probe on BIOS chip failed. Using ROM\n");
 138                mymtd = do_map_probe("map_rom", &l440gx_map);
 139        }
 140        if (mymtd) {
 141                mymtd->owner = THIS_MODULE;
 142
 143                add_mtd_device(mymtd);
 144                return 0;
 145        }
 146
 147        iounmap(l440gx_map.virt);
 148        return -ENXIO;
 149}
 150
 151static void __exit cleanup_l440gx(void)
 152{
 153        del_mtd_device(mymtd);
 154        map_destroy(mymtd);
 155
 156        iounmap(l440gx_map.virt);
 157}
 158
 159module_init(init_l440gx);
 160module_exit(cleanup_l440gx);
 161
 162MODULE_LICENSE("GPL");
 163MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
 164MODULE_DESCRIPTION("MTD map driver for BIOS chips on Intel L440GX motherboards");
 165
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.