view loadtools/fldevs.c @ 1008:2b4c3e0f73fc

doc/High-speed-serial: update for current situation
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 10 Dec 2023 23:42:12 +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},
};