aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2008-01-16 09:45:20 -0500
committerDavid Woodhouse <dwmw2@infradead.org>2008-04-22 13:11:35 -0400
commitc3f08b353519ee9c64308837199a9fcf83e863da (patch)
treee50b0fa304b93e2f1ff429e9a4108ecbf9902275
parent7fe9296c80e9a4ee51b43fbfbceb5143751a9d5c (diff)
[MTD] [MAPS] add support for Nvidia MCP55 to ck804xrom
This patch extends the existing MAPS driver for the Nvidia CK804 chipset (ck804xrom.c) to also work on the Nvidia MCP55 chipset. As both chipsets are rather similar, suporting them both with the same driver is easy. Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
-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 @@
28 28
29#define ROM_PROBE_STEP_SIZE (64*1024) 29#define ROM_PROBE_STEP_SIZE (64*1024)
30 30
31#define DEV_CK804 1
32#define DEV_MCP55 2
33
31struct ck804xrom_window { 34struct ck804xrom_window {
32 void __iomem *virt; 35 void __iomem *virt;
33 unsigned long phys; 36 unsigned long phys;
@@ -45,8 +48,9 @@ struct ck804xrom_map_info {
45 char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN]; 48 char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN];
46}; 49};
47 50
48 51/*
49/* The 2 bits controlling the window size are often set to allow reading 52 * The following applies to ck804 only:
53 * The 2 bits controlling the window size are often set to allow reading
50 * the BIOS, but too small to allow writing, since the lock registers are 54 * the BIOS, but too small to allow writing, since the lock registers are
51 * 4MiB lower in the address space than the data. 55 * 4MiB lower in the address space than the data.
52 * 56 *
@@ -58,10 +62,17 @@ struct ck804xrom_map_info {
58 * If only the 7 Bit is set, it is a 4MiB window. Otherwise, a 62 * If only the 7 Bit is set, it is a 4MiB window. Otherwise, a
59 * 64KiB window. 63 * 64KiB window.
60 * 64 *
65 * The following applies to mcp55 only:
66 * The 15 bits controlling the window size are distributed as follows:
67 * byte @0x88: bit 0..7
68 * byte @0x8c: bit 8..15
69 * word @0x90: bit 16..30
70 * If all bits are enabled, we have a 16? MiB window
71 * Please set win_size_bits to 0x7fffffff if you actually want to do something
61 */ 72 */
62static uint win_size_bits = 0; 73static uint win_size_bits = 0;
63module_param(win_size_bits, uint, 0); 74module_param(win_size_bits, uint, 0);
64MODULE_PARM_DESC(win_size_bits, "ROM window size bits override for 0x88 byte, normally set by BIOS."); 75MODULE_PARM_DESC(win_size_bits, "ROM window size bits override, normally set by BIOS.");
65 76
66static struct ck804xrom_window ck804xrom_window = { 77static struct ck804xrom_window ck804xrom_window = {
67 .maps = LIST_HEAD_INIT(ck804xrom_window.maps), 78 .maps = LIST_HEAD_INIT(ck804xrom_window.maps),
@@ -102,10 +113,11 @@ static void ck804xrom_cleanup(struct ck804xrom_window *window)
102 113
103 114
104static int __devinit ck804xrom_init_one (struct pci_dev *pdev, 115static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
105 const struct pci_device_id *ent) 116 const struct pci_device_id *ent)
106{ 117{
107 static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; 118 static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
108 u8 byte; 119 u8 byte;
120 u16 word;
109 struct ck804xrom_window *window = &ck804xrom_window; 121 struct ck804xrom_window *window = &ck804xrom_window;
110 struct ck804xrom_map_info *map = NULL; 122 struct ck804xrom_map_info *map = NULL;
111 unsigned long map_top; 123 unsigned long map_top;
@@ -113,26 +125,42 @@ static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
113 /* Remember the pci dev I find the window in */ 125 /* Remember the pci dev I find the window in */
114 window->pdev = pci_dev_get(pdev); 126 window->pdev = pci_dev_get(pdev);
115 127
116 /* Enable the selected rom window. This is often incorrectly 128 switch (ent->driver_data) {
117 * set up by the BIOS, and the 4MiB offset for the lock registers 129 case DEV_CK804:
118 * requires the full 5MiB of window space. 130 /* Enable the selected rom window. This is often incorrectly
119 * 131 * set up by the BIOS, and the 4MiB offset for the lock registers
120 * This 'write, then read' approach leaves the bits for 132 * requires the full 5MiB of window space.
121 * other uses of the hardware info. 133 *
122 */ 134 * This 'write, then read' approach leaves the bits for
123 pci_read_config_byte(pdev, 0x88, &byte); 135 * other uses of the hardware info.
124 pci_write_config_byte(pdev, 0x88, byte | win_size_bits ); 136 */
125 137 pci_read_config_byte(pdev, 0x88, &byte);
126 138 pci_write_config_byte(pdev, 0x88, byte | win_size_bits );
127 /* Assume the rom window is properly setup, and find it's size */ 139
128 pci_read_config_byte(pdev, 0x88, &byte); 140 /* Assume the rom window is properly setup, and find it's size */
129 141 pci_read_config_byte(pdev, 0x88, &byte);
130 if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) 142
131 window->phys = 0xffb00000; /* 5MiB */ 143 if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6)))
132 else if ((byte & (1<<7)) == (1<<7)) 144 window->phys = 0xffb00000; /* 5MiB */
133 window->phys = 0xffc00000; /* 4MiB */ 145 else if ((byte & (1<<7)) == (1<<7))
134 else 146 window->phys = 0xffc00000; /* 4MiB */
135 window->phys = 0xffff0000; /* 64KiB */ 147 else
148 window->phys = 0xffff0000; /* 64KiB */
149 break;
150
151 case DEV_MCP55:
152 pci_read_config_byte(pdev, 0x88, &byte);
153 pci_write_config_byte(pdev, 0x88, byte | (win_size_bits & 0xff));
154
155 pci_read_config_byte(pdev, 0x8c, &byte);
156 pci_write_config_byte(pdev, 0x8c, byte | ((win_size_bits & 0xff00) >> 8));
157
158 pci_read_config_word(pdev, 0x90, &word);
159 pci_write_config_word(pdev, 0x90, word | ((win_size_bits & 0x7fff0000) >> 16));
160
161 window->phys = 0xff000000; /* 16MiB, hardcoded for now */
162 break;
163 }
136 164
137 window->size = 0xffffffffUL - window->phys + 1UL; 165 window->size = 0xffffffffUL - window->phys + 1UL;
138 166
@@ -303,8 +331,15 @@ static void __devexit ck804xrom_remove_one (struct pci_dev *pdev)
303} 331}
304 332
305static struct pci_device_id ck804xrom_pci_tbl[] = { 333static struct pci_device_id ck804xrom_pci_tbl[] = {
306 { PCI_VENDOR_ID_NVIDIA, 0x0051, 334 { PCI_VENDOR_ID_NVIDIA, 0x0051, PCI_ANY_ID, PCI_ANY_ID, DEV_CK804 },
307 PCI_ANY_ID, PCI_ANY_ID, }, /* nvidia ck804 */ 335 { PCI_VENDOR_ID_NVIDIA, 0x0360, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
336 { PCI_VENDOR_ID_NVIDIA, 0x0361, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
337 { PCI_VENDOR_ID_NVIDIA, 0x0362, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
338 { PCI_VENDOR_ID_NVIDIA, 0x0363, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
339 { PCI_VENDOR_ID_NVIDIA, 0x0364, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
340 { PCI_VENDOR_ID_NVIDIA, 0x0365, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
341 { PCI_VENDOR_ID_NVIDIA, 0x0366, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
342 { PCI_VENDOR_ID_NVIDIA, 0x0367, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 },
308 { 0, } 343 { 0, }
309}; 344};
310 345
@@ -332,7 +367,7 @@ static int __init init_ck804xrom(void)
332 break; 367 break;
333 } 368 }
334 if (pdev) { 369 if (pdev) {
335 retVal = ck804xrom_init_one(pdev, &ck804xrom_pci_tbl[0]); 370 retVal = ck804xrom_init_one(pdev, id);
336 pci_dev_put(pdev); 371 pci_dev_put(pdev);
337 return retVal; 372 return retVal;
338 } 373 }