view loadtools/fldevs.c @ 1011:6d9b10633f10 default tip

etmsync Pirelli IMEI retrieval: fix poor use of printf() Bug reported by Vadim Yanitskiy <fixeria@osmocom.org>: the construct where a static-allocated string was passed to printf() without any format arguments causes newer compilers to report a security problem. Given that formatted output is not needed here, just fixed string output, change printf() to fputs(), and direct the error message to stderr while at it.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 23 May 2024 17:29:57 +0000
parents ad3041e19884
children
line wrap: on
line source

/*
 * This module holds the tables of supported flash devices
 */

#include <stdint.h>
#include "flash.h"

extern struct flash_cmdset flash_cmdset_amd;
extern struct flash_cmdset flash_cmdset_intel;
extern struct flash_cmdset flash_cmdset_intel_w30;

extern int plj_ppb_program_one();
extern int plj_ppb_program_all();
extern int plj_ppb_erase_all_single();
extern int plj_ppb_erase_all_dualbank();

extern int pln_ppb_program_one();
extern int pln_ppb_erase_all();

/* flash bank geometries */

static struct flash_geom geom_2M_topboot = {
	.total_size	= 0x200000,
	.nregions	= 2,
	.regions	= {0x10000, 31, 0x2000, 8},
	.total_sectors	= 39,
};

static struct flash_geom geom_2M_bottomboot = {
	.total_size	= 0x200000,
	.nregions	= 2,
	.regions	= {0x2000, 8, 0x10000, 31},
	.total_sectors	= 39,
};

static struct flash_geom geom_4M_topboot = {
	.total_size	= 0x400000,
	.nregions	= 2,
	.regions	= {0x10000, 63, 0x2000, 8},
	.total_sectors	= 71,
};

static struct flash_geom geom_4M_bottomboot = {
	.total_size	= 0x400000,
	.nregions	= 2,
	.regions	= {0x2000, 8, 0x10000, 63},
	.total_sectors	= 71,
};

static struct flash_geom geom_4M_bothends = {
	.total_size	= 0x400000,
	.nregions	= 3,
	.regions	= {0x2000, 8, 0x10000, 62, 0x2000, 8},
	.total_sectors	= 78,
};

static struct flash_geom geom_8M_topboot = {
	.total_size	= 0x800000,
	.nregions	= 2,
	.regions	= {0x10000, 127, 0x2000, 8},
	.total_sectors	= 135,
};

static struct flash_geom geom_8M_bottomboot = {
	.total_size	= 0x800000,
	.nregions	= 2,
	.regions	= {0x2000, 8, 0x10000, 127},
	.total_sectors	= 135,
};

static struct flash_geom geom_8M_bothends = {
	.total_size	= 0x800000,
	.nregions	= 3,
	.regions	= {0x2000, 8, 0x10000, 126, 0x2000, 8},
	.total_sectors	= 142,
};

static struct flash_geom geom_8M_topboot_big = {
	.total_size	= 0x800000,
	.nregions	= 2,
	.regions	= {0x40000, 31, 0x10000, 4},
	.total_sectors	= 35,
};

static struct flash_geom geom_8M_bottomboot_big = {
	.total_size	= 0x800000,
	.nregions	= 2,
	.regions	= {0x10000, 4, 0x40000, 31},
	.total_sectors	= 35,
};

/* Intel and compatible flash chips */

static struct cfi_check intel_2M_topboot_cfi[] = {
	{0x10, 'Q'},
	{0x11, 'R'},
	{0x12, 'Y'},
	{0x13, 0x03},
	{0x14, 0x00},
	{0x27, 0x15},
	{0x2C, 0x02},
	{0x2D, 0x1E},
	{0x2E, 0x00},
	{0x2F, 0x00},
	{0x30, 0x01},
	{0x31, 0x07},
	{0x32, 0x00},
	{0x33, 0x20},
	{0x34, 0x00},
	{-1,   0}
};

static struct cfi_check intel_2M_bottomboot_cfi[] = {
	{0x10, 'Q'},
	{0x11, 'R'},
	{0x12, 'Y'},
	{0x13, 0x03},
	{0x14, 0x00},
	{0x27, 0x15},
	{0x2C, 0x02},
	{0x2D, 0x07},
	{0x2E, 0x00},
	{0x2F, 0x20},
	{0x30, 0x00},
	{0x31, 0x1E},
	{0x32, 0x00},
	{0x33, 0x00},
	{0x34, 0x01},
	{-1,   0}
};

static struct cfi_check intel_4M_topboot_cfi[] = {
	{0x10, 'Q'},
	{0x11, 'R'},
	{0x12, 'Y'},
	{0x13, 0x03},
	{0x14, 0x00},
	{0x27, 0x16},
	{0x2C, 0x02},
	{0x2D, 0x3E},
	{0x2E, 0x00},
	{0x2F, 0x00},
	{0x30, 0x01},
	{0x31, 0x07},
	{0x32, 0x00},
	{0x33, 0x20},
	{0x34, 0x00},
	{-1,   0}
};

static struct cfi_check intel_4M_bottomboot_cfi[] = {
	{0x10, 'Q'},
	{0x11, 'R'},
	{0x12, 'Y'},
	{0x13, 0x03},
	{0x14, 0x00},
	{0x27, 0x16},
	{0x2C, 0x02},
	{0x2D, 0x07},
	{0x2E, 0x00},
	{0x2F, 0x20},
	{0x30, 0x00},
	{0x31, 0x3E},
	{0x32, 0x00},
	{0x33, 0x00},
	{0x34, 0x01},
	{-1,   0}
};

static struct cfi_check intel_8M_topboot_cfi[] = {
	{0x10, 'Q'},
	{0x11, 'R'},
	{0x12, 'Y'},
	{0x13, 0x03},
	{0x14, 0x00},
	{0x27, 0x17},
	{0x2C, 0x02},
	{0x2D, 0x7E},
	{0x2E, 0x00},
	{0x2F, 0x00},
	{0x30, 0x01},
	{0x31, 0x07},
	{0x32, 0x00},
	{0x33, 0x20},
	{0x34, 0x00},
	{-1,   0}
};

static struct cfi_check intel_8M_bottomboot_cfi[] = {
	{0x10, 'Q'},
	{0x11, 'R'},
	{0x12, 'Y'},
	{0x13, 0x03},
	{0x14, 0x00},
	{0x27, 0x17},
	{0x2C, 0x02},
	{0x2D, 0x07},
	{0x2E, 0x00},
	{0x2F, 0x20},
	{0x30, 0x00},
	{0x31, 0x7E},
	{0x32, 0x00},
	{0x33, 0x00},
	{0x34, 0x01},
	{-1,   0}
};

/* classic Intel C3 family: found in low-end Mot C1xx models and BenQ M32 */

struct flash_device flashdev_28F160C3T = {
	.name			= "Intel 28F160C3T",
	.cfi_table		= intel_2M_topboot_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_4M,
	.bank_geom		= {&geom_2M_topboot, 0},
	.cmdset			= &flash_cmdset_intel,
};

struct flash_device flashdev_28F160C3B = {
	.name			= "Intel 28F160C3B",
	.cfi_table		= intel_2M_bottomboot_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_4M,
	.bank_geom		= {&geom_2M_bottomboot, 0},
	.cmdset			= &flash_cmdset_intel,
};

struct flash_device flashdev_28F320C3T = {
	.name			= "Intel 28F320C3T",
	.cfi_table		= intel_4M_topboot_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_4M,
	.bank_geom		= {&geom_4M_topboot, 0},
	.cmdset			= &flash_cmdset_intel,
};

struct flash_device flashdev_28F320C3B = {
	.name			= "Intel 28F320C3B",
	.cfi_table		= intel_4M_bottomboot_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_4M,
	.bank_geom		= {&geom_4M_bottomboot, 0},
	.cmdset			= &flash_cmdset_intel,
};

struct flash_device flashdev_28F640C3T = {
	.name			= "Intel 28F640C3T",
	.cfi_table		= intel_8M_topboot_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_8M,
	.bank_geom		= {&geom_8M_topboot, 0},
	.cmdset			= &flash_cmdset_intel,
};

struct flash_device flashdev_28F640C3B = {
	.name			= "Intel 28F640C3B",
	.cfi_table		= intel_8M_bottomboot_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_8M,
	.bank_geom		= {&geom_8M_bottomboot, 0},
	.cmdset			= &flash_cmdset_intel,
};

/*
 * Intel W18 and W30 families are equivalent in terms of geometries and
 * relevant quirks, and are distinguishable only by ID codes.  We treat them
 * all as W30, based on the latter family being the first one encountered:
 * 28F640W30B is the flash chip used on TI's legendary D-Sample board, and
 * the flash inside Motorola C155/156 is an MCP equivalent of the same.
 */

struct flash_device flashdev_28F320W30T = {
	.name			= "Intel 28F320W30T",
	.cfi_table		= intel_4M_topboot_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_4M,
	.bank_geom		= {&geom_4M_topboot, 0},
	.cmdset			= &flash_cmdset_intel_w30,
};

struct flash_device flashdev_28F320W30B = {
	.name			= "Intel 28F320W30B",
	.cfi_table		= intel_4M_bottomboot_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_4M,
	.bank_geom		= {&geom_4M_bottomboot, 0},
	.cmdset			= &flash_cmdset_intel_w30,
};

struct flash_device flashdev_28F640W30T = {
	.name			= "Intel 28F640W30T",
	.cfi_table		= intel_8M_topboot_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_8M,
	.bank_geom		= {&geom_8M_topboot, 0},
	.cmdset			= &flash_cmdset_intel_w30,
};

struct flash_device flashdev_28F640W30B = {
	.name			= "Intel 28F640W30B",
	.cfi_table		= intel_8M_bottomboot_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_8M,
	.bank_geom		= {&geom_8M_bottomboot, 0},
	.cmdset			= &flash_cmdset_intel_w30,
};

/* classic AMD flash chips */

static struct cfi_check Am29DL640G_cfi[] = {
	{0x10, 'Q'},
	{0x11, 'R'},
	{0x12, 'Y'},
	{0x13, 0x02},
	{0x14, 0x00},
	{0x15, 0x40},
	{0x16, 0x00},
	{0x27, 0x17},
	{0x2C, 0x03},
	{0x2D, 0x07},
	{0x2E, 0x00},
	{0x2F, 0x20},
	{0x30, 0x00},
	{0x31, 0x7D},
	{0x32, 0x00},
	{0x33, 0x00},
	{0x34, 0x01},
	{0x35, 0x07},
	{0x36, 0x00},
	{0x37, 0x20},
	{0x38, 0x00},
	{0x40, 'P'},
	{0x41, 'R'},
	{0x42, 'I'},
	{0x43, '1'},
	{0x44, '3'},
	{0x49, 0x04},
	{-1,   0}
};

static struct amd_lock_info Am29DL640G_lock_info = {
	.ngroups		= 8,
	.groups			= {
		{0x2000, 8, 0, 1, 0},
		{0x10000, 3, 0, 0, 0},
		{0x40000, 3, 1, 0, 1},
		{0x40000, 12, 1, 1, 1},
		{0x40000, 12, 1, 1, 1},
		{0x40000, 3, 1, 1, 0},
		{0x10000, 3, 0, 0, 0},
		{0x2000, 8, 0, 0, 1}},
	.have_status_word_3	= 1,
};

struct flash_device flashdev_Am29DL640G = {
	.name			= "Am29DL640G",
	.cfi_table		= Am29DL640G_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_8M,
	.bank_geom		= {&geom_8M_bothends, 0},
	.cmdset			= &flash_cmdset_amd,
	.lock_info		= {&Am29DL640G_lock_info, 0},
};

/* Spansion S71PL-J and S71PL-N flash */

static struct cfi_check spansion_PL032J_cfi[] = {
	{0x10, 'Q'},
	{0x11, 'R'},
	{0x12, 'Y'},
	{0x13, 0x02},
	{0x14, 0x00},
	{0x15, 0x40},
	{0x16, 0x00},
	{0x27, 0x16},
	{0x2C, 0x03},
	{0x2D, 0x07},
	{0x2E, 0x00},
	{0x2F, 0x20},
	{0x30, 0x00},
	{0x31, 0x3D},
	{0x32, 0x00},
	{0x33, 0x00},
	{0x34, 0x01},
	{0x35, 0x07},
	{0x36, 0x00},
	{0x37, 0x20},
	{0x38, 0x00},
	{0x40, 'P'},
	{0x41, 'R'},
	{0x42, 'I'},
	{0x43, '1'},
	{0x44, '3'},
	{-1,   0}
};

struct flash_device flashdev_PL032J = {
	.name			= "Spansion S29PL032J",
	.cfi_table		= spansion_PL032J_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_4M,
	.bank_geom		= {&geom_4M_bothends, 0},
	.cmdset			= &flash_cmdset_amd,
};

/*
 * For our purposes, S29PL064J/S71PL064J differs from Am29DL640G only
 * in terms of lock status retrieval and manipulation: the older chip
 * lacks persistent/password mode lock bits and in-system lock/unlock
 * operations.  We distinguish them by one byte in CFI.
 */

static struct cfi_check spansion_PL064J_cfi[] = {
	{0x10, 'Q'},
	{0x11, 'R'},
	{0x12, 'Y'},
	{0x13, 0x02},
	{0x14, 0x00},
	{0x15, 0x40},
	{0x16, 0x00},
	{0x27, 0x17},
	{0x2C, 0x03},
	{0x2D, 0x07},
	{0x2E, 0x00},
	{0x2F, 0x20},
	{0x30, 0x00},
	{0x31, 0x7D},
	{0x32, 0x00},
	{0x33, 0x00},
	{0x34, 0x01},
	{0x35, 0x07},
	{0x36, 0x00},
	{0x37, 0x20},
	{0x38, 0x00},
	{0x40, 'P'},
	{0x41, 'R'},
	{0x42, 'I'},
	{0x43, '1'},
	{0x44, '3'},
	{0x49, 0x07},
	{-1,   0}
};

static struct amd_lock_info PL064J_lock_info = {
	.ngroups		= 8,
	.groups			= {
		{0x2000, 8, 0, 1, 0},
		{0x10000, 3, 0, 0, 0},
		{0x40000, 3, 1, 0, 1},
		{0x40000, 12, 1, 1, 1},
		{0x40000, 12, 1, 1, 1},
		{0x40000, 3, 1, 1, 0},
		{0x10000, 3, 0, 0, 0},
		{0x2000, 8, 0, 0, 1}},
	.have_status_word_3	= 1,
	.have_mode_lock_bits	= 1,
	.ppb_program_one	= plj_ppb_program_one,
	.ppb_program_all	= plj_ppb_program_all,
	.ppb_erase_all		= plj_ppb_erase_all_single,
};

struct flash_device flashdev_PL064J = {
	.name			= "Spansion S29PL064J",
	.cfi_table		= spansion_PL064J_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_8M,
	.bank_geom		= {&geom_8M_bothends, 0},
	.cmdset			= &flash_cmdset_amd,
	.lock_info		= {&PL064J_lock_info, 0},
};

static struct cfi_check spansion_PL129J_cfi[] = {
	{0x10, 'Q'},
	{0x11, 'R'},
	{0x12, 'Y'},
	{0x13, 0x02},
	{0x14, 0x00},
	{0x15, 0x40},
	{0x16, 0x00},
	{0x27, 0x18},
	{0x2C, 0x03},
	{0x2D, 0x07},
	{0x2E, 0x00},
	{0x2F, 0x20},
	{0x30, 0x00},
	{0x31, 0xFD},
	{0x32, 0x00},
	{0x33, 0x00},
	{0x34, 0x01},
	{0x35, 0x07},
	{0x36, 0x00},
	{0x37, 0x20},
	{0x38, 0x00},
	{0x40, 'P'},
	{0x41, 'R'},
	{0x42, 'I'},
	{0x43, '1'},
	{0x44, '3'},
	{-1,   0}
};

static struct amd_lock_info PL129J_lock_info_0 = {
	.ngroups		= 4,
	.groups			= {
		{0x2000, 8, 0, 1, 0},
		{0x10000, 3, 0, 0, 0},
		{0x40000, 7, 1, 0, 1},
		{0x40000, 24, 1, 1, 1}},
	.have_status_word_3	= 1,
	.have_mode_lock_bits	= 1,
	.ppb_program_one	= plj_ppb_program_one,
	.ppb_program_all	= plj_ppb_program_all,
	.ppb_erase_all		= plj_ppb_erase_all_dualbank,
};

static struct amd_lock_info PL129J_lock_info_1 = {
	.ngroups		= 4,
	.groups			= {
		{0x40000, 24, 1, 1, 1},
		{0x40000, 7, 1, 1, 0},
		{0x10000, 3, 0, 0, 0},
		{0x2000, 8, 0, 0, 1}},
	.have_status_word_3	= 1,
	.ppb_program_one	= plj_ppb_program_one,
	.ppb_program_all	= plj_ppb_program_all,
};

struct flash_device flashdev_PL129J = {
	.name			= "Spansion S29PL129J",
	.cfi_table		= spansion_PL129J_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_DUAL_8M,
	.bank_geom		= {&geom_8M_bottomboot, &geom_8M_topboot},
	.cmdset			= &flash_cmdset_amd,
	.lock_info		= {&PL129J_lock_info_0, &PL129J_lock_info_1},
};

static struct cfi_check spansion_PL129N_cfi[] = {
	{0x10, 'Q'},
	{0x11, 'R'},
	{0x12, 'Y'},
	{0x13, 0x02},
	{0x14, 0x00},
	{0x15, 0x40},
	{0x16, 0x00},
	{0x27, 0x18},
	{0x2C, 0x03},
	{0x2D, 0x03},
	{0x2E, 0x00},
	{0x2F, 0x00},
	{0x30, 0x01},
	{0x31, 0x3D},
	{0x32, 0x00},
	{0x33, 0x00},
	{0x34, 0x04},
	{0x35, 0x03},
	{0x36, 0x00},
	{0x37, 0x00},
	{0x38, 0x01},
	{0x40, 'P'},
	{0x41, 'R'},
	{0x42, 'I'},
	{0x43, '1'},
	{0x44, '4'},
	{-1,   0}
};

static struct amd_lock_info PL129N_lock_info_0 = {
	.ngroups		= 3,
	.groups			= {
		{0x10000, 4, 0, 1, 0},
		{0x40000, 7, 0, 0, 1},
		{0x40000, 24, 0, 1, 1}},
	.have_status_word_3	= 1,
	.have_pln_lock_reg	= 1,
	.ppb_program_one	= pln_ppb_program_one,
	.ppb_erase_all		= pln_ppb_erase_all,
};

static struct amd_lock_info PL129N_lock_info_1 = {
	.ngroups		= 3,
	.groups			= {
		{0x40000, 24, 0, 1, 1},
		{0x40000, 7, 0, 1, 0},
		{0x10000, 4, 0, 0, 1}},
	.have_status_word_3	= 1,
	.ppb_program_one	= pln_ppb_program_one,
};

struct flash_device flashdev_PL129N = {
	.name			= "Spansion S29PL129N",
	.cfi_table		= spansion_PL129N_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_DUAL_8M,
	.bank_geom		= {&geom_8M_bottomboot_big,
				   &geom_8M_topboot_big},
	.cmdset			= &flash_cmdset_amd,
	.lock_info		= {&PL129N_lock_info_0, &PL129N_lock_info_1},
};

/* Samsung K5A32xxCTM introduced onto the scene by Openmoko */

static struct cfi_check samsung_4M_topboot_cfi[] = {
	{0x10, 'Q'},
	{0x11, 'R'},
	{0x12, 'Y'},
	{0x13, 0x02},
	{0x14, 0x00},
	{0x15, 0x40},
	{0x16, 0x00},
	{0x27, 0x16},
	{0x2C, 0x02},
	{0x2D, 0x07},
	{0x2E, 0x00},
	{0x2F, 0x20},
	{0x30, 0x00},
	{0x31, 0x3E},
	{0x32, 0x00},
	{0x33, 0x00},
	{0x34, 0x01},
	{0x40, 'P'},
	{0x41, 'R'},
	{0x42, 'I'},
	{0x43, '3'},
	{0x44, '3'},
	{0x4F, 0x03},
	{-1,   0}
};

struct flash_device flashdev_K5A32xx_T = {
	.name			= "Samsung K5A32xx_T",
	.cfi_table		= samsung_4M_topboot_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_4M,
	.bank_geom		= {&geom_4M_topboot, 0},
	.cmdset			= &flash_cmdset_amd,
};

/* a different 4 MiB Samsung flash chip used in Huawei GTM900 */

static struct cfi_check samsung_4M_bothends_cfi[] = {
	{0x10, 'Q'},
	{0x11, 'R'},
	{0x12, 'Y'},
	{0x13, 0x02},
	{0x14, 0x00},
	{0x15, 0x40},
	{0x16, 0x00},
	{0x27, 0x16},
	{0x2C, 0x03},
	{0x2D, 0x07},
	{0x2E, 0x00},
	{0x2F, 0x20},
	{0x30, 0x00},
	{0x31, 0x3D},
	{0x32, 0x00},
	{0x33, 0x00},
	{0x34, 0x01},
	{0x35, 0x07},
	{0x36, 0x00},
	{0x37, 0x20},
	{0x38, 0x00},
	{0x40, 'P'},
	{0x41, 'R'},
	{0x42, 'I'},
	{0x43, '0'},
	{0x44, '0'},
	{0x4F, 0x04},
	{-1,   0}
};

struct flash_device flashdev_K5L33xx_A = {
	.name			= "Samsung K5L33xx_A",
	.cfi_table		= samsung_4M_bothends_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_SINGLE_4M,
	.bank_geom		= {&geom_4M_bothends, 0},
	.cmdset			= &flash_cmdset_amd,
};

/* Samsung equivalent of S71PL129J, found in Sony Ericsson K200/220 phones */

static struct cfi_check samsung_PL129J_equiv_cfi[] = {
	{0x10, 'Q'},
	{0x11, 'R'},
	{0x12, 'Y'},
	{0x13, 0x02},
	{0x14, 0x00},
	{0x15, 0x40},
	{0x16, 0x00},
	{0x27, 0x18},
	{0x2C, 0x03},
	{0x2D, 0x07},
	{0x2E, 0x00},
	{0x2F, 0x20},
	{0x30, 0x00},
	{0x31, 0xFD},
	{0x32, 0x00},
	{0x33, 0x00},
	{0x34, 0x01},
	{0x35, 0x07},
	{0x36, 0x00},
	{0x37, 0x20},
	{0x38, 0x00},
	{0x40, 'P'},
	{0x41, 'R'},
	{0x42, 'I'},
	{0x43, '0'},
	{0x44, '0'},
	{0x4F, 0x04},
	{-1,   0}
};

static struct amd_lock_info K5L29_lock_info_0 = {
	.ngroups		= 4,
	.groups			= {
		{0x2000, 8, 0, 1, 0},
		{0x10000, 3, 0, 0, 0},
		{0x40000, 7, 1, 0, 1},
		{0x40000, 24, 1, 1, 1}},
	.have_status_word_3	= 1,
	.have_status_word_7	= 1,
	.have_mode_lock_bits	= 1,
	.ppb_program_one	= plj_ppb_program_one,
	.ppb_program_all	= plj_ppb_program_all,
	.ppb_erase_all		= plj_ppb_erase_all_dualbank,
};

static struct amd_lock_info K5L29_lock_info_1 = {
	.ngroups		= 4,
	.groups			= {
		{0x40000, 24, 1, 1, 1},
		{0x40000, 7, 1, 1, 0},
		{0x10000, 3, 0, 0, 0},
		{0x2000, 8, 0, 0, 1}},
	.have_status_word_3	= 1,
	.have_status_word_7	= 1,
	.ppb_program_one	= plj_ppb_program_one,
	.ppb_program_all	= plj_ppb_program_all,
};

struct flash_device flashdev_K5L29xx_A = {
	.name			= "Samsung K5L29xx_A",
	.cfi_table		= samsung_PL129J_equiv_cfi,
	.required_global_config	= FLASH_GLOBAL_CFG_DUAL_8M,
	.bank_geom		= {&geom_8M_bottomboot, &geom_8M_topboot},
	.cmdset			= &flash_cmdset_amd,
	.lock_info		= {&K5L29_lock_info_0, &K5L29_lock_info_1},
};