summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/cr50/board.c35
-rw-r--r--chip/g/flash.c37
-rw-r--r--chip/g/flash_config.h38
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 */
+