// SPDX-License-Identifier: Apache-2.0
/*
 * Copyright (C) 2021 Gwenhael Goavec-Merou <gwenhael.goavec-merou@trabucayre.com>
 */

#ifndef SRC_SPIFLASHDB_HPP_
#define SRC_SPIFLASHDB_HPP_

#include <stdint.h>

#include <map>
#include <string>

typedef enum {
	STATR   = 0,  /* status register */
	FUNCR   = 1,  /* function register */
	CONFR   = 2,  /* configuration register */
	NVCONFR = 3,  /* Nonvolatile configuration register */
	NONER   = 99, /* "none" register */
} tb_loc_t;

typedef struct {
	std::string manufacturer; /**< manufacturer name */
	std::string model;        /**< chip name */
	uint32_t nr_sector;       /**< number of sectors */
	bool sector_erase;        /**< 64KB erase support */
	/* missing 32KB erase */
	bool subsector_erase;     /**< 4KB erase support */
	bool has_extended;
	bool tb_otp;              /**< TOP/BOTTOM One Time Programming */
	uint16_t tb_offset;       /**< TOP/BOTTOM bit offset */
	tb_loc_t tb_register;     /**< TOP/BOTTOM location (register) */
	uint8_t bp_len;           /**< BPx length */
	uint8_t bp_offset[4];     /**< BP[0:3] bit offset */
	tb_loc_t quad_register;   /**< TOP/BOTTOM bit offset */
	uint16_t quad_mask;       /** Quad Enable bit offset */
	bool global_lock;         /** Global lock/unlock bit */
} flash_t;

static std::map <uint32_t, flash_t> flash_list = {
	{0x010216, {
		.manufacturer = "spansion",
		.model = "S25FL064P / EPCS64",
		.nr_sector = 128,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = CONFR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x010219, {
		/* https://www.mouser.fr/datasheet/2/196/Infineon_S25FL128SS25FL256S_128_Mb__16_MB_256_Mb__-3363490.pdf */
		.manufacturer = "spansion",
		.model = "S25FL256S",
		.nr_sector = 512,
		.sector_erase = true,
		.subsector_erase = false,
		.has_extended = true,
		.tb_otp = true,
		.tb_offset = (1 << 5),
		.tb_register = CONFR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		.quad_register = CONFR,
		.quad_mask = (1 << 1),
		.global_lock = false,
	}},
	{0x010220, {
		.manufacturer = "spansion",
		.model = "S25FL512S",
		.nr_sector = 1024,
		.sector_erase = true,
		.subsector_erase = false,
		.has_extended = true,
		.tb_otp = true,
		.tb_offset = (1 << 5),
		.tb_register = CONFR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x012018, {
		.manufacturer = "spansion",
		.model = "S25FL128S",
		.nr_sector = 256,
		.sector_erase = true,
		.subsector_erase = false,
		.has_extended = true,
		.tb_otp = true,
		.tb_offset = (1 << 5),
		.tb_register = CONFR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		.quad_register = CONFR,
		.quad_mask = (1 << 1),
		.global_lock = false,
	}},
	{0x016018, {
		/* https://www.infineon.com/dgdl/Infineon-S25FL128L_S25FL256L_128_Mb_16_MB_256_Mb_32_MB_FL-L_flash_SPI_multi-I_O_3-DataSheet-v13_00-EN.pdf?fileId=8ac78c8c7d0d8da4017d0ed40e335224 */
		.manufacturer = "spansion",
		.model = "S25FL128L",
		.nr_sector = 256,
		.sector_erase = true,
		.subsector_erase = false,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 6),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x016019, {
		.manufacturer = "spansion",
		.model = "S25FL256L",
		.nr_sector = 512,
		.sector_erase = true,
		.subsector_erase = false,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 6),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x0b4016, {
		/* https://datasheet.lcsc.com/lcsc/2005251035_XTX-XT25F32BSOIGU-S_C558851.pdf */
		.manufacturer = "XTX",
		.model = "XT25F32B-S",
		.nr_sector = 1024,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = false,
		.tb_offset = (1 << 14),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x202014, {
		/* https://pdf1.alldatasheet.com/datasheet-pdf/download/22807/STMICROELECTRONICS/M25P80.html */
		.manufacturer = "ST",
		.model = "M25P80",
		.nr_sector = 16,
		.sector_erase = true,
		.subsector_erase = false,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = 0, // unused
		.tb_register = STATR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x202015, {
		/* https://datasheet.octopart.com/M25P16-VME6G-STMicroelectronics-datasheet-7623188.pdf */
		.manufacturer = "ST",
		.model = "M25P16",
		.nr_sector = 32,
		.sector_erase = true,
		.subsector_erase = false,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = 0, // unused
		.tb_register = STATR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x202016, {
		/* https://pdf1.alldatasheet.com/datasheet-pdf/download/104949/STMICROELECTRONICS/M25P32.html */
		.manufacturer = "ST",
		.model = "M25P32",
		.nr_sector = 64,
		.sector_erase = true,
		.subsector_erase = false,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = 0, // unused
		.tb_register = STATR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x20ba16, {
		/* https://www.digikey.co.uk/htmldatasheets/production/1283198/0/0/1/N25Q032A-32Mb-1-8V.pdf */
		.manufacturer = "micron",
		.model = "N25Q32",
		.nr_sector = 64,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		// Disabled because the chip is unable to work in single after being confgured in quad
		// this option isn't required and the chip is always able to uses quad mode instructions
		.quad_register = NONER,
		.quad_mask = 0,
		//.quad_register = NVCONFR,
		//.quad_mask = (1 << 3),
		.global_lock = false,
	}},
	{0x20ba17, {
		.manufacturer = "micron",
		.model = "N25Q64",
		.nr_sector = 128,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
		// Disabled because the chip is unable to work in single after being confgured in quad
		// this option isn't required and the chip is always able to uses quad mode instructions
		.quad_register = NONER,
		.quad_mask = 0,
		//.quad_register = NVCONFR,
		//.quad_mask = (1 << 3),
		.global_lock = false,
	}},
	{0x20ba18, {
		/* https://media-www.micron.com/-/media/client/global/documents/products/data-sheet/nor-flash/serial-nor/n25q/n25q_128mb_3v_65nm.pdf */
		.manufacturer = "micron",
		.model = "N25Q128_3V",
		.nr_sector = 256,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
		// Disabled because the chip is unable to work in single after being confgured in quad
		// this option isn't required and the chip is always able to uses quad mode instructions
		.quad_register = NONER,
		.quad_mask = 0,
		//.quad_register = NVCONFR,
		//.quad_mask = (1 << 3),
		.global_lock = false,
	}},
	{0x20ba19, {
		/* https://datasheet.octopart.com/N25Q256A13E1241F-Micron-datasheet-11552757.pdf */
		.manufacturer = "micron",
		.model = "N25Q256",
		.nr_sector = 512,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
		// Disabled because the chip is unable to work in single after being confgured in quad
		// this option isn't required and the chip is always able to uses quad mode instructions
		.quad_register = NONER,
		.quad_mask = 0,
		//.quad_register = NVCONFR,
		//.quad_mask = (1 << 3),
		.global_lock = false,
	}},
	{0x20bb18, {
		/* https://www.micron.com/-/media/client/global/documents/products/data-sheet/nor-flash/serial-nor/n25q/n25q_128mb_1_8v_65nm.pdf */
		/* MT25QU128ABA has the same JEDEC-standard signature: https://media-www.micron.com/-/media/client/global/documents/products/data-sheet/nor-flash/serial-nor/mt25q/die-rev-a/mt25q_qlhs_u_128_aba_0.pdf */
		/* Differences: https://media-www.micron.com/-/media/client/global/documents/products/technical-note/nor-flash/tn2501_migrating_n25q_to_mt25ql.pdf */
		.manufacturer = "micron",
		.model = "MT25/N25Q128_1_8V",
		.nr_sector = 256,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x20bb19, {
		.manufacturer = "micron",
		.model = "N25Q256A",
		.nr_sector = 512,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x20bb20, {
		.manufacturer = "micron",
		.model = "MT25QU512",
		.nr_sector = 1024,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x20bb21, {
		.manufacturer = "micron",
		.model = "MT25QU01G",
		.nr_sector = 2048,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x20bb22, {
		.manufacturer = "micron",
		.model = "MT25QU02G",
		.nr_sector = 4096,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x9d6016, {
		.manufacturer = "ISSI",
		.model = "IS25LP032",
		.nr_sector = 64,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = (1 << 1),
		.tb_register = FUNCR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x9d6017, {
		.manufacturer = "ISSI",
		.model = "IS25LP064",
		.nr_sector = 128,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = (1 << 1),
		.tb_register = FUNCR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x9d6018, {
		.manufacturer = "ISSI",
		.model = "IS25LP128",
		.nr_sector = 256,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = (1 << 1),
		.tb_register = FUNCR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x9d6019, {
		/* https://www.issi.com/WW/pdf/IS25LP(WP)256D.pdf */
		.manufacturer = "ISSI",
		.model = "IS25LP256",
		.nr_sector = 512,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = (1 << 1),
		.tb_register = FUNCR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0xba6015, {
		.manufacturer = "Zetta",
		.model = "ZD25WQ16CSIGT",
		.nr_sector = 32,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0xbf258d, {
		.manufacturer = "microchip",
		.model = "SST25VF040B",
		.nr_sector = 8,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = false,
		.tb_offset = 0, // unused
		.tb_register = NONER,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0xbf2642, {
		.manufacturer = "microchip",
		.model = "SST26VF032B",
		.nr_sector = 64,
		.sector_erase = false,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = false,
		.tb_offset = 0, // unused
		.tb_register = NONER,
		.bp_len = 0,
		.bp_offset = {0, 0, 0, 0},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = true,
	}},
	{0xbf2643, {
		.manufacturer = "microchip",
		.model = "SST26VF064B",
		.nr_sector = 128,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = false,
		.tb_offset = 0, // unused
		.tb_register = NONER,
		.bp_len = 0,
		.bp_offset = {0, 0, 0, 0},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = true,
	}},
	{0xc22016, {
		/* https://www.macronix.com/Lists/Datasheet/Attachments/8933/MX25L3233F,%203V,%2032Mb,%20v1.7.pdf */
		.manufacturer = "Macronix",
		.model = "MX25L3233F",
		.nr_sector = 256,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = (1 << 3),
		.tb_register = CONFR,
		.bp_len = 5,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = STATR,
		.quad_mask = (1 << 6),
		.global_lock = false,
	}},
	{0xc22017, {
		/* https://www.macronix.com/Lists/Datasheet/Attachments/8554/MX25L1605D,%203V,%2016Mb,%20v1.5.pdf */
		.manufacturer = "Macronix",
		.model = "MX25L6405",
		.nr_sector = 128,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = 0,
		.tb_register = NONER,
		.bp_len = 5,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0xc22018, {
		/* https://www.macronix.com/Lists/Datasheet/Attachments/8934/MX25L12833F,%203V,%20128Mb,%20v1.0.pdf */
		.manufacturer = "Macronix",
		.model = "MX25L12833",
		.nr_sector = 256,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = (1 << 3),
		.tb_register = CONFR,
		.bp_len = 5,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = STATR,
		.quad_mask = (1 << 6),
		.global_lock = false,
	}},
	{0xc22019, {
		/* https://www.mxic.com.tw/Lists/Datasheet/Attachments/8906/MX25L25645G,%203V,%20256Mb,%20v2.0.pdf */
		.manufacturer = "Macronix",
		.model = "MX25L25645G",
		.nr_sector = 512,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = (1 << 3),
		.tb_register = CONFR,
		.bp_len = 5,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = STATR,
		.quad_mask = (1 << 6),
		.global_lock = false,
	}},
	{0xc2201a, {
		/* https://www.macronix.com/Lists/Datasheet/Attachments/8745/MX25L51245G,%203V,%20512Mb,%20v1.7.pdf */
		.manufacturer = "Macronix",
		.model = "MX25L51245G",
		.nr_sector = 1024,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = (1 << 3),
		.tb_register = CONFR,
		.bp_len = 5,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = STATR,
		.quad_mask = (1 << 6),
		.global_lock = false,
	}},	
	{0xc22537, {
		/* https://www.macronix.com/Lists/Datasheet/Attachments/8904/MX25U6432F,%201.8V,%2064Mb,%20v1.1.pdf */
		.manufacturer = "Macronix",
		.model = "MX25U6432F",
		.nr_sector = 128,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = (1 << 3),
		.tb_register = CONFR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = STATR,
		.quad_mask = (1 << 6),
		.global_lock = false,
	}},
	{0xc84016, {
		/* https://cdn.compacttool.ru/downloads/GD25Q32%20datasheet.pdf */
		.manufacturer = "GigaDevice",
		.model = "GD25Q32C",
		.nr_sector = 64,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = false,
		.tb_offset = (1 << 14),  // CMP
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = STATR,
		.quad_mask = (1 << 6),
		.global_lock = false,
	}},
	{0xc22817, {
		/* https://www.macronix.com/Lists/Datasheet/Attachments/8868/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.6.pdf */
		.manufacturer = "Macronix",
		.model = "MX25R6435F",
		.nr_sector = 128,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = (1 << 3),
		.tb_register = CONFR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0xc22314, {
		/* https://datasheet4u.com/pdf-down/M/X/2/MX25V8035F-MACRONIX.pdf */
		.manufacturer = "Macronix",
		.model = "MX25V8035F",
		.nr_sector = 16,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = true,
		.tb_offset = (1 << 3),
		.tb_register = CONFR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 5)},
		.quad_register = STATR,
		.quad_mask = (1 << 6),
		.global_lock = false,
	}},
	{0xef4014, {
		/* https://cdn-shop.adafruit.com/datasheets/W25Q80BV.pdf */
		.manufacturer = "Winbond",
		.model = "W25Q80BV",
		.nr_sector = 16,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0xef4015, {
		.manufacturer = "Winbond",
		.model = "W25Q16",
		.nr_sector = 32,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0xef4016, {
		.manufacturer = "Winbond",
		.model = "W25Q32",
		.nr_sector = 64,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0xef4017, {
		.manufacturer = "Winbond",
		.model = "W25Q64",
		.nr_sector = 128,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0xef4018, {
		.manufacturer = "Winbond",
		.model = "W25Q128",
		.nr_sector = 256,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x6bbb14, {
		.manufacturer = "Everspin",
		.model = "EM008LX",
		.nr_sector = 16,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x6bbb15, {
		.manufacturer = "Everspin",
		.model = "EM016LX",
		.nr_sector = 32,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x6bbb16, {
		.manufacturer = "Everspin",
		.model = "EM032LX",
		.nr_sector = 64,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x6bbb17, {
		.manufacturer = "Everspin",
		.model = "EM064LX",
		.nr_sector = 128,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = true,
		.tb_otp = false,
		.tb_offset = (1 << 5),
		.tb_register = STATR,
		.bp_len = 4,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), (1 << 6)},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
	{0x1f4216, {
		.manufacturer = "Renesas",
		.model = "AT25QL321",
		.nr_sector = 64,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = false,
		.tb_offset = 0, // unused
		.tb_register = NONER,
		.bp_len = 0, // unused
		.bp_offset =  {0, 0, 0, 0},
		.quad_register = CONFR,
		.quad_mask = (1 << 1),
		.global_lock = false,
	}},
	{0x1f4701, {
		.manufacturer = "Adesto",
		.model = "AT25DF321A",
		.nr_sector = 64,
		.sector_erase = true,
		.subsector_erase = true,
		.has_extended = false,
		.tb_otp = false,
		.tb_offset = (1 << 3),
		.tb_register = STATR,
		.bp_len = 3,
		.bp_offset = {(1 << 2), (1 << 3), (1 << 4), 0},
		.quad_register = NONER,
		.quad_mask = 0,
		.global_lock = false,
	}},
};

#endif  // SRC_SPIFLASHDB_HPP_
