[flashrom] [PATCH] [rfc/demo] implementation of the Thinkpad T20/T21/T22 host

Michael Karcher flashrom at mkarcher.dialup.fu-berlin.de
Sat Jan 16 13:54:49 CET 2010


This mainboard uses external pins for banking the ROM chip, which seems
to be impossible to do with the "internal" programmer, yet I had to clone
most of the init stuff from internal.c . Hints for a clean implementation
will be appreciated.
---
 Makefile   |    2 +-
 flash.h    |   11 ++++++
 flashrom.c |   19 ++++++++++
 t20.c      |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 139 insertions(+), 1 deletions(-)
 create mode 100644 t20.c

diff --git a/Makefile b/Makefile
index 501f65a..cdd45d1 100644
--- a/Makefile
+++ b/Makefile
@@ -101,7 +101,7 @@ CONFIG_PRINT_WIKI ?= no
 
 ifeq ($(CONFIG_INTERNAL), yes)
 FEATURE_CFLAGS += -D'INTERNAL_SUPPORT=1'
-PROGRAMMER_OBJS += chipset_enable.o board_enable.o cbtable.o it87spi.o ichspi.o sb600spi.o wbsio_spi.o
+PROGRAMMER_OBJS += chipset_enable.o board_enable.o cbtable.o it87spi.o ichspi.o sb600spi.o t20.o wbsio_spi.o
 NEED_PCI := yes
 endif
 
diff --git a/flash.h b/flash.h
index 9a25c70..77b0d48 100644
--- a/flash.h
+++ b/flash.h
@@ -58,6 +58,9 @@ enum programmer {
 #if INTERNAL_SUPPORT == 1
 	PROGRAMMER_IT87SPI,
 #endif
+#if INTERNAL_SUPPORT == 1
+	PROGRAMMER_TPT20,
+#endif
 #if FT2232_SPI_SUPPORT == 1
 	PROGRAMMER_FT2232SPI,
 #endif
@@ -435,6 +438,14 @@ uint8_t drkaiser_chip_readb(const chipaddr addr);
 extern struct pcidev_status drkaiser_pcidev[];
 #endif
 
+/* t20.c */
+#if INTERNAL_SUPPORT == 1
+int t20_init(void);
+int t20_shutdown(void);
+void t20_chip_writeb(uint8_t val, chipaddr addr);
+uint8_t t20_chip_readb(const chipaddr addr);
+#endif
+
 /* satasii.c */
 #if SATASII_SUPPORT == 1
 int satasii_init(void);
diff --git a/flashrom.c b/flashrom.c
index db44c2f..7f05eeb 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -226,6 +226,25 @@ const struct programmer_entry programmer_table[] = {
 	},
 #endif
 
+#if INTERNAL_SUPPORT == 1
+	{
+		.name			= "t20",
+		.init			= t20_init,
+		.shutdown		= t20_shutdown,
+		.map_flash_region	= fallback_map,
+		.unmap_flash_region	= fallback_unmap,
+		.chip_readb		= t20_chip_readb,
+		.chip_readw		= fallback_chip_readw,
+		.chip_readl		= fallback_chip_readl,
+		.chip_readn		= fallback_chip_readn,
+		.chip_writeb		= t20_chip_writeb,
+		.chip_writew		= fallback_chip_writew,
+		.chip_writel		= fallback_chip_writel,
+		.chip_writen		= fallback_chip_writen,
+		.delay			= internal_delay,
+	},
+#endif
+
 #if FT2232_SPI_SUPPORT == 1
 	{
 		.name			= "ft2232spi",
diff --git a/t20.c b/t20.c
new file mode 100644
index 0000000..d6841cc
--- /dev/null
+++ b/t20.c
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright (C) 2010 Michael Karcher <flashrom at mkarcher.dialup.fu-berlin.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+/* Base address of register IND1 in the Field IMGA in the DSDT */
+#define IMGA1_BASE 0x15EE
+
+#include "flash.h"
+
+static uint8_t *t20_base;
+
+#define MAX_COUNT 20
+
+static void imga1_mask(uint8_t index, uint8_t mask, uint8_t value)
+{
+	uint16_t temp;
+	int count = 0;
+	/* Be careful, as ACPI might use these registers too, so check
+	   that the index is still OK. */
+	do {
+		OUTB(index, IMGA1_BASE);
+		temp = INW(IMGA1_BASE);
+	}
+	while ((temp & 0xff) != index && ++count < MAX_COUNT);
+	if(count == MAX_COUNT)
+	{
+		printf("error: IMGA1 index stuck at %02x\n", temp & 0xff);
+		return;
+	}
+	temp &= ~(mask << 8);
+	temp |= (value & mask) << 8;
+	OUTW(temp, IMGA1_BASE);
+}
+
+int t20_init(void)
+{
+	pacc = pci_alloc();
+	pci_init(pacc);
+	pci_scan_bus(pacc);	/* We want to get the list of devices */
+	get_io_perms();
+	/* ID of the graphics chip in T20/T21/T22. The mainboards are
+	   identical in these models */
+	if (!pci_card_find(0x5333, 0x8c12, 0x1014, 0x017f))
+	{
+		msg_perr("This is not a ThinkPad T20/T21/T22\n");
+		return 1;
+	}
+	if (chipset_flash_enable() == -2) {
+		printf("WARNING: No chipset found. Flash detection "
+		       "will most likely fail.\n");
+	}
+
+	imga1_mask(0, 4, 4);	/* Enable flash writes */
+	t20_base = physmap("IBM T20 mainboard flash", 0xFFFE0000, 0x20000);
+	buses_supported = CHIP_BUSTYPE_PARALLEL;
+	return 0;
+}
+
+int t20_shutdown(void)
+{
+	physunmap(t20_base, 0x20000);
+	imga1_mask(0, 4, 4);	/* Disable flash writes */
+	release_io_perms();
+	pci_cleanup(pacc);
+	return 0;
+}
+
+static unsigned int currentbank = -1U;
+
+static void switchtobank(unsigned int banknum)
+{
+	if (banknum > 3)
+	{
+		msg_perr("Bad bank number %d\n", banknum);
+		return;
+	}
+	if(banknum != currentbank)
+		imga1_mask(0, 3, banknum);
+	currentbank = banknum;
+}
+
+void t20_chip_writeb(uint8_t val, chipaddr addr)
+{
+	switchtobank(addr >> 17);
+	mmio_writeb(val, t20_base + (addr & 0x1FFFF));
+}
+
+uint8_t t20_chip_readb(chipaddr addr)
+{
+	switchtobank(addr >> 17);
+	return mmio_readb(t20_base + (addr & 0x1FFFF));
+}
-- 
1.6.5





More information about the flashrom mailing list