Add support for Intel S33 series flash chips

This includes:
Bottom boot block:
* 16Mb/2MB:
  QB25F160S33B8, QB25F016S33B8, QH25F160S33B8, QH25F016S33B8
* 32Mb/4MB:
  QB25F320S33B8, QH25F320S33B8
* 64Mb/8MB:
  QB25F640S33B8, QH25F640S33B8

Top boot block:
* 16Mb/2MB:
  QB25F160S33T8, QB25F016S33T8, QH25F160S33T8, QH25F016S33T8
* 32Mb/4MB:
  QB25F320S33T8, QH25F320S33T8
* 64Mb/8MB:
  QB25F640S33T8, QH25F640S33T8

At least some seem to be marketed by other vendors (too?) but also with
Intel's vendor ID.

Besides a 0xC7 chip erase and a 0xD8 uniform 64kB block erase they
support also erasing the top/bottom 8 8kB blocks with opcode 0x40.
But since this command fails for all addresses outside those ranges,
it is not easily implemented with flashrom's current code base and
hence left out.

Corresponding to flashrom svn r1636.

Signed-off-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
Acked-by: Stefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
diff --git a/chipdrivers.h b/chipdrivers.h
index fe1e598..04ffda6 100644
--- a/chipdrivers.h
+++ b/chipdrivers.h
@@ -77,6 +77,8 @@
 int spi_disable_blockprotect_at25f512b(struct flashctx *flash);
 int spi_disable_blockprotect_at25fs010(struct flashctx *flash);
 int spi_disable_blockprotect_at25fs040(struct flashctx *flash);
+int spi_prettyprint_status_register_s33(struct flashctx *flash);
+int spi_disable_blockprotect_s33(struct flashctx *flash);
 int spi_prettyprint_status_register_sst25(struct flashctx *flash);
 int spi_prettyprint_status_register_sst25vf016(struct flashctx *flash);
 int spi_prettyprint_status_register_sst25vf040b(struct flashctx *flash);
diff --git a/flashchips.c b/flashchips.c
index 5e036ac..9dd045e 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -4422,6 +4422,240 @@
 
 	{
 		.vendor		= "Intel",
+		.name		= "25F160S33B8",
+		.bustype	= BUS_SPI,
+		.manufacture_id	= INTEL_ID,
+		.model_id	= INTEL_25F160S33B8,
+		.total_size	= 2048,
+		.page_size	= 256,
+		/* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */
+		.feature_bits	= FEATURE_WRSR_WREN | FEATURE_OTP,
+		.tested		= TEST_UNTESTED,
+		.probe		= probe_spi_rdid,
+		.probe_timing	= TIMING_ZERO,
+		.block_erasers	=
+		{
+			{
+				/* This chip supports erasing of the 8 so-called "parameter blocks" with
+				 * opcode 0x40. Trying to access an address outside these 8 8kB blocks does
+				 * have no effect on the memory contents, but sets a flag in the SR.
+				.eraseblocks = {
+					{8 * 1024, 8},
+					{64 * 1024, 31} // inaccessible
+				},
+				.block_erase = spi_block_erase_40,
+			}, { */
+				.eraseblocks = { {64 * 1024, 32} },
+				.block_erase = spi_block_erase_d8,
+			}, {
+				.eraseblocks = { {2 * 1024 * 1024, 1} },
+				.block_erase = spi_block_erase_c7,
+			}
+		},
+		.printlock	= spi_prettyprint_status_register_s33,
+		.unlock		= spi_disable_blockprotect_s33,
+		.write		= spi_chip_write_256,
+		.read		= spi_chip_read,	/* also fast read 0x0B */
+		.voltage	= {2700, 3600},
+	},
+
+	{
+		.vendor		= "Intel",
+		.name		= "25F160S33T8",
+		.bustype	= BUS_SPI,
+		.manufacture_id	= INTEL_ID,
+		.model_id	= INTEL_25F160S33T8,
+		.total_size	= 2048,
+		.page_size	= 256,
+		/* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */
+		.feature_bits	= FEATURE_WRSR_WREN | FEATURE_OTP,
+		.tested		= TEST_UNTESTED,
+		.probe		= probe_spi_rdid,
+		.probe_timing	= TIMING_ZERO,
+		.block_erasers	=
+		{
+			{
+				/* This chip supports erasing of the 8 so-called "parameter blocks" with
+				 * opcode 0x40. Trying to access an address outside these 8 8kB blocks does
+				 * have no effect on the memory contents, but sets a flag in the SR.
+				.eraseblocks = {
+					{64 * 1024, 31}, // inaccessible
+					{8 * 1024, 8}
+				},
+				.block_erase = spi_block_erase_40,
+			}, { */
+				.eraseblocks = { {64 * 1024, 32} },
+				.block_erase = spi_block_erase_d8,
+			}, {
+				.eraseblocks = { {2 * 1024 * 1024, 1} },
+				.block_erase = spi_block_erase_c7,
+			}
+		},
+		.printlock	= spi_prettyprint_status_register_s33,
+		.unlock		= spi_disable_blockprotect_s33,
+		.write		= spi_chip_write_256,
+		.read		= spi_chip_read,	/* also fast read 0x0B */
+		.voltage	= {2700, 3600},
+	},
+
+	{
+		.vendor		= "Intel",
+		.name		= "25F320S33B8",
+		.bustype	= BUS_SPI,
+		.manufacture_id	= INTEL_ID,
+		.model_id	= INTEL_25F320S33B8,
+		.total_size	= 4096,
+		.page_size	= 256,
+		/* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */
+		.feature_bits	= FEATURE_WRSR_WREN | FEATURE_OTP,
+		.tested		= TEST_UNTESTED,
+		.probe		= probe_spi_rdid,
+		.probe_timing	= TIMING_ZERO,
+		.block_erasers	=
+		{
+			{
+				/* This chip supports erasing of the 8 so-called "parameter blocks" with
+				 * opcode 0x40. Trying to access an address outside these 8 8kB blocks does
+				 * have no effect on the memory contents, but sets a flag in the SR.
+				.eraseblocks = {
+					{8 * 1024, 8},
+					{64 * 1024, 63} // inaccessible
+				},
+				.block_erase = spi_block_erase_40,
+			}, { */
+				.eraseblocks = { {64 * 1024, 64} },
+				.block_erase = spi_block_erase_d8,
+			}, {
+				.eraseblocks = { {4 * 1024 * 1024, 1} },
+				.block_erase = spi_block_erase_c7,
+			}
+		},
+		.printlock	= spi_prettyprint_status_register_s33,
+		.unlock		= spi_disable_blockprotect_s33,
+		.write		= spi_chip_write_256,
+		.read		= spi_chip_read,	/* also fast read 0x0B */
+		.voltage	= {2700, 3600},
+	},
+
+	{
+		.vendor		= "Intel",
+		.name		= "25F320S33T8",
+		.bustype	= BUS_SPI,
+		.manufacture_id	= INTEL_ID,
+		.model_id	= INTEL_25F320S33T8,
+		.total_size	= 4096,
+		.page_size	= 256,
+		/* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */
+		.feature_bits	= FEATURE_WRSR_WREN | FEATURE_OTP,
+		.tested		= TEST_UNTESTED,
+		.probe		= probe_spi_rdid,
+		.probe_timing	= TIMING_ZERO,
+		.block_erasers	=
+		{
+			{
+				/* This chip supports erasing of the 8 so-called "parameter blocks" with
+				 * opcode 0x40. Trying to access an address outside these 8 8kB blocks does
+				 * have no effect on the memory contents, but sets a flag in the SR.
+				.eraseblocks = {
+					{64 * 1024, 63}, // inaccessible
+					{8 * 1024, 8}
+				},
+				.block_erase = spi_block_erase_40,
+			}, { */
+				.eraseblocks = { {64 * 1024, 64} },
+				.block_erase = spi_block_erase_d8,
+			}, {
+				.eraseblocks = { {4 * 1024 * 1024, 1} },
+				.block_erase = spi_block_erase_c7,
+			}
+		},
+		.printlock	= spi_prettyprint_status_register_s33,
+		.unlock		= spi_disable_blockprotect_s33,
+		.write		= spi_chip_write_256,
+		.read		= spi_chip_read,	/* also fast read 0x0B */
+		.voltage	= {2700, 3600},
+	},
+
+	{
+		.vendor		= "Intel",
+		.name		= "25F640S33B8",
+		.bustype	= BUS_SPI,
+		.manufacture_id	= INTEL_ID,
+		.model_id	= INTEL_25F640S33B8,
+		.total_size	= 8192,
+		.page_size	= 256,
+		/* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */
+		.feature_bits	= FEATURE_WRSR_WREN | FEATURE_OTP,
+		.tested		= TEST_UNTESTED,
+		.probe		= probe_spi_rdid,
+		.probe_timing	= TIMING_ZERO,
+		.block_erasers	=
+		{
+			{
+				/* This chip supports erasing of the 8 so-called "parameter blocks" with
+				 * opcode 0x40. Trying to access an address outside these 8 8kB blocks does
+				 * have no effect on the memory contents, but sets a flag in the SR.
+				.eraseblocks = {
+					{8 * 1024, 8},
+					{64 * 1024, 127} // inaccessible
+				},
+				.block_erase = spi_block_erase_40,
+			}, { */
+				.eraseblocks = { {64 * 1024, 128} },
+				.block_erase = spi_block_erase_d8,
+			}, {
+				.eraseblocks = { {8 * 1024 * 1024, 1} },
+				.block_erase = spi_block_erase_c7,
+			}
+		},
+		.printlock	= spi_prettyprint_status_register_s33,
+		.unlock		= spi_disable_blockprotect_s33,
+		.write		= spi_chip_write_256,
+		.read		= spi_chip_read,	/* also fast read 0x0B */
+		.voltage	= {2700, 3600},
+	},
+
+	{
+		.vendor		= "Intel",
+		.name		= "25F640S33T8",
+		.bustype	= BUS_SPI,
+		.manufacture_id	= INTEL_ID,
+		.model_id	= INTEL_25F640S33T8,
+		.total_size	= 8192,
+		.page_size	= 256,
+		/* OTP: 506B total (2x 8B, 30x 16B, 1x 10B); read 0x4B; write 0x42 */
+		.feature_bits	= FEATURE_WRSR_WREN | FEATURE_OTP,
+		.tested		= TEST_UNTESTED,
+		.probe		= probe_spi_rdid,
+		.probe_timing	= TIMING_ZERO,
+		.block_erasers	=
+		{
+			{
+				/* This chip supports erasing of the 8 so-called "parameter blocks" with
+				 * opcode 0x40. Trying to access an address outside these 8 8kB blocks does
+				 * have no effect on the memory contents, but sets a flag in the SR.
+				.eraseblocks = {
+					{64 * 1024, 127}, // inaccessible
+					{8 * 1024, 8}
+				},
+				.block_erase = spi_block_erase_40,
+			}, { */
+				.eraseblocks = { {64 * 1024, 128} },
+				.block_erase = spi_block_erase_d8,
+			}, {
+				.eraseblocks = { {8 * 1024 * 1024, 1} },
+				.block_erase = spi_block_erase_c7,
+			}
+		},
+		.printlock	= spi_prettyprint_status_register_s33,
+		.unlock		= spi_disable_blockprotect_s33,
+		.write		= spi_chip_write_256,
+		.read		= spi_chip_read,	/* also fast read 0x0B */
+		.voltage	= {2700, 3600},
+	},
+
+	{
+		.vendor		= "Intel",
 		.name		= "28F001BN/BX-B",
 		.bustype	= BUS_PARALLEL,
 		.manufacture_id	= INTEL_ID,
diff --git a/flashchips.h b/flashchips.h
index f10fbae..073f4eb 100644
--- a/flashchips.h
+++ b/flashchips.h
@@ -364,6 +364,12 @@
 #define INTEL_28F008B3B		0xD3	/* 28F008B3-B */
 #define INTEL_28F004B3T		0xD4	/* 28F004B3-T */
 #define INTEL_28F004B3B		0xD5	/* 28F004B3-B */
+#define INTEL_25F160S33B8	0x8911	/* Same as 25F016S33B8 */
+#define INTEL_25F320S33B8	0x8912
+#define INTEL_25F640S33B8	0x8913
+#define INTEL_25F160S33T8	0x8915	/* Same as 25F016S33T8 */
+#define INTEL_25F320S33T8	0x8916
+#define INTEL_25F640S33T8	0x8917
 
 #define SHARP_LH28F008SA	0xA2	/* Sharp chip, Intel Vendor ID */
 #define SHARP_LH28F008SC	0xA6	/* Sharp chip, Intel Vendor ID */
diff --git a/spi25_statusreg.c b/spi25_statusreg.c
index 84e8f63..2e01c06 100644
--- a/spi25_statusreg.c
+++ b/spi25_statusreg.c
@@ -468,6 +468,29 @@
 	return spi_disable_blockprotect_generic(flash, 0x7C, 1 << 7, 0);
 }
 
+/* === Intel === */
+
+/* TODO: Clear P_FAIL and E_FAIL with Clear SR Fail Flags Command (30h) here? */
+int spi_disable_blockprotect_s33(struct flashctx *flash)
+{
+	return spi_disable_blockprotect_generic(flash, 0x1C, 1 << 7, 0);
+}
+
+int spi_prettyprint_status_register_s33(struct flashctx *flash)
+{
+	uint8_t status = spi_read_status_register(flash);
+	msg_cdbg("Chip status register is %02x\n", status);
+
+	spi_prettyprint_status_register_srwd(status);
+	msg_cdbg("Chip status register: Program Fail Flag (P_FAIL) is %sset\n",
+		 (status & (1 << 6)) ? "" : "not ");
+	msg_cdbg("Chip status register: Erase Fail Flag (E_FAIL) is %sset\n",
+		 (status & (1 << 5)) ? "" : "not ");
+	spi_prettyprint_status_register_bp(status, 2);
+	spi_prettyprint_status_register_welwip(status);
+	return 0;
+}
+
 /* === SST === */
 
 static void spi_prettyprint_status_register_sst25_common(uint8_t status)