|
@@ -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;
|
|
|
}
|