summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/maps/ck804xrom.c89
1 files changed, 62 insertions, 27 deletions
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
index 688ef495888a..59d8fb49270a 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;
}
OpenPOWER on IntegriCloud