summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2016-02-11 15:03:12 -0800
committerchrome-bot <chrome-bot@chromium.org>2016-02-17 12:01:31 -0800
commitffd5819d326e66c49f1df517b26581bff4fd68be (patch)
tree0cd77217f02eba999dbcb1c9f608a61d77809a3c
parentb37a7b7166e2408f3a4e25abadea00e3dff4a864 (diff)
downloadchrome-ec-ffd5819d326e66c49f1df517b26581bff4fd68be.tar.gz
cr50: allow board to provide flash configuration
The g chip is used in multiple designs, likely to have different flash memory layout and access permissions. This patch introduces a mechanism which allows the board layer to provide flash configuration information to the flash driver. The flash region which is going to be enabled for write access depends on the area the code is executing from. If running from the bottom half (A), the whole top half should be writeable (this includes both NVRAM area and the B code space). If running from B, the writeable area starts on top of RO and extends to the end of NVRAM. CQ-DEPEND=CL:*248190 BRANCH=none BUG=chrome-os-partner:37754 TEST=with the rest of the patches applied verified that software update can happen in both spaces, A and B. Change-Id: Iab1c1a2766ae9bcfe04ff170c010f180cd1f770f Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/327412 Reviewed-by: Bill Richardson <wfrichar@chromium.org> Reviewed-by: Nadim Taha <ntaha@chromium.org>
-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 */
+