| /* Copyright 2015 The ChromiumOS Authors |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "debug_printf.h" |
| #include "setup.h" |
| #include "rom_flash.h" |
| |
| static int _flash_error(void) |
| { |
| int retval = GREG32(FLASH, FSH_ERROR); |
| |
| if (!retval) |
| return 0; |
| |
| debug_printf("Register FLASH_FSH_ERROR is not zero (found %x).\n", |
| retval); |
| debug_printf("Will read again to verify FSH_ERROR was cleared "); |
| debug_printf("and then continue...\n"); |
| |
| retval = GREG32(FLASH, FSH_ERROR); |
| if (retval) { |
| debug_printf("ERROR: Read to FLASH_FSH_ERROR (%x) " |
| "did not clear it\n", retval); |
| } |
| |
| return retval; |
| } |
| |
| /* Verify the flash controller is awake. */ |
| static int _check_flash_is_awake(void) |
| { |
| int retval; |
| |
| GREG32(FLASH, FSH_TRANS) = 0xFFFFFFFF; |
| retval = GREG32(FLASH, FSH_TRANS); |
| GREG32(FLASH, FSH_TRANS) = 0x0; |
| |
| if (retval == 0) { |
| debug_printf("ERROR:FLASH Controller seems unresponsive. "); |
| debug_printf("Did you make sure to run 'reseth'?\n"); |
| return E_FL_NOT_AWAKE; |
| } |
| |
| return 0; |
| } |
| |
| /* Send cmd to flash controller. */ |
| static int _flash_cmd(uint32_t fidx, uint32_t cmd) |
| { |
| int cnt, retval; |
| |
| /* Activate controller. */ |
| GREG32(FLASH, FSH_PE_EN) = FSH_OP_ENABLE; |
| GREG32_ADDR(FLASH, FSH_PE_CONTROL0)[fidx] = cmd; |
| |
| /* wait on FSH_PE_EN (means the operation started) */ |
| cnt = 500; /* TODO(mschilder): pick sane value. */ |
| |
| do { |
| retval = GREG32(FLASH, FSH_PE_EN); |
| } while (retval && cnt--); |
| |
| if (retval) { |
| debug_printf("ERROR: FLASH_FSH_PE_EN never went to 0, is "); |
| debug_printf("0x%x after timeout\n", retval); |
| return E_FL_TIMEOUT; |
| } |
| |
| /* |
| * wait 100us before checking FSH_PE_CONTROL (means the operation |
| * ended) |
| */ |
| cnt = 1000000; |
| do { |
| retval = GREG32_ADDR(FLASH, FSH_PE_CONTROL0)[fidx]; |
| } while (retval && --cnt); |
| |
| if (retval) { |
| debug_printf |
| ("ERROR: FLASH_FSH_PE_CONTROL%d is 0x%x after timeout\n", |
| fidx, retval); |
| GREG32_ADDR(FLASH, FSH_PE_CONTROL0)[fidx] = 0; |
| return E_FL_TIMEOUT; |
| } |
| |
| return 0; |
| } |
| |
| int flash_info_read(uint32_t offset, uint32_t *dst) |
| { |
| int retval; |
| |
| /* Make sure flash controller is awake. */ |
| retval = _check_flash_is_awake(); |
| if (retval) |
| return retval; |
| |
| GWRITE_FIELD(FLASH, FSH_TRANS, OFFSET, offset); |
| GWRITE_FIELD(FLASH, FSH_TRANS, MAINB, 1); |
| GWRITE_FIELD(FLASH, FSH_TRANS, SIZE, 1); |
| |
| retval = _flash_cmd(1, FSH_OP_READ); |
| if (retval) |
| return retval; |
| |
| if (_flash_error()) |
| return E_FL_ERROR; |
| |
| if (!retval) |
| *dst = GREG32(FLASH, FSH_DOUT_VAL1); |
| |
| return retval; |
| } |