FreeCalypso > hg > freecalypso-tools
view loadtools/flashid.c @ 737:6d97866bad79
first round of documentation for DUART28C boot control addition
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 16 Sep 2020 06:10:39 +0000 |
parents | f229efbfd581 |
children | 54a0bc149d9c |
line wrap: on
line source
/* * Flash device detection code lives here */ #include <sys/types.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include "flash.h" extern struct flash_device flashdev_28F160C3T; extern struct flash_device flashdev_28F320C3T; extern struct flash_device flashdev_28F640C3T; extern struct flash_device flashdev_28F640C3B; extern struct flash_device flashdev_28F640W30T; extern struct flash_device flashdev_28F640W30B; extern struct flash_device flashdev_Am29DL640G; extern struct flash_device flashdev_PL032J; extern struct flash_device flashdev_PL129J; extern struct flash_device flashdev_PL129N; extern struct flash_device flashdev_K5A32xx_T; extern struct flash_device flashdev_K5L33xx_A; extern int flash_global_config; extern struct flash_bank_info flash_bank_info[2]; static run_cfi_check(bi, table) struct flash_bank_info *bi; struct cfi_check *table; { struct cfi_check *tp; uint16_t rdword; for (tp = table; tp->offset >= 0; tp++) { if (do_r16(bi->base_addr + (tp->offset << 1), &rdword) < 0) return(-1); if (rdword != tp->expect_val) return(0); } return(1); } static try_device(bi, dev) struct flash_bank_info *bi; struct flash_device *dev; { int rc; printf("Appears to be %s or compatible, checking CFI\n", dev->name); if (do_w16(bi->base_addr + 0xAA, 0x98)) { fprintf(stderr, "unexpected response to w16 - aborting\n"); return(-1); } rc = run_cfi_check(bi, dev->cfi_table); if (rc < 0) return(rc); if (!rc) { fprintf(stderr, "Error: CFI mismatch, unsafe to continue\n"); return(-1); } printf("Confirmed %s or compatible\n", dev->name); bi->device = dev; return(0); } static spansion_pl129j_or_n(bi) struct flash_bank_info *bi; { int rc; printf("Spansion PL129J or PL129N, looking at CFI\n"); /* need to go back to read array first, CFI cmd ignored otherwise */ if (do_w16(bi->base_addr + 0xAAA, 0xF0)) { bad_w16: fprintf(stderr, "unexpected response to w16 - aborting\n"); return(-1); } if (do_w16(bi->base_addr + 0xAAA, 0x98)) goto bad_w16; rc = run_cfi_check(bi, flashdev_PL129N.cfi_table); if (rc < 0) return(rc); if (rc) { printf("Found PL129N\n"); bi->device = &flashdev_PL129N; return(0); } rc = run_cfi_check(bi, flashdev_PL129J.cfi_table); if (rc < 0) return(rc); if (rc) { printf("Found PL129J\n"); bi->device = &flashdev_PL129J; return(0); } fprintf(stderr, "Error: no matching CFI found\n"); return(-1); } static amd_extended_id(bi) struct flash_bank_info *bi; { uint16_t ext1, ext2; printf("AMD-style extended ID device, reading extended ID\n"); if (do_r16(bi->base_addr + 0x1C, &ext1) < 0) return(-1); if (do_r16(bi->base_addr + 0x1E, &ext2) < 0) return(-1); printf("Extended ID: %04X %04X\n", ext1, ext2); if (ext1 == 0x2221 && ext2 == 0x2200) return spansion_pl129j_or_n(bi); if (ext1 == 0x2202 && ext2 == 0x2201) return try_device(bi, &flashdev_Am29DL640G); if (ext1 == 0x220A && ext2 == 0x2201) return try_device(bi, &flashdev_PL032J); fprintf(stderr, "Error: unknown device ID\n"); return(-1); } static samsung_extended_id(bi) struct flash_bank_info *bi; { uint16_t ext1, ext2; printf("Samsung extended ID device, reading extended ID\n"); if (do_r16(bi->base_addr + 0x1C, &ext1) < 0) return(-1); if (do_r16(bi->base_addr + 0x1E, &ext2) < 0) return(-1); printf("Extended ID: %04X %04X\n", ext1, ext2); if (ext1 == 0x2503 && ext2 == 0x2501) return try_device(bi, &flashdev_K5L33xx_A); fprintf(stderr, "Error: unknown device ID\n"); return(-1); } static struct idmap { uint16_t manuf_id; uint16_t dev_id; int (*handler)(); void *extra_arg; } device_id_table[] = { /* AMD/Spansion devices */ {0x0001, 0x227E, amd_extended_id, 0}, /* 28F160C3T and 28F320C3T equivalents found in some Mot C1xx phones */ {0x0020, 0x88BA, try_device, &flashdev_28F320C3T}, {0x0020, 0x88CE, try_device, &flashdev_28F160C3T}, /* Intel flash chips */ {0x0089, 0x8854, try_device, &flashdev_28F640W30T}, {0x0089, 0x8855, try_device, &flashdev_28F640W30B}, {0x0089, 0x8864, try_device, &flashdev_28F640W30T}, {0x0089, 0x88C2, try_device, &flashdev_28F160C3T}, {0x0089, 0x88C4, try_device, &flashdev_28F320C3T}, {0x0089, 0x88CC, try_device, &flashdev_28F640C3T}, {0x0089, 0x88CD, try_device, &flashdev_28F640C3B}, /* Samsung flash */ {0x00EC, 0x22A0, try_device, &flashdev_K5A32xx_T}, {0x00EC, 0x257E, samsung_extended_id, 0}, /* table search terminator */ {0, 0, 0, 0} }; flash_detect(bank, repeat) { struct flash_bank_info *bi; uint16_t manuf_id, dev_id; struct idmap *tp; int rc; bi = flash_bank_info + bank; if (bi->detect_done && !repeat) return(0); printf("Autodetecting flash chip type\n"); if (do_w16(bi->base_addr + 0xAAA, 0xAA)) { bad_w16: fprintf(stderr, "unexpected response to w16 in read ID cmd sequence - aborting\n"); return(-1); } if (do_w16(bi->base_addr + 0x554, 0x55)) goto bad_w16; if (do_w16(bi->base_addr + 0xAAA, 0x90)) goto bad_w16; if (do_r16(bi->base_addr, &manuf_id) < 0) return(-1); if (do_r16(bi->base_addr + 2, &dev_id) < 0) return(-1); printf("Basic device ID: %04X %04X\n", manuf_id, dev_id); for (tp = device_id_table; tp->handler; tp++) if (tp->manuf_id == manuf_id && tp->dev_id == dev_id) break; if (!tp->handler) { fprintf(stderr, "Error: unknown device ID\n"); return(-1); } rc = tp->handler(bi, tp->extra_arg); if (rc < 0) return(rc); /* got the device, see if it is compatible with global config */ if (bi->device->required_global_config > flash_global_config) { fprintf(stderr, "Error: detected flash device is not compatible with the configured mapping\n"); return(-1); } /* good to go */ if (bi->device->bank_geom[1] && bank) bi->geom = bi->device->bank_geom[1]; else bi->geom = bi->device->bank_geom[0]; bi->ops = bi->device->cmdset; bi->detect_done = 1; /* return device to read array mode */ return bi->ops->reset_cmd(bi); }