mec1322: Add flash physical interface functions

Add physical flash interface for read / write / protection of external
SPI on mec1322.

BUG=chrome-os-partner:36167
TEST=Manual on glower:
flashread 0xf000 0x200 --> dumps 0xff
flashwrite 0xf000 0x200
flashread 0xf000 0x200 --> dumps write pattern
flasherase 0xf000 0x1000
flashread 0xf000 0x200 --> dumps 0xff
spi_flash_prot 0 0x10000
flashinfo --> shows first 64KB protected
spi_flashwrite 0xf000 0x200 --> access denied
spi_flashwrite 0x1f000 0x200 --> OK
flashread 0x1f000 0x200 --> dumps write pattern
BRANCH=None

Change-Id: I2cb20a49934999fc0dd9b3425eb99708711637c5
Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/257132
Reviewed-by: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
Shawn Nematbakhsh
2015-03-10 13:51:38 -07:00
committed by ChromeOS Commit Bot
parent 27199e7b64
commit 07d3b69413
9 changed files with 283 additions and 22 deletions

View File

@@ -49,10 +49,15 @@
#define CONFIG_WATCHDOG_HELP
#define CONFIG_CLOCK_CRYSTAL
#define CONFIG_WAKE_PIN GPIO_POWER_BUTTON_L
/* 512kb SPI flash */
#define CONFIG_SPI_FLASH_SIZE 0x00080000
#define CONFIG_SPI_FLASH_W25X40
#define CONFIG_SPI_PORT 1
#define CONFIG_SPI_CS_GPIO GPIO_PVT_CS0
#undef CONFIG_CONSOLE_CMDHELP
#define CONFIG_CMD_FLASH
#define CONFIG_CMD_SPI_FLASH
#undef CONFIG_TASK_PROFILING
/* Modules we want to exclude */

View File

@@ -14,6 +14,8 @@
#define CONFIG_FANS 1
#define CONFIG_ADC
#define CONFIG_WAKE_PIN GPIO_S1
#define CONFIG_SPI_FLASH_SIZE 0x00800000
#define CONFIG_SPI_FLASH_W25Q64
#define CONFIG_SPI_PORT 0
#define CONFIG_SPI_CS_GPIO GPIO_SHD_CS0

View File

@@ -22,7 +22,7 @@ GPIO(SHD_CS0, PORT(15), 0, GPIO_ODR_HIGH, NULL)
* emulate anyway, to make it more convenient to debug other code.
*/
UNIMPLEMENTED(RECOVERY_L) /* Recovery signal from DOWN button */
UNIMPLEMENTED(WP) /* Write protect input */
UNIMPLEMENTED(WP_L) /* Write protect input */
UNIMPLEMENTED(ENTERING_RW) /* EC entering RW code */
ALTERNATE(PORT(16), 0x24, 1, MODULE_UART, 0) /* UART0 */

View File

@@ -23,13 +23,13 @@
#define CONFIG_POWER_COMMON
#define CONFIG_EXTPOWER_GPIO
#define CONFIG_SPI
#define CONFIG_SPI_PORT 1
#define CONFIG_SPI_CS_GPIO GPIO_PVT_CS0
#define CONFIG_SPI_FLASH
#define CONFIG_SPI_FLASH_SIZE 4194304
/* TODO: Add flash protect support for the SPI part strago actually has */
#define CONFIG_SPI_FLASH_W25Q64
/* Modules we want to exclude */
#undef CONFIG_EEPROM
#undef CONFIG_EOPTION

View File

@@ -37,6 +37,7 @@ GPIO(PVT_CS0, PORT(14), 6, GPIO_ODR_HIGH, NU
* emulate anyway, to make it more convenient to debug other code.
*/
UNIMPLEMENTED(ENTERING_RW) /* EC entering RW code */
UNIMPLEMENTED(WP_L) /* SPI WP Input */
/* Alternate functions GPIO definition */
ALTERNATE(PORT(16), 0x24, 1, MODULE_UART, 0) /* UART0 */

View File

@@ -15,6 +15,7 @@ CFLAGS_CPU+=-march=armv7e-m -mcpu=cortex-m4
chip-y=clock.o gpio.o hwtimer.o system.o uart.o jtag.o
chip-$(CONFIG_ADC)+=adc.o
chip-$(CONFIG_FANS)+=fan.o
chip-$(CONFIG_FLASH)+=flash.o
chip-$(CONFIG_I2C)+=i2c.o
chip-$(CONFIG_LPC)+=lpc.o
chip-$(CONFIG_PWM)+=pwm.o

View File

@@ -47,25 +47,36 @@
/* Default task stack size */
#define TASK_STACK_SIZE 512
#define CONFIG_FLASH_BASE 0x00100000
#define CONFIG_FLASH_PHYSICAL_SIZE 0x00018000
/* Size of one firmware image in RAM */
/****************************************************************************/
/* Define our flash layout. */
/* Protect bank size 4K bytes */
#define CONFIG_FLASH_BANK_SIZE 0x00001000
/* Sector erase size 4K bytes */
#define CONFIG_FLASH_ERASE_SIZE 0x00001000
/* Minimum write size */
#define CONFIG_FLASH_WRITE_SIZE 0x00000004
/* One page size for write */
#define CONFIG_FLASH_WRITE_IDEAL_SIZE 256
/* 96KB flash used for program memory */
#define CONFIG_FLASH_PHYSICAL_SIZE 0x00018000
/* Program memory base address */
#define CONFIG_FLASH_BASE 0x00100000
#define CONFIG_CDRAM_BASE 0x00100000
#define CONFIG_CDRAM_SIZE 0x00020000
/* Size of one firmware image in flash */
#ifndef CONFIG_FW_IMAGE_SIZE
#define CONFIG_FW_IMAGE_SIZE (CONFIG_FLASH_PHYSICAL_SIZE / 2)
#define CONFIG_FW_IMAGE_SIZE (CONFIG_FLASH_PHYSICAL_SIZE / 2)
#endif
/* RO firmware must start at beginning of flash */
#define CONFIG_FW_RO_OFF 0
#define CONFIG_FW_RO_OFF 0
#define CONFIG_FW_RO_SIZE CONFIG_FW_IMAGE_SIZE
#define CONFIG_FLASH_SIZE CONFIG_FLASH_PHYSICAL_SIZE
#define CONFIG_FW_RO_SIZE CONFIG_FW_IMAGE_SIZE
#define CONFIG_FLASH_SIZE CONFIG_FLASH_PHYSICAL_SIZE
/*
* TODO(crosbug.com/p/37510): Implement a loader to load either RO or RW at
@@ -73,14 +84,18 @@
* memory, only flash + load RW for now.
*/
#undef CONFIG_FW_INCLUDE_RO
#define CONFIG_FW_RW_OFF CONFIG_FW_RO_OFF
#define CONFIG_FW_RW_SIZE CONFIG_FLASH_PHYSICAL_SIZE
#define CONFIG_FW_RW_OFF CONFIG_FW_RO_OFF
#define CONFIG_FW_RW_SIZE CONFIG_FLASH_PHYSICAL_SIZE
/* TODO(crosbug.com/p/23796): why 2 sets of configs with the same numbers? */
#define CONFIG_FW_WP_RO_OFF CONFIG_FW_RO_OFF
#define CONFIG_FW_WP_RO_SIZE CONFIG_FW_RO_SIZE
#define CONFIG_FW_WP_RO_OFF CONFIG_FW_RO_OFF
#define CONFIG_FW_WP_RO_SIZE CONFIG_FW_RO_SIZE
#define CONFIG_FLASH_BANK_SIZE 4
/* Non-memmapped, external SPI */
/* #define CONFIG_CODERAM_ARCH */
#undef CONFIG_FLASH_MAPPED
#undef CONFIG_FLASH_PSTATE
#define CONFIG_SPI_FLASH
/****************************************************************************/
/* Customize the build */
@@ -91,12 +106,10 @@
#define CONFIG_SWITCH
#define CONFIG_MPU
#endif
#define CONFIG_DMA
#define CONFIG_FPU
#define CONFIG_I2C
#define CONFIG_LPC
#define CONFIG_FPU
#define CONFIG_SPI
#define CONFIG_DMA
#undef CONFIG_FLASH
#endif /* __CROS_EC_CONFIG_CHIP_H */

227
chip/mec1322/flash.c Normal file
View File

@@ -0,0 +1,227 @@
/* Copyright 2015 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.
*/
#include "common.h"
#include "console.h"
#include "flash.h"
#include "host_command.h"
#include "shared_mem.h"
#include "spi.h"
#include "spi_flash.h"
#include "system.h"
#include "util.h"
#include "watchdog.h"
#define PAGE_SIZE 256
/**
* Read from physical flash.
*
* @param offset Flash offset to write.
* @param size Number of bytes to write.
* @param data Destination buffer for data. Must be 32-bit aligned.
*/
int flash_physical_read(int offset, int size, char *data)
{
int ret;
/* Fail if offset, size, and data aren't at least word-aligned */
if ((offset | size | (uint32_t)(uintptr_t)data) & 3)
return EC_ERROR_INVAL;
spi_enable(1);
ret = spi_flash_read((uint8_t *)data, offset, size);
spi_enable(0);
return ret;
}
/**
* Write to physical flash.
*
* Offset and size must be a multiple of CONFIG_FLASH_WRITE_SIZE.
*
* @param offset Flash offset to write.
* @param size Number of bytes to write.
* @param data Data to write to flash. Must be 32-bit aligned.
*/
int flash_physical_write(int offset, int size, const char *data)
{
int ret, i, write_size;
/* Fail if offset, size, and data aren't at least word-aligned */
if ((offset | size | (uint32_t)(uintptr_t)data) & 3)
return EC_ERROR_INVAL;
spi_enable(1);
for (i = 0; i < size; i += write_size) {
write_size = MIN(size, SPI_FLASH_MAX_WRITE_SIZE);
ret = spi_flash_write(offset + i,
write_size,
(uint8_t *)data + i);
if (ret != EC_SUCCESS)
break;
/* BUG: Multi-page writes fail if no delay */
msleep(1);
}
spi_enable(0);
return ret;
}
/**
* Erase physical flash.
*
* Offset and size must be a multiple of CONFIG_FLASH_ERASE_SIZE.
*
* @param offset Flash offset to erase.
* @param size Number of bytes to erase.
*/
int flash_physical_erase(int offset, int size)
{
int ret;
spi_enable(1);
ret = spi_flash_erase(offset, size);
spi_enable(0);
return ret;
}
/**
* Read physical write protect setting for a flash bank.
*
* @param bank Bank index to check.
* @return non-zero if bank is protected until reboot.
*/
int flash_physical_get_protect(int bank)
{
uint32_t addr = bank * CONFIG_FLASH_BANK_SIZE;
int ret;
spi_enable(1);
ret = spi_flash_check_protect(addr, CONFIG_FLASH_BANK_SIZE);
spi_enable(0);
return ret;
}
/**
* Protect flash now.
*
* @param all Protect all (=1) or just read-only and pstate (=0).
* @return non-zero if error.
*/
int flash_physical_protect_now(int all)
{
int offset, size, ret;
if (all) {
offset = 0;
size = CONFIG_FLASH_PHYSICAL_SIZE;
} else {
offset = CONFIG_FW_RO_OFF;
size = CONFIG_FW_RO_SIZE;
}
spi_enable(1);
ret = spi_flash_set_protect(offset, size);
spi_enable(0);
return ret;
}
/**
* Return flash protect state flags from the physical layer.
*
* This should only be called by flash_get_protect().
*
* Uses the EC_FLASH_PROTECT_* flags from ec_commands.h
*/
uint32_t flash_physical_get_protect_flags(void)
{
uint32_t flags = 0;
spi_enable(1);
if (spi_flash_check_protect(CONFIG_FW_RO_OFF, CONFIG_FW_RO_SIZE)) {
flags |= EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW;
if (spi_flash_check_protect(CONFIG_FW_RW_OFF,
CONFIG_FW_RW_SIZE))
flags |= EC_FLASH_PROTECT_ALL_NOW;
}
spi_enable(0);
return flags;
}
/**
* Return the valid flash protect flags.
*
* @return A combination of EC_FLASH_PROTECT_* flags from ec_commands.h
*/
uint32_t flash_physical_get_valid_flags(void)
{
return EC_FLASH_PROTECT_RO_AT_BOOT |
EC_FLASH_PROTECT_RO_NOW |
EC_FLASH_PROTECT_ALL_NOW;
}
/**
* Return the writable flash protect flags.
*
* @param cur_flags The current flash protect flags.
* @return A combination of EC_FLASH_PROTECT_* flags from ec_commands.h
*/
uint32_t flash_physical_get_writable_flags(uint32_t cur_flags)
{
uint32_t ret = 0;
enum spi_flash_wp wp_status = spi_flash_check_wp();
if (wp_status == SPI_WP_NONE || (wp_status == SPI_WP_HARDWARE &&
!(cur_flags & EC_FLASH_PROTECT_GPIO_ASSERTED)))
ret = EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RO_NOW |
EC_FLASH_PROTECT_ALL_NOW;
return ret;
}
/**
* Enable write protect for the specified range.
*
* Once write protect is enabled, it will STAY enabled until the system is
* hard-rebooted with the hardware write protect pin deasserted. If the write
* protect pin is deasserted, the protect setting is ignored, and the entire
* flash will be writable.
*
* @param range The range to protect.
* @return EC_SUCCESS, or nonzero if error.
*/
int flash_physical_protect_at_boot(enum flash_wp_range range)
{
int offset, size, ret;
switch (range) {
case FLASH_WP_NONE:
offset = size = 0;
break;
case FLASH_WP_RO:
offset = CONFIG_FW_RO_OFF;
size = CONFIG_FW_RO_SIZE;
break;
case FLASH_WP_ALL:
offset = 0;
size = CONFIG_FLASH_PHYSICAL_SIZE;
break;
}
spi_enable(1);
ret = spi_flash_set_protect(offset, size);
spi_enable(0);
return ret;
}
/**
* Initialize the module.
*
* Applies at-boot protection settings if necessary.
*/
int flash_pre_init(void)
{
return EC_SUCCESS;
}

View File

@@ -369,3 +369,15 @@ void htimer_interrupt(void)
/* Time to wake up */
}
DECLARE_IRQ(MEC1322_IRQ_HTIMER, htimer_interrupt, 1);
/* TODO(crosbug.com/p/37510): Implement bootloader */
enum system_image_copy_t system_get_shrspi_image_copy(void)
{
return SYSTEM_IMAGE_RW;
}
/* TODO(crosbug.com/p/37510): Implement bootloader */
uint32_t system_get_lfw_address(uint32_t flash_addr)
{
return CONFIG_FW_RO_OFF;
}