Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ck804xrom.c
0004  *
0005  * Normal mappings of chips in physical memory
0006  *
0007  * Dave Olsen <dolsen@lnxi.com>
0008  * Ryan Jackson <rjackson@lnxi.com>
0009  */
0010 
0011 #include <linux/module.h>
0012 #include <linux/types.h>
0013 #include <linux/kernel.h>
0014 #include <linux/init.h>
0015 #include <linux/slab.h>
0016 #include <asm/io.h>
0017 #include <linux/mtd/mtd.h>
0018 #include <linux/mtd/map.h>
0019 #include <linux/mtd/cfi.h>
0020 #include <linux/mtd/flashchip.h>
0021 #include <linux/pci.h>
0022 #include <linux/pci_ids.h>
0023 #include <linux/list.h>
0024 
0025 
0026 #define MOD_NAME KBUILD_BASENAME
0027 
0028 #define ADDRESS_NAME_LEN 18
0029 
0030 #define ROM_PROBE_STEP_SIZE (64*1024)
0031 
0032 #define DEV_CK804 1
0033 #define DEV_MCP55 2
0034 
0035 struct ck804xrom_window {
0036     void __iomem *virt;
0037     unsigned long phys;
0038     unsigned long size;
0039     struct list_head maps;
0040     struct resource rsrc;
0041     struct pci_dev *pdev;
0042 };
0043 
0044 struct ck804xrom_map_info {
0045     struct list_head list;
0046     struct map_info map;
0047     struct mtd_info *mtd;
0048     struct resource rsrc;
0049     char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
0050 };
0051 
0052 /*
0053  * The following applies to ck804 only:
0054  * The 2 bits controlling the window size are often set to allow reading
0055  * the BIOS, but too small to allow writing, since the lock registers are
0056  * 4MiB lower in the address space than the data.
0057  *
0058  * This is intended to prevent flashing the bios, perhaps accidentally.
0059  *
0060  * This parameter allows the normal driver to override the BIOS settings.
0061  *
0062  * The bits are 6 and 7.  If both bits are set, it is a 5MiB window.
0063  * If only the 7 Bit is set, it is a 4MiB window.  Otherwise, a
0064  * 64KiB window.
0065  *
0066  * The following applies to mcp55 only:
0067  * The 15 bits controlling the window size are distributed as follows: 
0068  * byte @0x88: bit 0..7
0069  * byte @0x8c: bit 8..15
0070  * word @0x90: bit 16..30
0071  * If all bits are enabled, we have a 16? MiB window
0072  * Please set win_size_bits to 0x7fffffff if you actually want to do something
0073  */
0074 static uint win_size_bits = 0;
0075 module_param(win_size_bits, uint, 0);
0076 MODULE_PARM_DESC(win_size_bits, "ROM window size bits override, normally set by BIOS.");
0077 
0078 static struct ck804xrom_window ck804xrom_window = {
0079     .maps = LIST_HEAD_INIT(ck804xrom_window.maps),
0080 };
0081 
0082 static void ck804xrom_cleanup(struct ck804xrom_window *window)
0083 {
0084     struct ck804xrom_map_info *map, *scratch;
0085     u8 byte;
0086 
0087     if (window->pdev) {
0088         /* Disable writes through the rom window */
0089         pci_read_config_byte(window->pdev, 0x6d, &byte);
0090         pci_write_config_byte(window->pdev, 0x6d, byte & ~1);
0091     }
0092 
0093     /* Free all of the mtd devices */
0094     list_for_each_entry_safe(map, scratch, &window->maps, list) {
0095         if (map->rsrc.parent)
0096             release_resource(&map->rsrc);
0097 
0098         mtd_device_unregister(map->mtd);
0099         map_destroy(map->mtd);
0100         list_del(&map->list);
0101         kfree(map);
0102     }
0103     if (window->rsrc.parent)
0104         release_resource(&window->rsrc);
0105 
0106     if (window->virt) {
0107         iounmap(window->virt);
0108         window->virt = NULL;
0109         window->phys = 0;
0110         window->size = 0;
0111     }
0112     pci_dev_put(window->pdev);
0113 }
0114 
0115 
0116 static int __init ck804xrom_init_one(struct pci_dev *pdev,
0117                      const struct pci_device_id *ent)
0118 {
0119     static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
0120     u8 byte;
0121     u16 word;
0122     struct ck804xrom_window *window = &ck804xrom_window;
0123     struct ck804xrom_map_info *map = NULL;
0124     unsigned long map_top;
0125 
0126     /* Remember the pci dev I find the window in */
0127     window->pdev = pci_dev_get(pdev);
0128 
0129     switch (ent->driver_data) {
0130     case DEV_CK804:
0131         /* Enable the selected rom window.  This is often incorrectly
0132          * set up by the BIOS, and the 4MiB offset for the lock registers
0133          * requires the full 5MiB of window space.
0134          *
0135          * This 'write, then read' approach leaves the bits for
0136          * other uses of the hardware info.
0137          */
0138         pci_read_config_byte(pdev, 0x88, &byte);
0139         pci_write_config_byte(pdev, 0x88, byte | win_size_bits );
0140 
0141         /* Assume the rom window is properly setup, and find it's size */
0142         pci_read_config_byte(pdev, 0x88, &byte);
0143 
0144         if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6)))
0145             window->phys = 0xffb00000; /* 5MiB */
0146         else if ((byte & (1<<7)) == (1<<7))
0147             window->phys = 0xffc00000; /* 4MiB */
0148         else
0149             window->phys = 0xffff0000; /* 64KiB */
0150         break;
0151 
0152     case DEV_MCP55:
0153         pci_read_config_byte(pdev, 0x88, &byte);
0154         pci_write_config_byte(pdev, 0x88, byte | (win_size_bits & 0xff));
0155 
0156         pci_read_config_byte(pdev, 0x8c, &byte);
0157         pci_write_config_byte(pdev, 0x8c, byte | ((win_size_bits & 0xff00) >> 8));
0158 
0159         pci_read_config_word(pdev, 0x90, &word);
0160         pci_write_config_word(pdev, 0x90, word | ((win_size_bits & 0x7fff0000) >> 16));
0161 
0162         window->phys = 0xff000000; /* 16MiB, hardcoded for now */
0163         break;
0164     }
0165 
0166     window->size = 0xffffffffUL - window->phys + 1UL;
0167 
0168     /*
0169      * Try to reserve the window mem region.  If this fails then
0170      * it is likely due to a fragment of the window being
0171      * "reserved" by the BIOS.  In the case that the
0172      * request_mem_region() fails then once the rom size is
0173      * discovered we will try to reserve the unreserved fragment.
0174      */
0175     window->rsrc.name = MOD_NAME;
0176     window->rsrc.start = window->phys;
0177     window->rsrc.end   = window->phys + window->size - 1;
0178     window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
0179     if (request_resource(&iomem_resource, &window->rsrc)) {
0180         window->rsrc.parent = NULL;
0181         printk(KERN_ERR MOD_NAME
0182                " %s(): Unable to register resource %pR - kernel bug?\n",
0183             __func__, &window->rsrc);
0184     }
0185 
0186 
0187     /* Enable writes through the rom window */
0188     pci_read_config_byte(pdev, 0x6d, &byte);
0189     pci_write_config_byte(pdev, 0x6d, byte | 1);
0190 
0191     /* FIXME handle registers 0x80 - 0x8C the bios region locks */
0192 
0193     /* For write accesses caches are useless */
0194     window->virt = ioremap(window->phys, window->size);
0195     if (!window->virt) {
0196         printk(KERN_ERR MOD_NAME ": ioremap(%08lx, %08lx) failed\n",
0197             window->phys, window->size);
0198         goto out;
0199     }
0200 
0201     /* Get the first address to look for a rom chip at */
0202     map_top = window->phys;
0203 #if 1
0204     /* The probe sequence run over the firmware hub lock
0205      * registers sets them to 0x7 (no access).
0206      * Probe at most the last 4MiB of the address space.
0207      */
0208     if (map_top < 0xffc00000)
0209         map_top = 0xffc00000;
0210 #endif
0211     /* Loop  through and look for rom chips.  Since we don't know the
0212      * starting address for each chip, probe every ROM_PROBE_STEP_SIZE
0213      * bytes from the starting address of the window.
0214      */
0215     while((map_top - 1) < 0xffffffffUL) {
0216         struct cfi_private *cfi;
0217         unsigned long offset;
0218         int i;
0219 
0220         if (!map) {
0221             map = kmalloc(sizeof(*map), GFP_KERNEL);
0222             if (!map)
0223                 goto out;
0224         }
0225         memset(map, 0, sizeof(*map));
0226         INIT_LIST_HEAD(&map->list);
0227         map->map.name = map->map_name;
0228         map->map.phys = map_top;
0229         offset = map_top - window->phys;
0230         map->map.virt = (void __iomem *)
0231             (((unsigned long)(window->virt)) + offset);
0232         map->map.size = 0xffffffffUL - map_top + 1UL;
0233         /* Set the name of the map to the address I am trying */
0234         sprintf(map->map_name, "%s @%08Lx",
0235             MOD_NAME, (unsigned long long)map->map.phys);
0236 
0237         /* There is no generic VPP support */
0238         for(map->map.bankwidth = 32; map->map.bankwidth;
0239             map->map.bankwidth >>= 1)
0240         {
0241             char **probe_type;
0242             /* Skip bankwidths that are not supported */
0243             if (!map_bankwidth_supported(map->map.bankwidth))
0244                 continue;
0245 
0246             /* Setup the map methods */
0247             simple_map_init(&map->map);
0248 
0249             /* Try all of the probe methods */
0250             probe_type = rom_probe_types;
0251             for(; *probe_type; probe_type++) {
0252                 map->mtd = do_map_probe(*probe_type, &map->map);
0253                 if (map->mtd)
0254                     goto found;
0255             }
0256         }
0257         map_top += ROM_PROBE_STEP_SIZE;
0258         continue;
0259     found:
0260         /* Trim the size if we are larger than the map */
0261         if (map->mtd->size > map->map.size) {
0262             printk(KERN_WARNING MOD_NAME
0263                 " rom(%llu) larger than window(%lu). fixing...\n",
0264                 (unsigned long long)map->mtd->size, map->map.size);
0265             map->mtd->size = map->map.size;
0266         }
0267         if (window->rsrc.parent) {
0268             /*
0269              * Registering the MTD device in iomem may not be possible
0270              * if there is a BIOS "reserved" and BUSY range.  If this
0271              * fails then continue anyway.
0272              */
0273             map->rsrc.name  = map->map_name;
0274             map->rsrc.start = map->map.phys;
0275             map->rsrc.end   = map->map.phys + map->mtd->size - 1;
0276             map->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
0277             if (request_resource(&window->rsrc, &map->rsrc)) {
0278                 printk(KERN_ERR MOD_NAME
0279                     ": cannot reserve MTD resource\n");
0280                 map->rsrc.parent = NULL;
0281             }
0282         }
0283 
0284         /* Make the whole region visible in the map */
0285         map->map.virt = window->virt;
0286         map->map.phys = window->phys;
0287         cfi = map->map.fldrv_priv;
0288         for(i = 0; i < cfi->numchips; i++)
0289             cfi->chips[i].start += offset;
0290 
0291         /* Now that the mtd devices is complete claim and export it */
0292         map->mtd->owner = THIS_MODULE;
0293         if (mtd_device_register(map->mtd, NULL, 0)) {
0294             map_destroy(map->mtd);
0295             map->mtd = NULL;
0296             goto out;
0297         }
0298 
0299 
0300         /* Calculate the new value of map_top */
0301         map_top += map->mtd->size;
0302 
0303         /* File away the map structure */
0304         list_add(&map->list, &window->maps);
0305         map = NULL;
0306     }
0307 
0308  out:
0309     /* Free any left over map structures */
0310     kfree(map);
0311 
0312     /* See if I have any map structures */
0313     if (list_empty(&window->maps)) {
0314         ck804xrom_cleanup(window);
0315         return -ENODEV;
0316     }
0317     return 0;
0318 }
0319 
0320 
0321 static void ck804xrom_remove_one(struct pci_dev *pdev)
0322 {
0323     struct ck804xrom_window *window = &ck804xrom_window;
0324 
0325     ck804xrom_cleanup(window);
0326 }
0327 
0328 static const struct pci_device_id ck804xrom_pci_tbl[] = {
0329     { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0051), .driver_data = DEV_CK804 },
0330     { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0360), .driver_data = DEV_MCP55 },
0331     { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0361), .driver_data = DEV_MCP55 },
0332     { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0362), .driver_data = DEV_MCP55 },
0333     { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0363), .driver_data = DEV_MCP55 },
0334     { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0364), .driver_data = DEV_MCP55 },
0335     { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0365), .driver_data = DEV_MCP55 },
0336     { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0366), .driver_data = DEV_MCP55 },
0337     { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, 0x0367), .driver_data = DEV_MCP55 },
0338     { 0, }
0339 };
0340 
0341 #if 0
0342 MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl);
0343 
0344 static struct pci_driver ck804xrom_driver = {
0345     .name =     MOD_NAME,
0346     .id_table = ck804xrom_pci_tbl,
0347     .probe =    ck804xrom_init_one,
0348     .remove =   ck804xrom_remove_one,
0349 };
0350 #endif
0351 
0352 static int __init init_ck804xrom(void)
0353 {
0354     struct pci_dev *pdev;
0355     const struct pci_device_id *id;
0356     int retVal;
0357     pdev = NULL;
0358 
0359     for(id = ck804xrom_pci_tbl; id->vendor; id++) {
0360         pdev = pci_get_device(id->vendor, id->device, NULL);
0361         if (pdev)
0362             break;
0363     }
0364     if (pdev) {
0365         retVal = ck804xrom_init_one(pdev, id);
0366         pci_dev_put(pdev);
0367         return retVal;
0368     }
0369     return -ENXIO;
0370 #if 0
0371     return pci_register_driver(&ck804xrom_driver);
0372 #endif
0373 }
0374 
0375 static void __exit cleanup_ck804xrom(void)
0376 {
0377     ck804xrom_remove_one(ck804xrom_window.pdev);
0378 }
0379 
0380 module_init(init_ck804xrom);
0381 module_exit(cleanup_ck804xrom);
0382 
0383 MODULE_LICENSE("GPL");
0384 MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>, Dave Olsen <dolsen@lnxi.com>");
0385 MODULE_DESCRIPTION("MTD map driver for BIOS chips on the Nvidia ck804 southbridge");
0386