diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/maps/ck804xrom.c | 89 |
1 files changed, 62 insertions, 27 deletions
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c index 688ef495888..59d8fb49270 100644 --- a/drivers/mtd/maps/ck804xrom.c +++ b/drivers/mtd/maps/ck804xrom.c @@ -28,6 +28,9 @@ #define ROM_PROBE_STEP_SIZE (64*1024) +#define DEV_CK804 1 +#define DEV_MCP55 2 + struct ck804xrom_window { void __iomem *virt; unsigned long phys; @@ -45,8 +48,9 @@ struct ck804xrom_map_info { char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN]; }; - -/* The 2 bits controlling the window size are often set to allow reading +/* + * The following applies to ck804 only: + * The 2 bits controlling the window size are often set to allow reading * the BIOS, but too small to allow writing, since the lock registers are * 4MiB lower in the address space than the data. * @@ -58,10 +62,17 @@ struct ck804xrom_map_info { * If only the 7 Bit is set, it is a 4MiB window. Otherwise, a * 64KiB window. * + * The following applies to mcp55 only: + * The 15 bits controlling the window size are distributed as follows: + * byte @0x88: bit 0..7 + * byte @0x8c: bit 8..15 + * word @0x90: bit 16..30 + * If all bits are enabled, we have a 16? MiB window + * Please set win_size_bits to 0x7fffffff if you actually want to do something */ static uint win_size_bits = 0; module_param(win_size_bits, uint, 0); -MODULE_PARM_DESC(win_size_bits, "ROM window size bits override for 0x88 byte, normally set by BIOS."); +MODULE_PARM_DESC(win_size_bits, "ROM window size bits override, normally set by BIOS."); static struct ck804xrom_window ck804xrom_window = { .maps = LIST_HEAD_INIT(ck804xrom_window.maps), @@ -102,10 +113,11 @@ static void ck804xrom_cleanup(struct ck804xrom_window *window) static int __devinit ck804xrom_init_one (struct pci_dev *pdev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; u8 byte; + u16 word; struct ck804xrom_window *window = &ck804xrom_window; struct ck804xrom_map_info *map = NULL; unsigned long map_top; @@ -113,26 +125,42 @@ static int __devinit ck804xrom_init_one (struct pci_dev *pdev, /* Remember the pci dev I find the window in */ window->pdev = pci_dev_get(pdev); - /* Enable the selected rom window. This is often incorrectly - * set up by the BIOS, and the 4MiB offset for the lock registers - * requires the full 5MiB of window space. - * - * This 'write, then read' approach leaves the bits for - * other uses of the hardware info. - */ - pci_read_config_byte(pdev, 0x88, &byte); - pci_write_config_byte(pdev, 0x88, byte | win_size_bits ); - - - /* Assume the rom window is properly setup, and find it's size */ - pci_read_config_byte(pdev, 0x88, &byte); - - if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) - window->phys = 0xffb00000; /* 5MiB */ - else if ((byte & (1<<7)) == (1<<7)) - window->phys = 0xffc00000; /* 4MiB */ - else - window->phys = 0xffff0000; /* 64KiB */ + switch (ent->driver_data) { + case DEV_CK804: + /* Enable the selected rom window. This is often incorrectly + * set up by the BIOS, and the 4MiB offset for the lock registers + * requires the full 5MiB of window space. + * + * This 'write, then read' approach leaves the bits for + * other uses of the hardware info. + */ + pci_read_config_byte(pdev, 0x88, &byte); + pci_write_config_byte(pdev, 0x88, byte | win_size_bits ); + + /* Assume the rom window is properly setup, and find it's size */ + pci_read_config_byte(pdev, 0x88, &byte); + + if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) + window->phys = 0xffb00000; /* 5MiB */ + else if ((byte & (1<<7)) == (1<<7)) + window->phys = 0xffc00000; /* 4MiB */ + else + window->phys = 0xffff0000; /* 64KiB */ + break; + + case DEV_MCP55: + pci_read_config_byte(pdev, 0x88, &byte); + pci_write_config_byte(pdev, 0x88, byte | (win_size_bits & 0xff)); + + pci_read_config_byte(pdev, 0x8c, &byte); + pci_write_config_byte(pdev, 0x8c, byte | ((win_size_bits & 0xff00) >> 8)); + + pci_read_config_word(pdev, 0x90, &word); + pci_write_config_word(pdev, 0x90, word | ((win_size_bits & 0x7fff0000) >> 16)); + + window->phys = 0xff000000; /* 16MiB, hardcoded for now */ + break; + } window->size = 0xffffffffUL - window->phys + 1UL; @@ -303,8 +331,15 @@ static void __devexit ck804xrom_remove_one (struct pci_dev *pdev) } static struct pci_device_id ck804xrom_pci_tbl[] = { - { PCI_VENDOR_ID_NVIDIA, 0x0051, - PCI_ANY_ID, PCI_ANY_ID, }, /* nvidia ck804 */ + { PCI_VENDOR_ID_NVIDIA, 0x0051, PCI_ANY_ID, PCI_ANY_ID, DEV_CK804 }, + { PCI_VENDOR_ID_NVIDIA, 0x0360, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, + { PCI_VENDOR_ID_NVIDIA, 0x0361, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, + { PCI_VENDOR_ID_NVIDIA, 0x0362, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, + { PCI_VENDOR_ID_NVIDIA, 0x0363, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, + { PCI_VENDOR_ID_NVIDIA, 0x0364, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, + { PCI_VENDOR_ID_NVIDIA, 0x0365, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, + { PCI_VENDOR_ID_NVIDIA, 0x0366, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, + { PCI_VENDOR_ID_NVIDIA, 0x0367, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, { 0, } }; @@ -332,7 +367,7 @@ static int __init init_ck804xrom(void) break; } if (pdev) { - retVal = ck804xrom_init_one(pdev, &ck804xrom_pci_tbl[0]); + retVal = ck804xrom_init_one(pdev, id); pci_dev_put(pdev); return retVal; } |