[PATCH] [MTD] MAPS: add support for ICH6/7/8 in ichxrom.c
Joey Ku (辜女育)
joey.ku at gmail.com
Fri Dec 1 02:29:06 EST 2006
[PATCH] [MTD] MAPS: add support for ICH6/7/8 in ichxrom.c
Add code to support ICH6/7/8
BTW, I don't have ICH7/8 machine for testing.
I guess it should work. :>
Signed-off-by: laface.tw at gmail.com
--
--- ichxrom.c.org 2006-11-30 16:56:49.000000000 +0800
+++ ichxrom.c 2006-12-01 15:02:21.086309768 +0800
@@ -26,11 +26,28 @@
#define ROM_PROBE_STEP_SIZE (64*1024) /* 64KiB */
-#define BIOS_CNTL 0x4e
-#define FWH_DEC_EN1 0xE3
-#define FWH_DEC_EN2 0xF0
-#define FWH_SEL1 0xE8
-#define FWH_SEL2 0xEE
+enum ichxrom_chip_type {
+ ICHXROM_ICH5 = 0,
+ ICHXROM_ICH6,
+};
+
+struct ichxrom_conf_reg_offset {
+ u8 bios_cntl;
+ u8 fwh_dec_en1;
+ u8 fwh_dec_en2;
+ u8 fwh_sel1;
+ u8 fwh_sel2;
+};
+
+struct ichxrom_chip_info {
+ struct pci_device_id pci_dev_id;
+ enum ichxrom_chip_type type;
+};
+
+struct ichxrom_chip {
+ struct ichxrom_conf_reg_offset reg_offset;
+ unsigned long (*setup_addr)(const struct ichxrom_chip *chip, struct
pci_dev *pdev);
+};
struct ichxrom_window {
void __iomem* virt;
@@ -39,6 +56,7 @@
struct list_head maps;
struct resource rsrc;
struct pci_dev *pdev;
+ const struct ichxrom_chip *chip;
};
struct ichxrom_map_info {
@@ -53,14 +71,79 @@
.maps = LIST_HEAD_INIT(ichxrom_window.maps),
};
+static unsigned long ichxrom_find_decode_region(u8 en1, u8 en2)
+{
+ unsigned long phys = 0;
+
+ if (en1 == 0xff) {
+ phys = 0xffc00000;
+ if ((en2 & 0x0f) == 0x0f) {
+ phys = 0xff400000;
+ }
+ else if ((en2 & 0x0e) == 0x0e) {
+ phys = 0xff500000;
+ }
+ else if ((en2 & 0x0c) == 0x0c) {
+ phys = 0xff600000;
+ }
+ else if ((en2 & 0x08) == 0x08) {
+ phys = 0xff700000;
+ }
+ }
+ else if ((en1 & 0xfe) == 0xfe) {
+ phys = 0xffc80000;
+ }
+ else if ((en1 & 0xfc) == 0xfc) {
+ phys = 0xffd00000;
+ }
+ else if ((en1 & 0xf8) == 0xf8) {
+ phys = 0xffd80000;
+ }
+ else if ((en1 & 0xf0) == 0xf0) {
+ phys = 0xffe00000;
+ }
+ else if ((en1 & 0xe0) == 0xe0) {
+ phys = 0xffe80000;
+ }
+ else if ((en1 & 0xc0) == 0xc0) {
+ phys = 0xfff00000;
+ }
+ else if ((en1 & 0x80) == 0x80) {
+ phys = 0xfff80000;
+ }
+
+ return phys;
+}
+
+static unsigned long ichxrom_ich5_setup_addr(const struct
ichxrom_chip *chip, struct pci_dev *pdev)
+{
+ u8 en1, en2;
+
+ pci_read_config_byte(pdev, chip->reg_offset.fwh_dec_en1, &en1);
+ pci_read_config_byte(pdev, chip->reg_offset.fwh_dec_en2, &en2);
+
+ return ichxrom_find_decode_region(en1, en2);
+}
+
+static unsigned long ichxrom_ich6_setup_addr(const struct
ichxrom_chip *chip, struct pci_dev *pdev)
+{
+ u16 word;
+
+ pci_read_config_word(pdev, chip->reg_offset.fwh_dec_en1, &word);
+
+ return ichxrom_find_decode_region((word>>8), (word&0x0f));
+}
+
static void ichxrom_cleanup(struct ichxrom_window *window)
{
struct ichxrom_map_info *map, *scratch;
u16 word;
/* Disable writes through the rom window */
- pci_read_config_word(window->pdev, BIOS_CNTL, &word);
- pci_write_config_word(window->pdev, BIOS_CNTL, word & ~1);
+ pci_read_config_word(window->pdev,
+ window->chip->reg_offset.bios_cntl, &word);
+ pci_write_config_word(window->pdev,
+ window->chip->reg_offset.bios_cntl, word & ~1);
pci_dev_put(window->pdev);
/* Free all of the mtd devices */
@@ -85,13 +168,12 @@
static int __devinit ichxrom_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+ const struct ichxrom_chip *chip)
{
static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
struct ichxrom_window *window = &ichxrom_window;
struct ichxrom_map_info *map = NULL;
unsigned long map_top;
- u8 byte;
u16 word;
/* For now I just handle the ichx and I assume there
@@ -105,47 +187,10 @@
* but don't currently handle that case either.
*/
window->pdev = pdev;
+ window->chip = chip;
/* Find a region continuous to the end of the ROM window */
- window->phys = 0;
- pci_read_config_byte(pdev, FWH_DEC_EN1, &byte);
- if (byte == 0xff) {
- window->phys = 0xffc00000;
- pci_read_config_byte(pdev, FWH_DEC_EN2, &byte);
- if ((byte & 0x0f) == 0x0f) {
- window->phys = 0xff400000;
- }
- else if ((byte & 0x0e) == 0x0e) {
- window->phys = 0xff500000;
- }
- else if ((byte & 0x0c) == 0x0c) {
- window->phys = 0xff600000;
- }
- else if ((byte & 0x08) == 0x08) {
- window->phys = 0xff700000;
- }
- }
- else if ((byte & 0xfe) == 0xfe) {
- window->phys = 0xffc80000;
- }
- else if ((byte & 0xfc) == 0xfc) {
- window->phys = 0xffd00000;
- }
- else if ((byte & 0xf8) == 0xf8) {
- window->phys = 0xffd80000;
- }
- else if ((byte & 0xf0) == 0xf0) {
- window->phys = 0xffe00000;
- }
- else if ((byte & 0xe0) == 0xe0) {
- window->phys = 0xffe80000;
- }
- else if ((byte & 0xc0) == 0xc0) {
- window->phys = 0xfff00000;
- }
- else if ((byte & 0x80) == 0x80) {
- window->phys = 0xfff80000;
- }
+ window->phys = chip->setup_addr(chip, pdev);
if (window->phys == 0) {
printk(KERN_ERR MOD_NAME ": Rom window is closed\n");
@@ -155,7 +200,7 @@
window->size = (0xffffffffUL - window->phys) + 1UL;
/* Enable writes through the rom window */
- pci_read_config_word(pdev, BIOS_CNTL, &word);
+ pci_read_config_word(pdev, chip->reg_offset.bios_cntl, &word);
if (!(word & 1) && (word & (1<<1))) {
/* The BIOS will generate an error if I enable
* this device, so don't even try.
@@ -163,7 +208,7 @@
printk(KERN_ERR MOD_NAME ": firmware access control, I can't enable
writes\n");
goto out;
}
- pci_write_config_word(pdev, BIOS_CNTL, word | 1);
+ pci_write_config_word(pdev, chip->reg_offset.bios_cntl, word | 1);
/*
* Try to reserve the window mem region. If this fails then
@@ -304,7 +349,6 @@
list_add(&map->list, &window->maps);
map = NULL;
}
-
out:
/* Free any left over map structures */
kfree(map);
@@ -317,25 +361,96 @@
return 0;
}
-
static void __devexit ichxrom_remove_one (struct pci_dev *pdev)
{
struct ichxrom_window *window = &ichxrom_window;
ichxrom_cleanup(window);
}
-static struct pci_device_id ichxrom_pci_tbl[] __devinitdata = {
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
- PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
- PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
- PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,
- PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
- PCI_ANY_ID, PCI_ANY_ID, },
- { 0, },
+const static const struct ichxrom_chip ichxrom_chip_tbl[] = {
+ [ICHXROM_ICH5] = {
+ .reg_offset = {
+ .bios_cntl = 0x4E,
+ .fwh_dec_en1 = 0xE3,
+ .fwh_dec_en2 = 0xF0,
+ .fwh_sel1 = 0xE8,
+ .fwh_sel2 = 0xEE
+ },
+ .setup_addr = ichxrom_ich5_setup_addr,
+ },
+
+ [ICHXROM_ICH6] = {
+ .reg_offset = {
+ .bios_cntl = 0xDC,
+ .fwh_dec_en1 = 0xD8,
+ .fwh_dec_en2 = 0x00, /* the register is not exist */
+ .fwh_sel1 = 0xD0,
+ .fwh_sel2 = 0xD4
+ },
+ .setup_addr = ichxrom_ich6_setup_addr,
+ }
+};
+
+static struct ichxrom_chip_info ichxrom_chip_probe_tbl[] __devinitdata = {
+ { .pci_dev_id = { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ .type = ICHXROM_ICH5,
+ },
+ { .pci_dev_id = { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ .type = ICHXROM_ICH5,
+ },
+ { .pci_dev_id = { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ .type = ICHXROM_ICH5,
+ },
+ { .pci_dev_id = { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ .type = ICHXROM_ICH5,
+ },
+ { .pci_dev_id = { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ .type = ICHXROM_ICH5,
+ },
+ { .pci_dev_id = { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0 ,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ .type = ICHXROM_ICH6,
+ },
+ { .pci_dev_id = { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1 ,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ .type = ICHXROM_ICH6,
+ },
+/* Not yet tested! It should work for ich7/8.
+ { .pci_dev_id = { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0 ,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ .type = ICHXROM_ICH6,
+ },
+ { .pci_dev_id = { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1 ,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ .type = ICHXROM_ICH6,
+ },
+ { .pci_dev_id = { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31 ,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ .type = ICHXROM_ICH6,
+ },
+ { .pci_dev_id = { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0 ,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ .type = ICHXROM_ICH6,
+ },
+ { .pci_dev_id = { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2 ,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ .type = ICHXROM_ICH6,
+ },
+ { .pci_dev_id = { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3 ,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ .type = ICHXROM_ICH6,
+ },
+ { .pci_dev_id = { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0 ,
+ PCI_ANY_ID, PCI_ANY_ID, },
+ .type = ICHXROM_ICH6,
+ },
+*/
+ { { 0 }, },
};
#if 0
@@ -352,18 +467,23 @@
static int __init init_ichxrom(void)
{
struct pci_dev *pdev;
- struct pci_device_id *id;
+ struct ichxrom_chip_info *chip;
pdev = NULL;
- for (id = ichxrom_pci_tbl; id->vendor; id++) {
- pdev = pci_get_device(id->vendor, id->device, NULL);
+
+ for (chip = ichxrom_chip_probe_tbl; chip->pci_dev_id.vendor ; chip++) {
+ pdev = pci_get_device(chip->pci_dev_id.vendor,
+ chip->pci_dev_id.device, NULL);
+
if (pdev) {
break;
}
+
}
if (pdev) {
- return ichxrom_init_one(pdev, &ichxrom_pci_tbl[0]);
+ return ichxrom_init_one(pdev, &ichxrom_chip_tbl[chip->type]);
}
+
return -ENXIO;
#if 0
return pci_register_driver(&ichxrom_driver);
More information about the linux-mtd
mailing list