>From 3c1c3acc233443866db9285e3cee7cb615c829ac Mon Sep 17 00:00:00 2001
From: Stefan Tauner <stefan.tauner@student.tuwien.ac.at>
Date: Fri, 19 Aug 2011 10:52:20 +0200
Subject: [PATCH] [not for merge] ichspi: add prettyprinting and unlocking of PR registers

also, add "Sealed-case PC" to the list of non-laptop DMI chassis types.

Signed-off-by: Stefan Tauner <stefan.tauner@student.tuwien.ac.at>
---
 dmi.c    |    1 +
 ichspi.c |   67 +++++++++++++++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 54 insertions(+), 14 deletions(-)

diff --git a/dmi.c b/dmi.c
index 8f78376..5f64b94 100644
--- a/dmi.c
+++ b/dmi.c
@@ -81,6 +81,7 @@ static const struct {
 	{0x0e, 1, "Sub Notebook"},
 	{0x11, 0, "Main Server Chassis"},
 	{0x17, 0, "Rack Mount Chassis"},
+	{0x18, 0, "Sealed-case PC"}, /* used by Supermicro (X8SIE) */
 };
 
 #define DMI_COMMAND_LEN_MAX 260
diff --git a/ichspi.c b/ichspi.c
index 8b4210e..f9a1b82 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -69,10 +69,8 @@
 #define ICH9_REG_FREG0		0x54	/* 32 Bytes Flash Region 0 */
 
 #define ICH9_REG_PR0		0x74	/* 32 Bytes Protected Range 0 */
-#define ICH9_REG_PR1		0x78	/* 32 Bytes Protected Range 1 */
-#define ICH9_REG_PR2		0x7c	/* 32 Bytes Protected Range 2 */
-#define ICH9_REG_PR3		0x80	/* 32 Bytes Protected Range 3 */
-#define ICH9_REG_PR4		0x84	/* 32 Bytes Protected Range 4 */
+#define PR_WP_OFF		31	/* 31: write protection enable */
+#define PR_RP_OFF		15	/* 15: read protection enable */
 
 #define ICH9_REG_SSFS		0x90	/* 08 Bits */
 #define SSFS_SCIP_OFF		0	/* SPI Cycle In Progress */
@@ -1163,6 +1161,51 @@ static void do_ich9_spi_frap(uint32_t frap, int i)
 		    access_names[rwperms]);
 }
 
+	/* In contrast to FRAP and the master section of the descriptor the bits
+	 * in the PR registers have an inverted meaning. The bits in FRAP
+	 * indicate read and write access _grant_. Here they indicate read
+	 * and write _protection_ respectively. If both bits are 0 the address
+	 * bits are ignored.
+	 */
+#define ICH_PR_PERMS(pr)	(((~((pr) >> PR_RP_OFF) & 1) << 0) | \
+				 ((~((pr) >> PR_WP_OFF) & 1) << 1))
+
+static void prettyprint_ich9_reg_pr(int i)
+{
+	static const char *const access_names[4] = {
+		"locked", "read-only", "write-only", "read-write"
+	};
+	uint8_t off = ICH9_REG_PR0 + (i * 4);
+	uint32_t pr = mmio_readl(ich_spibar + off);
+	int rwperms = ICH_PR_PERMS(pr);
+
+	msg_pdbg("0x%02X: 0x%08x (PR%u", off, pr, i);
+	if (rwperms != 0x3)
+		msg_pdbg(")\n0x%08x-0x%08x is %s\n", (ICH_FREG_BASE(pr) << 12),
+			 (ICH_FREG_LIMIT(pr) << 12) | 0x0fff,
+			 access_names[rwperms]);
+	else
+		msg_pdbg(", unused)\n");
+}
+
+/* Set the read and write protection enable bits of PR register @i according to
+ * @read_prot and @write_prot. */
+static void ich8_set_pr(int i, int read_prot, int write_prot)
+{
+	void *addr = ich_spibar + ICH9_REG_PR0 + (i * 4);
+	uint32_t pr = mmio_readl(addr);
+
+	msg_gspew("PR%u is 0x%08x, ", i, pr);
+	pr &= ~((1 << PR_RP_OFF) | (1 << PR_WP_OFF));
+	if (read_prot)
+		pr |= (1 << PR_RP_OFF);
+	if (write_prot)
+		pr |= (1 << PR_WP_OFF);
+	msg_gspew("trying to set it to 0x%08x ", pr);
+	mmio_writel(pr, addr);
+	msg_gspew("resulted in 0x%08x.\n", mmio_readl(addr));
+}
+
 static const struct spi_programmer spi_programmer_ich7 = {
 	.type = SPI_CONTROLLER_ICH7,
 	.max_data_read = 64,
@@ -1279,16 +1322,12 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
 		for(i = 0; i < 5; i++)
 			do_ich9_spi_frap(tmp, i);
 
-		msg_pdbg("0x74: 0x%08x (PR0)\n",
-			     mmio_readl(ich_spibar + ICH9_REG_PR0));
-		msg_pdbg("0x78: 0x%08x (PR1)\n",
-			     mmio_readl(ich_spibar + ICH9_REG_PR1));
-		msg_pdbg("0x7C: 0x%08x (PR2)\n",
-			     mmio_readl(ich_spibar + ICH9_REG_PR2));
-		msg_pdbg("0x80: 0x%08x (PR3)\n",
-			     mmio_readl(ich_spibar + ICH9_REG_PR3));
-		msg_pdbg("0x84: 0x%08x (PR4)\n",
-			     mmio_readl(ich_spibar + ICH9_REG_PR4));
+		/* try to disable PR locks before printing them */
+		if (!ichspi_lock)
+			for(i = 0; i < 5; i++)
+				ich8_set_pr(i, 0, 0);
+		for(i = 0; i < 5; i++)
+			prettyprint_ich9_reg_pr(i);
 
 		tmp = mmio_readl(ich_spibar + ICH9_REG_SSFS);
 		msg_pdbg("0x90: 0x%02x (SSFS)\n", tmp & 0xff);
-- 
1.7.1

