diff options
-rw-r--r-- | board/cr50/board.c | 35 | ||||
-rw-r--r-- | chip/g/flash.c | 37 | ||||
-rw-r--r-- | chip/g/flash_config.h | 38 |
3 files changed, 101 insertions, 9 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c index 492989b4f1..3b754655b8 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -6,6 +6,7 @@ #include "common.h" #include "console.h" #include "ec_version.h" +#include "flash_config.h" #include "gpio.h" #include "hooks.h" #include "registers.h" @@ -160,3 +161,37 @@ const void * const usb_strings[] = { }; BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT); #endif + +int flash_regions_to_enable(struct g_flash_region *regions, + int max_regions) +{ + uint32_t half = CONFIG_FLASH_SIZE / 2; + + if (max_regions < 1) + return 0; + + if ((uint32_t)flash_regions_to_enable < + (CONFIG_MAPPED_STORAGE_BASE + half)) + /* + * Running from RW_A. Need to enable writes into the top half, + * which consists of NV_RAM and RW_B sections. + */ + regions->reg_base = CONFIG_MAPPED_STORAGE_BASE + half; + else + /* + * Running from RW_B, need to enable access to both program + * memory in the lower half and the NVRAM space in the top + * half. + * + * NVRAM space in the top half by design is at the same offset + * and of the same size as the RO section in the lower half. + */ + regions->reg_base = CONFIG_MAPPED_STORAGE_BASE + + CONFIG_RO_SIZE; + + /* The size of the write enable area is the same in both cases. */ + regions->reg_size = half; + regions->reg_perms = FLASH_REGION_EN_ALL; + + return 1; /* One region is enough. */ +} diff --git a/chip/g/flash.c b/chip/g/flash.c index 06cd2304ed..52d7499294 100644 --- a/chip/g/flash.c +++ b/chip/g/flash.c @@ -41,6 +41,7 @@ #include "common.h" #include "console.h" #include "flash.h" +#include "flash_config.h" #include "registers.h" #include "timer.h" #include "watchdog.h" @@ -49,15 +50,33 @@ int flash_pre_init(void) { - /* Enable access to the upper half of the flash */ - uint32_t half = CONFIG_FLASH_SIZE / 2; - - GWRITE(GLOBALSEC, FLASH_REGION2_BASE_ADDR, - CONFIG_MAPPED_STORAGE_BASE + half); - GWRITE(GLOBALSEC, FLASH_REGION2_SIZE, half - 1); - GWRITE_FIELD(GLOBALSEC, FLASH_REGION2_CTRL, WR_EN, 1); - GWRITE_FIELD(GLOBALSEC, FLASH_REGION2_CTRL, RD_EN, 1); - GWRITE_FIELD(GLOBALSEC, FLASH_REGION2_CTRL, EN, 1); + struct g_flash_region regions[4]; + int i, num_regions; + + num_regions = flash_regions_to_enable(regions, ARRAY_SIZE(regions)); + + for (i = 0; i < num_regions; i++) { + int reg_base; + + /* Region range */ + reg_base = GBASE(GLOBALSEC) + + GOFFSET(GLOBALSEC, FLASH_REGION2_BASE_ADDR) + + i * 8; + + REG32(reg_base) = regions[i].reg_base; + + /* + * The hardware requires a value which is 1 less than the + * actual region size. + */ + REG32(reg_base + 4) = regions[i].reg_size - 1; + + /* Region permissions. */ + reg_base = GBASE(GLOBALSEC) + + GOFFSET(GLOBALSEC, FLASH_REGION2_CTRL) + + i * 4; + REG32(reg_base) = regions[i].reg_perms; + } return EC_SUCCESS; } diff --git a/chip/g/flash_config.h b/chip/g/flash_config.h new file mode 100644 index 0000000000..202221a5a1 --- /dev/null +++ b/chip/g/flash_config.h @@ -0,0 +1,38 @@ +/* + * Copyright 2016 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#ifndef __EC_CHIP_G_FLASH_CONFIG_H +#define __EC_CHIP_G_FLASH_CONFIG_H + +#define FLASH_REGION_EN_ALL ((1 << GC_GLOBALSEC_FLASH_REGION0_CTRL_EN_LSB) |\ + (1 << GC_GLOBALSEC_FLASH_REGION0_CTRL_RD_EN_LSB) |\ + (1 << GC_GLOBALSEC_FLASH_REGION0_CTRL_WR_EN_LSB)) + +/* + * The below structure describes a single flash region (the hardware supports + * up to eight). The reg_size field is the actual region size, The reg_perms + * bits are as used in the above macro, allowing to enable the region and its + * read and write accesses separately. + */ +struct g_flash_region { + uint32_t reg_base; + uint32_t reg_size; + uint32_t reg_perms; +}; + +/* + * This function is provided by the board layer to describe necessary flash + * regions' configuration to allow the flash driver to set the regions + * properly. + * + * The function is passed an array of the g_flash_region structures of the + * max_regions size, it fills as many entties as necessary and returns the + * number of set up entries. + */ +int flash_regions_to_enable(struct g_flash_region *regions, + int max_regions); + +#endif /* ! __EC_CHIP_G_FLASH_CONFIG_H */ + |