From ce5fad038d2802e6caec11da1bfc7dc9780e7ee5 Mon Sep 17 00:00:00 2001 From: Carl-Daniel Hailfinger Date: Thu, 18 Feb 2010 12:24:38 +0000 Subject: Refactor MCP SPI detection - Set supported buses based on ISA bridge reg 0x8a - Use MCP55 chipset enable only if LPC is detected - Allow LPC on MCP61 - Eliminate duplicated code where possible Corresponding to flashrom svn r906. Signed-off-by: Carl-Daniel Hailfinger Acked-by: Michael Karcher --- chipset_enable.c | 155 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 101 insertions(+), 54 deletions(-) diff --git a/chipset_enable.c b/chipset_enable.c index bb3fd7b..1830eb2 100644 --- a/chipset_enable.c +++ b/chipset_enable.c @@ -1054,31 +1054,41 @@ static int enable_flash_mcp55(struct pci_dev *dev, const char *name) return 0; } -/** - * The MCP67 code is guesswork based on cleanroom reverse engineering. - * Due to that, it only reads info and doesn't change any settings. - * It is assumed that LPC chips need the MCP55 code and SPI chips need the - * code provided in this function. Until we know for sure, call - * enable_flash_mcp55 from this function. Warning: enable_flash_mcp55 - * might make SPI flash inaccessible. The same caveat applies to SPI init - * for LPC flash. +/* This is a shot in the dark. Even if the code is totally bogus for some + * chipsets, users will at least start to send in reports. */ -static int enable_flash_mcp67(struct pci_dev *dev, const char *name) +static int enable_flash_mcp6x_7x_common(struct pci_dev *dev, const char *name) { - int result = 0; + int ret = 0; uint8_t byte; uint16_t status; + char *busname; uint32_t mcp_spibaraddr; void *mcp_spibar; struct pci_dev *smbusdev; + msg_pinfo("This chipset is not really supported yet. Guesswork...\n"); + /* dev is the ISA bridge. No idea what the stuff below does. */ byte = pci_read_byte(dev, 0x8a); - msg_pdbg("ISA bridge reg 0x8a contents: 0x%02x, bit 6 is %i, bit 5 is " - "%i\n", byte, (byte >> 6) & 0x1, (byte >> 5) & 0x1); - msg_pdbg("Guessed flash bus type is %s\n", ((byte >> 5) & 0x3) == 0x2 ? - "SPI" : "unknown, probably LPC"); - /* Disable the write code for now until we have more info. */ + msg_pdbg("ISA/LPC bridge reg 0x8a contents: 0x%02x, bit 6 is %i, bit 5 " + "is %i\n", byte, (byte >> 6) & 0x1, (byte >> 5) & 0x1); + switch ((byte >> 5) & 0x3) { + case 0x0: + buses_supported = CHIP_BUSTYPE_LPC; + break; + case 0x2: + buses_supported = CHIP_BUSTYPE_SPI; + break; + default: + buses_supported = CHIP_BUSTYPE_UNKNOWN; + break; + } + busname = flashbuses_to_text(buses_supported); + msg_pdbg("Guessed flash bus type is %s\n", busname); + free(busname); + + /* Force enable SPI and disable LPC? Not a good idea. */ #if 0 byte |= (1 << 6); byte &= ~(1 << 5); @@ -1088,8 +1098,15 @@ static int enable_flash_mcp67(struct pci_dev *dev, const char *name) /* Look for the SMBus device (SMBus PCI class) */ smbusdev = pci_dev_find_vendorclass(0x10de, 0x0c05); if (!smbusdev) { - msg_perr("ERROR: SMBus device not found. Aborting.\n"); - exit(1); + if (buses_supported & CHIP_BUSTYPE_SPI) { + msg_perr("ERROR: SMBus device not found. Not enabling " + "SPI.\n"); + buses_supported &= ~CHIP_BUSTYPE_SPI; + ret = 1; + } else { + msg_pinfo("Odd. SMBus device not found.\n"); + } + goto out_msg; } msg_pdbg("Found SMBus device %04x:%04x at %02x:%02x:%01x\n", smbusdev->vendor_id, smbusdev->device_id, @@ -1108,7 +1125,7 @@ static int enable_flash_mcp67(struct pci_dev *dev, const char *name) msg_pdbg("after clearing low bits BAR is at 0x%08x\n", mcp_spibaraddr); /* Accessing a NULL pointer BAR is evil. Don't do it. */ - if (mcp_spibaraddr) { + if (mcp_spibaraddr && (buses_supported == CHIP_BUSTYPE_SPI)) { /* Map the BAR. Bytewise/wordwise access at 0x530 and 0x540. */ mcp_spibar = physmap("MCP67 SPI", mcp_spibaraddr, 0x544); @@ -1125,54 +1142,84 @@ static int enable_flash_mcp67(struct pci_dev *dev, const char *name) status, status & 0x1, (status >> 8) & 0x1); /* FIXME: Remove the physunmap once the SPI driver exists. */ physunmap(mcp_spibar, 0x544); + } else if (!mcp_spibaraddr && (buses_supported & CHIP_BUSTYPE_SPI)) { + msg_pdbg("Strange. MCP SPI BAR is invalid.\n"); + buses_supported &= ~CHIP_BUSTYPE_SPI; + ret = 1; + } else if (mcp_spibaraddr && !(buses_supported & CHIP_BUSTYPE_SPI)) { + msg_pdbg("Strange. MCP SPI BAR is valid, but chipset apparently" + " doesn't have SPI enabled.\n"); } else { - msg_pdbg("Strange. MCP67 SPI BAR is invalid.\n"); + msg_pdbg("MCP SPI is not used.\n"); } +out_msg: msg_pinfo("Please send the output of \"flashrom -V\" to " "flashrom@flashrom.org to help us finish support for your " "chipset. Thanks.\n"); - /* Not sure if this is still correct. No docs as usual. */ - result = enable_flash_mcp55(dev, name); - - return result; + return ret; } -/* This is a shot in the dark. Even if the code is totally bogus for some - * chipsets, users will at least start to send in reports. +/** + * The MCP61/MCP67 code is guesswork based on cleanroom reverse engineering. + * Due to that, it only reads info and doesn't change any settings. + * It is assumed that LPC chips need the MCP55 code and SPI chips need the + * code provided in enable_flash_mcp6x_7x_common. Until we know for sure, call + * enable_flash_mcp55 from this function only if enable_flash_mcp6x_7x_common + * indicates the flash chip is LPC. Warning: enable_flash_mcp55 + * might make SPI flash inaccessible. The same caveat applies to SPI init + * for LPC flash. */ -static int enable_flash_mcp7x(struct pci_dev *dev, const char *name) +static int enable_flash_mcp67(struct pci_dev *dev, const char *name) { - uint8_t byte; - uint32_t mcp_spibaraddr; - struct pci_dev *smbusdev; - - msg_pinfo("This chipset is not really supported yet. Guesswork...\n"); + int result = 0; - /* dev is the ISA bridge. No idea what the stuff below does. */ - byte = pci_read_byte(dev, 0x8a); - msg_pdbg("ISA/LPC bridge reg 0x8a contents: 0x%02x, bit 6 is %i, bit 5 " - "is %i\n", byte, (byte >> 6) & 0x1, (byte >> 5) & 0x1); + result = enable_flash_mcp6x_7x_common(dev, name); + if (result) + return result; - /* Look for the SMBus device (SMBus PCI class) */ - smbusdev = pci_dev_find_vendorclass(0x10de, 0x0c05); - if (!smbusdev) { - msg_perr("ERROR: SMBus device not found. Aborting.\n"); - exit(1); + /* Not sure if this is correct. No docs as usual. */ + switch (buses_supported) { + case CHIP_BUSTYPE_LPC: + result = enable_flash_mcp55(dev, name); + break; + case CHIP_BUSTYPE_SPI: + msg_pinfo("SPI on this chipset is not supported yet.\n"); + buses_supported = CHIP_BUSTYPE_NONE; + break; + default: + msg_pinfo("Something went wrong with bus type detection.\n"); + buses_supported = CHIP_BUSTYPE_NONE; + break; } - msg_pdbg("Found SMBus device %04x:%04x at %02x:%02x:%01x\n", - smbusdev->vendor_id, smbusdev->device_id, - smbusdev->bus, smbusdev->dev, smbusdev->func); - /* Locate the BAR where the SPI interface lives. */ - mcp_spibaraddr = pci_read_long(smbusdev, 0x74); - msg_pdbg("SPI BAR is at 0x%08x, ", mcp_spibaraddr); + return result; +} - msg_pinfo("Please send the output of \"flashrom -V\" to " - "flashrom@flashrom.org to help us finish support for your " - "chipset. Thanks.\n"); +static int enable_flash_mcp7x(struct pci_dev *dev, const char *name) +{ + int result = 0; - return 0; + result = enable_flash_mcp6x_7x_common(dev, name); + if (result) + return result; + + /* Not sure if this is correct. No docs as usual. */ + switch (buses_supported) { + case CHIP_BUSTYPE_LPC: + msg_pinfo("LPC on this chipset is not supported yet.\n"); + break; + case CHIP_BUSTYPE_SPI: + msg_pinfo("SPI on this chipset is not supported yet.\n"); + buses_supported = CHIP_BUSTYPE_NONE; + break; + default: + msg_pinfo("Something went wrong with bus type detection.\n"); + buses_supported = CHIP_BUSTYPE_NONE; + break; + } + + return result; } static int enable_flash_ht1000(struct pci_dev *dev, const char *name) @@ -1314,10 +1361,10 @@ const struct penable chipset_enables[] = { {0x10de, 0x0365, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* LPC */ {0x10de, 0x0366, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* LPC */ {0x10de, 0x0367, OK, "NVIDIA", "MCP55", enable_flash_mcp55}, /* Pro */ - {0x10de, 0x03e0, NT, "NVIDIA", "MCP61", enable_flash_mcp7x}, - {0x10de, 0x03e1, NT, "NVIDIA", "MCP61", enable_flash_mcp7x}, - {0x10de, 0x03e2, NT, "NVIDIA", "MCP61", enable_flash_mcp7x}, - {0x10de, 0x03e3, NT, "NVIDIA", "MCP61", enable_flash_mcp7x}, + {0x10de, 0x03e0, NT, "NVIDIA", "MCP61", enable_flash_mcp67}, + {0x10de, 0x03e1, NT, "NVIDIA", "MCP61", enable_flash_mcp67}, + {0x10de, 0x03e2, NT, "NVIDIA", "MCP61", enable_flash_mcp67}, + {0x10de, 0x03e3, NT, "NVIDIA", "MCP61", enable_flash_mcp67}, {0x10de, 0x0440, NT, "NVIDIA", "MCP65", enable_flash_mcp7x}, {0x10de, 0x0441, NT, "NVIDIA", "MCP65", enable_flash_mcp7x}, {0x10de, 0x0442, NT, "NVIDIA", "MCP65", enable_flash_mcp7x}, -- cgit v1.1