char blackbox_read(blackbox_frame *frame, char *data) { uchar type = 0; // The first byte must be a start byte if (flash_read_uchar(blackbox_offset) != BLACKBOX_FRAME_START) return -1; // Read and validate the type type = flash_read_uchar(blackbox_offset + 1); if ((type != BLACKBOX_FRAME_TYPE_INFO) && (type != BLACKBOX_FRAME_TYPE_ERROR) && (type != BLACKBOX_FRAME_TYPE_ADC)) return -2; // Read tick uint32_t tick = flash_read_uint32(blackbox_offset + 2); // Read the data length uchar data_length = flash_read_uchar(blackbox_offset + 6); // The last byte must be an end byte if (flash_read_uchar(blackbox_offset + data_length + 7) != BLACKBOX_FRAME_END) return -3; // If we didn't fail yet, we are good to go frame->type = type; frame->tick = tick; frame->data_length = data_length; flash_read(data, data_length, blackbox_offset + 7); // Read actual data blackbox_offset += data_length + 8; // Prepare for next read return 0; }
/* * read jedec ids from device and set corresponding fields in info struct * * Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct * */ static void amd_read_jedec_ids(struct flash_info *info) { info->cmd_reset = AMD_CMD_RESET; info->manufacturer_id = 0; info->device_id = 0; info->device_id2 = 0; /* calculate command offsets as in the Linux driver */ info->addr_unlock1 = 0x555; info->addr_unlock2 = 0x2AA; /* * modify the unlock address if we are in compatibility mode */ if ( /* x8/x16 in x8 mode */ ((info->chipwidth == FLASH_CFI_BY8) && (info->interface == FLASH_CFI_X8X16)) || /* x16/x32 in x16 mode */ ((info->chipwidth == FLASH_CFI_BY16) && (info->interface == FLASH_CFI_X16X32))) { info->addr_unlock1 = 0xaaa; info->addr_unlock2 = 0x555; } flash_write_cmd(info, 0, 0, info->cmd_reset); flash_unlock_seq(info); flash_write_cmd(info, 0, info->addr_unlock1, FLASH_CMD_READ_ID); udelay(1000); /* some flash are slow to respond */ info->manufacturer_id = jedec_read_mfr(info); info->device_id = flash_read_uchar(info, FLASH_OFFSET_DEVICE_ID); if (info->device_id == 0x7E) { /* AMD 3-byte (expanded) device ids */ info->device_id2 = flash_read_uchar(info, FLASH_OFFSET_DEVICE_ID2); info->device_id2 <<= 8; info->device_id2 |= flash_read_uchar(info, FLASH_OFFSET_DEVICE_ID3); } flash_write_cmd(info, 0, 0, info->cmd_reset); }
/* * read jedec ids from device and set corresponding fields in info struct * * Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct * */ static void amd_read_jedec_ids (struct flash_info *info) { info->manufacturer_id = 0; info->device_id = 0; info->device_id2 = 0; flash_write_cmd(info, 0, 0, AMD_CMD_RESET); flash_unlock_seq(info); flash_write_cmd(info, 0, AMD_ADDR_START, FLASH_CMD_READ_ID); udelay(1000); /* some flash are slow to respond */ info->manufacturer_id = flash_read_uchar (info, FLASH_OFFSET_MANUFACTURER_ID); info->device_id = flash_read_uchar (info, FLASH_OFFSET_DEVICE_ID); if (info->device_id == 0x7E) { /* AMD 3-byte (expanded) device ids */ info->device_id2 = flash_read_uchar (info, FLASH_OFFSET_DEVICE_ID2); info->device_id2 <<= 8; info->device_id2 |= flash_read_uchar (info, FLASH_OFFSET_DEVICE_ID3); } flash_write_cmd(info, 0, 0, AMD_CMD_RESET); }
/* * The following code cannot be run from FLASH! * */ static ulong flash_get_size(ulong base, int banknum) { flash_info_t *info = &flash_info[banknum]; int i, j; int sect_cnt; unsigned long sector; unsigned long tmp; int size_ratio = 0; uchar num_erase_regions; int erase_region_size; int erase_region_count; info->start[0] = base; #if 0 invalidate_dcache_range(base, base + 0x400); #endif if (flash_detect_cfi(info)) { size_ratio = info->portwidth / info->chipwidth; num_erase_regions = flash_read_uchar(info, FLASH_OFFSET_NUM_ERASE_REGIONS); sect_cnt = 0; sector = base; for (i = 0; i < num_erase_regions; i++) { if (i > NUM_ERASE_REGIONS) { printf("%d erase regions found, only %d used\n", num_erase_regions, NUM_ERASE_REGIONS); break; } tmp = flash_read_long(info, 0, FLASH_OFFSET_ERASE_REGIONS); erase_region_size = (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128; tmp >>= 16; erase_region_count = (tmp & 0xffff) + 1; for (j = 0; j < erase_region_count; j++) { info->start[sect_cnt] = sector; sector += (erase_region_size * size_ratio); info->protect[sect_cnt] = flash_isset(info, sect_cnt, FLASH_OFFSET_PROTECT, FLASH_STATUS_PROTECT); sect_cnt++; } } info->sector_count = sect_cnt; /* multiply the size by the number of chips */ info->size = (1 << flash_read_uchar(info, FLASH_OFFSET_SIZE)) * size_ratio; info->buffer_size = (1 << flash_read_ushort(info, 0, FLASH_OFFSET_BUFFER_SIZE)); tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_ETOUT); info->erase_blk_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_EMAX_TOUT))); tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_WBTOUT); info->buffer_write_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_WBMAX_TOUT))); tmp = 1 << flash_read_uchar(info, FLASH_OFFSET_WTOUT); info->write_tout = (tmp * (1 << flash_read_uchar(info, FLASH_OFFSET_WMAX_TOUT))) / 1000; info->flash_id = FLASH_MAN_CFI; } flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); #ifdef DEBUG_FLASH printf("portwidth=%d chipwidth=%d\n", info->portwidth, info->chipwidth); /* test-only */ #endif #ifdef DEBUG_FLASH printf("found %d erase regions\n", num_erase_regions); #endif #ifdef DEBUG_FLASH printf("size=%08x sectors=%08x \n", info->size, info->sector_count); #endif return (info->size); }