FreeCalypso > hg > freecalypso-tools
view loadtools/fldevs.c @ 1000:39a6090a052a
doc/How-flash-really-works: article written
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 09 Dec 2023 09:08:19 +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}, };