mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 17:41:54 +00:00
nuc: Add SHI driver for arm-based platform in chip folder.
Add npcx_evb_arm board-level driver for arm-based platform. Add header.c: for booting from NPCX5M5G A3 Booter. Remove lfw folder due to those functionalitie have been replaced with Booter Modified drivers for Patch Set 1: 1. flash.c: Implement UMA lock, tri-state and selection register lock functionalities 2. hwtimer.c: Add ITIM32 for hwtimer 3. lpc.c: Add checking for LRESET 4. system.c: Modified CODERAM_ARCH functions for NPCX5M5G A3 Booter. 5. uart.c: Add support for module 2 Patch Set 2: 6. lpc.c: Modified lpc_get_pltrst_asserted() func Patch Set 3: 7. minimize the changes for CONFIG_CODERAM_ARCH in common layer 8. comments of Patch Set1/2 Patch Set 4: 9. Modified CONFIG_RO_MEM_OFF point to ro image and keep header as a part of ec.RO.flat. 10. Fixed RO_FRID and RW_FRID issues which caused by CONFIG_CODERAM_ARCH. Patch Set 5: 11. Modified system.c in common folder for supporting *_STORAGE_OFF. 12. Use *_STORAGE_OFF in firmware_image.lds.S to indicate flat file layout in flash. Patch Set 6: 13. rebase to newest version 14. system.c: Modified for the newest include/system.h Patch Set 7: 15. Merge from version 0625 BUG=chrome-os-partner:34346 TEST=make buildall -j; test nuvoton IC specific drivers BRANCH=none Change-Id: Ifd7c10b81b5781ccd75bb2558dc236486976e8ed Signed-off-by: Ian Chao <mlchao@nuvoton.com> Reviewed-on: https://chromium-review.googlesource.com/272034 Reviewed-by: Shawn N <shawnn@chromium.org> Tested-by: Shawn N <shawnn@chromium.org> Commit-Queue: Shawn N <shawnn@chromium.org>
This commit is contained in:
committed by
ChromeOS Commit Bot
parent
ccb6b15d51
commit
957638c78c
@@ -261,16 +261,6 @@ $(npcx-flash-fw-bin):
|
||||
-Wl,-Map,$(out)/$(npcx-flash-fw).map
|
||||
-@ $(OBJCOPY) -O binary $(out)/$(npcx-flash-fw).elf $@
|
||||
|
||||
# TODO: optional make rules for PROJECT_EXTRA
|
||||
$(npcx-lfw-bin):
|
||||
$(if $(V),,@echo ' EXTBIN ' $(subst $(out)/,,$@) ; )
|
||||
-@ mkdir -p $(@D)
|
||||
-@ $(CC) $(CFLAGS) -MMD -MF $(out)/$(npcx-lfw).d -c $(npcx-lfw).c \
|
||||
-o $(out)/$(npcx-lfw).o
|
||||
-@ $(CC) $(out)/$(npcx-lfw).o $(LDFLAGS) -o $(out)/$(npcx-lfw).elf \
|
||||
-Wl,-T,$(npcx-lfw).ld -Wl,-Map,$(out)/$(npcx-lfw).map
|
||||
-@ $(OBJCOPY) -O binary $(out)/$(npcx-lfw).elf $@
|
||||
|
||||
.PHONY: xrefs
|
||||
xrefs: $(call targ_if_prog,etags,$(out)/TAGS) \
|
||||
$(call targ_if_prog,ctags,$(out)/tags)
|
||||
|
||||
1
board/npcx_evb/Makefile
Symbolic link
1
board/npcx_evb/Makefile
Symbolic link
@@ -0,0 +1 @@
|
||||
../../Makefile
|
||||
@@ -97,7 +97,7 @@ const struct mft_t mft_channels[] = {
|
||||
.module = NPCX_MFT_MODULE_1,
|
||||
.port = NPCX_MFT_MODULE_PORT_TA,
|
||||
.default_count = 0xFFFF,
|
||||
#ifdef CONFIG_MFT_INPUT_LFCLK
|
||||
#ifdef NPCX_MFT_INPUT_LFCLK
|
||||
.freq = 32768,
|
||||
#else
|
||||
.freq = 2000000,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#define CONFIG_PECI
|
||||
#define CONFIG_PWM
|
||||
#define CONFIG_SPI
|
||||
#define CONFIG_LPC /* Used in Intel-based platform for host interface */
|
||||
|
||||
/* Optional features */
|
||||
#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands for testing */
|
||||
@@ -42,8 +43,12 @@
|
||||
#define CONFIG_FANS 1
|
||||
|
||||
/* Optional feature - used by nuvoton */
|
||||
#define CONFIG_PWM_INPUT_LFCLK /* PWM use LFCLK for input clock */
|
||||
#define CONFIG_MFT_INPUT_LFCLK /* MFT use LFCLK for input clock */
|
||||
#define NPCX_PWM_INPUT_LFCLK /* PWM use LFCLK for input clock */
|
||||
#define NPCX_MFT_INPUT_LFCLK /* MFT use LFCLK for input clock */
|
||||
#define NPCX_I2C0_BUS2 0 /* 0:GPIOB4/B5 1:GPIOB2/B3 as I2C0 */
|
||||
#define NPCX_UART_MODULE2 0 /* 0:GPIO10/11 1:GPIO64/65 as UART */
|
||||
#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/
|
||||
#define NPCX_TACH_SEL2 0 /* 0:GPIO40/A4 1:GPIO93/D3 as TACH */
|
||||
|
||||
/* Optional for testing */
|
||||
#undef CONFIG_PSTORE
|
||||
|
||||
@@ -5,20 +5,22 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/********************** Inputs with interrupt handlers are first for efficiency **********************/
|
||||
/* TODO: Redefine debug 2 inputs */
|
||||
GPIO_INT(RECOVERY_L, PIN(0, 0), GPIO_PULL_UP | GPIO_INT_BOTH, switch_interrupt) /* Recovery signal from servo */
|
||||
GPIO_INT(WP_L, PIN(9, 3), GPIO_PULL_DOWN | GPIO_INT_BOTH, switch_interrupt) /* Write protect input */
|
||||
GPIO_INT(RECOVERY_L, PIN(0, 0), GPIO_PULL_UP | GPIO_INT_BOTH, switch_interrupt) /* Recovery signal from servo */
|
||||
GPIO_INT(WP_L, PIN(9, 3), GPIO_PULL_DOWN | GPIO_INT_BOTH, switch_interrupt) /* Write protect input */
|
||||
|
||||
/* For testing 8042 commands, we need the following GPIOs */
|
||||
/* For testing keyboard commands, we need the following 4 GPIOs */
|
||||
/* TODO: Redefine 4 inputs */
|
||||
GPIO_INT(POWER_BUTTON_L, PIN(0, 2), GPIO_PULL_UP | GPIO_INT_BOTH, power_button_interrupt) /* Power button */
|
||||
GPIO_INT(LID_OPEN, PIN(3, 3), GPIO_PULL_DOWN | GPIO_INT_BOTH, lid_interrupt) /* Lid switch */
|
||||
GPIO_INT(POWER_BUTTON_L, PIN(0, 2), GPIO_PULL_UP | GPIO_INT_BOTH, power_button_interrupt) /* Power button */
|
||||
GPIO_INT(LID_OPEN, PIN(3, 3), GPIO_PULL_DOWN | GPIO_INT_BOTH, lid_interrupt) /* Lid switch */
|
||||
|
||||
/**************************** Need a empty line between GPIO_INT and GPIO ****************************/
|
||||
GPIO(ENTERING_RW, PIN(3, 6), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */
|
||||
GPIO(PCH_WAKE_L, PIN(5, 0), GPIO_OUT_HIGH) /* Wake signal output to PCH */
|
||||
|
||||
/* Used for module testing */
|
||||
GPIO(PGOOD_FAN, PIN(C, 7), GPIO_PULL_UP | GPIO_INPUT) /* Power Good for FAN test */
|
||||
GPIO(PGOOD_FAN, PIN(C, 7), GPIO_PULL_UP | GPIO_INPUT) /* Power Good for FAN test */
|
||||
GPIO(SPI_CS_L, PIN(A, 5), GPIO_OUT_HIGH) /* SPI_CS Ready, Low Active. */
|
||||
|
||||
/*
|
||||
@@ -35,14 +37,28 @@ GPIO(BOARD_VERSION3, PIN(6, 6), GPIO_INPUT) /* Board version stuffing r
|
||||
#ifdef CONFIG_KEYBOARD_COL2_INVERTED
|
||||
GPIO(KBD_KSO2, PIN(1, 7), GPIO_OUT_LOW) /* Negative edge triggered keyboard irq. */
|
||||
#endif
|
||||
|
||||
/**************************** Alternate pins for UART/I2C/ADC/SPI/PWM/MFT ****************************/
|
||||
/* Alternate pins for UART/I2C/ADC/SPI/PWM/MFT */
|
||||
#if NPCX_UART_MODULE2
|
||||
ALTERNATE(PIN_MASK(6, 0x30), 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO64/65 */
|
||||
#else
|
||||
ALTERNATE(PIN_MASK(1, 0x03), 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO10/11 */
|
||||
ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB4/B5 */
|
||||
#endif
|
||||
#if NPCX_I2C0_BUS2
|
||||
ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB2/B3 */
|
||||
#else
|
||||
ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB4/B5 */
|
||||
#endif
|
||||
ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1SDA GPIO87 */
|
||||
ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1SCL/I2C2SDA/I2C2SCL GPIO90/91/92 */
|
||||
ALTERNATE(PIN_MASK(4, 0x38), 1, MODULE_ADC, 0) /* ADC GPIO45/44/43 */
|
||||
ALTERNATE(PIN_MASK(A, 0x0A), 1, MODULE_SPI, 0) /* SPIP_MOSI/SPIP_SCLK GPIOA3/A1 */
|
||||
ALTERNATE(PIN_MASK(A, 0x0A), 1, MODULE_SPI, 0) /* SPIP_MOSI/SPIP_SCLK GPIOA3/A1 */
|
||||
ALTERNATE(PIN_MASK(9, 0x20), 1, MODULE_SPI, 0) /* SPIP_MISO GPIO95 */
|
||||
ALTERNATE(PIN_MASK(C, 0x04), 3, MODULE_PWM_KBLIGHT, 0) /* PWM1 for PWM/KBLIGHT Test GPIOC2 */
|
||||
ALTERNATE(PIN_MASK(C, 0x08), 7, MODULE_PWM_FAN, 0) /* PWM0 for PWM/FAN Test GPIOC3 */
|
||||
#if NPCX_TACH_SEL2
|
||||
ALTERNATE(PIN_MASK(9, 0x08), 3, MODULE_PWM_FAN, 0) /* MFT-1/TA1_TACH1 for FAN GPIO93 */
|
||||
#else
|
||||
ALTERNATE(PIN_MASK(4, 0x01), 3, MODULE_PWM_FAN, 0) /* MFT-1/TA1_TACH1 for FAN Test GPIO40 */
|
||||
#endif
|
||||
|
||||
1
board/npcx_evb_arm/Makefile
Symbolic link
1
board/npcx_evb_arm/Makefile
Symbolic link
@@ -0,0 +1 @@
|
||||
../../Makefile
|
||||
131
board/npcx_evb_arm/board.c
Normal file
131
board/npcx_evb_arm/board.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/* 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.
|
||||
*/
|
||||
/* EC for Nuvoton M4 EB configuration */
|
||||
|
||||
#include "adc.h"
|
||||
#include "adc_chip.h"
|
||||
#include "backlight.h"
|
||||
#include "chipset.h"
|
||||
#include "common.h"
|
||||
#include "driver/temp_sensor/tmp006.h"
|
||||
#include "extpower.h"
|
||||
#include "fan.h"
|
||||
#include "fan_chip.h"
|
||||
#include "gpio.h"
|
||||
#include "i2c.h"
|
||||
#include "keyboard_scan.h"
|
||||
#include "lid_switch.h"
|
||||
#include "peci.h"
|
||||
#include "power.h"
|
||||
#include "power_button.h"
|
||||
#include "pwm.h"
|
||||
#include "pwm_chip.h"
|
||||
#include "registers.h"
|
||||
#include "switch.h"
|
||||
#include "temp_sensor.h"
|
||||
#include "temp_sensor_chip.h"
|
||||
#include "timer.h"
|
||||
#include "thermal.h"
|
||||
#include "util.h"
|
||||
#include "shi_chip.h"
|
||||
|
||||
#include "gpio_list.h"
|
||||
|
||||
/******************************************************************************/
|
||||
/* ADC channels. Must be in the exactly same order as in enum adc_channel. */
|
||||
const struct adc_t adc_channels[] = {
|
||||
[ADC_CH_0] = {"ADC0", NPCX_ADC_INPUT_CH0, ADC_MAX_VOLT,
|
||||
ADC_READ_MAX+1, 0},
|
||||
[ADC_CH_1] = {"ADC1", NPCX_ADC_INPUT_CH1, ADC_MAX_VOLT,
|
||||
ADC_READ_MAX+1, 0},
|
||||
[ADC_CH_2] = {"ADC2", NPCX_ADC_INPUT_CH2, ADC_MAX_VOLT,
|
||||
ADC_READ_MAX+1, 0},
|
||||
};
|
||||
BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT);
|
||||
|
||||
/******************************************************************************/
|
||||
/* PWM channels. Must be in the exactly same order as in enum pwm_channel. */
|
||||
const struct pwm_t pwm_channels[] = {
|
||||
[PWM_CH_FAN] = {
|
||||
.channel = 0,
|
||||
/*
|
||||
* flags can reverse the PWM output signal according to
|
||||
* the board design
|
||||
*/
|
||||
.flags = PWM_CONFIG_ACTIVE_LOW,
|
||||
/*
|
||||
* freq_operation = freq_input / prescaler_divider
|
||||
* freq_output = freq_operation / cycle_pulses
|
||||
* and freq_output <= freq_mft
|
||||
*/
|
||||
.freq = 34,
|
||||
/*
|
||||
* cycle_pulses = (cycle_pulses * freq_output) *
|
||||
* RPM_EDGES * RPM_SCALE * 60 / poles / rpm_min
|
||||
*/
|
||||
.cycle_pulses = 480,
|
||||
},
|
||||
[PWM_CH_KBLIGHT] = {
|
||||
.channel = 1,
|
||||
.flags = 0,
|
||||
.freq = 10000,
|
||||
.cycle_pulses = 100,
|
||||
},
|
||||
};
|
||||
BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT);
|
||||
|
||||
/******************************************************************************/
|
||||
/* Physical fans. These are logically separate from pwm_channels. */
|
||||
const struct fan_t fans[] = {
|
||||
[FAN_CH_0] = {
|
||||
.flags = FAN_USE_RPM_MODE,
|
||||
.rpm_min = 1020,
|
||||
.rpm_start = 1020,
|
||||
.rpm_max = 8190,
|
||||
.ch = 0,/* Use PWM/MFT to control fan */
|
||||
.pgood_gpio = GPIO_PGOOD_FAN,
|
||||
.enable_gpio = -1,
|
||||
},
|
||||
};
|
||||
BUILD_ASSERT(ARRAY_SIZE(fans) == FAN_CH_COUNT);
|
||||
|
||||
/******************************************************************************/
|
||||
/* MFT channels. These are logically separate from mft_channels. */
|
||||
const struct mft_t mft_channels[] = {
|
||||
[MFT_CH_0] = {
|
||||
.module = NPCX_MFT_MODULE_1,
|
||||
.port = NPCX_MFT_MODULE_PORT_TA,
|
||||
.default_count = 0xFFFF,
|
||||
#ifdef NPCX_MFT_INPUT_LFCLK
|
||||
.freq = 32768,
|
||||
#else
|
||||
.freq = 2000000,
|
||||
#endif
|
||||
},
|
||||
};
|
||||
BUILD_ASSERT(ARRAY_SIZE(mft_channels) == MFT_CH_COUNT);
|
||||
|
||||
/******************************************************************************/
|
||||
/* I2C ports */
|
||||
const struct i2c_port_t i2c_ports[] = {
|
||||
{"master", I2C_PORT_MASTER, 100,
|
||||
GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA},
|
||||
};
|
||||
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
|
||||
|
||||
/******************************************************************************/
|
||||
/* Keyboard scan setting */
|
||||
struct keyboard_scan_config keyscan_config = {
|
||||
.output_settle_us = 40,
|
||||
.debounce_down_us = 6 * MSEC,
|
||||
.debounce_up_us = 30 * MSEC,
|
||||
.scan_period_us = 1500,
|
||||
.min_post_scan_delay_us = 1000,
|
||||
.poll_timeout_us = SECOND,
|
||||
.actual_key_mask = {
|
||||
0x14, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff,
|
||||
0xa4, 0xff, 0xf6, 0x55, 0xfa, 0xc8 /* full set */
|
||||
},
|
||||
};
|
||||
90
board/npcx_evb_arm/board.h
Normal file
90
board/npcx_evb_arm/board.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Configuration for Nuvoton M4 EB */
|
||||
|
||||
#ifndef __CROS_EC_BOARD_H
|
||||
#define __CROS_EC_BOARD_H
|
||||
|
||||
/* Support Code RAM architecture (Run code in RAM) */
|
||||
#define CONFIG_CODERAM_ARCH
|
||||
|
||||
/* Optional modules */
|
||||
#define CONFIG_ADC
|
||||
#define CONFIG_PWM
|
||||
#define CONFIG_SHI /* Used in ARM-based platform for host interface */
|
||||
|
||||
/* Optional features */
|
||||
#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands for testing */
|
||||
#define CONFIG_SPI_FLASH_SIZE 0x00800000 /* 8MB spi flash */
|
||||
#define CONFIG_SPI_FLASH_W25Q64
|
||||
#define CONFIG_KEYBOARD_BOARD_CONFIG
|
||||
#define CONFIG_KEYBOARD_PROTOCOL_MKBP /* Instead of 8042 protocol of keyboard */
|
||||
#define CONFIG_POWER_BUTTON
|
||||
#define CONFIG_VBOOT_HASH
|
||||
#define CONFIG_PWM_KBLIGHT
|
||||
#define CONFIG_BOARD_VERSION
|
||||
|
||||
/* Optional features for test commands */
|
||||
#define CONFIG_CMD_TASKREADY
|
||||
#define CONFIG_CMD_STACKOVERFLOW
|
||||
#define CONFIG_CMD_JUMPTAGS
|
||||
#define CONFIG_CMD_FLASH
|
||||
#define CONFIG_CMD_SPI_FLASH
|
||||
#define CONFIG_CMD_SCRATCHPAD
|
||||
#define CONFIG_CMD_I2CWEDGE
|
||||
|
||||
#define CONFIG_UART_HOST 0
|
||||
#define CONFIG_FANS 1
|
||||
|
||||
/* Optional feature - used by nuvoton */
|
||||
#define NPCX_PWM_INPUT_LFCLK /* PWM use LFCLK for input clock */
|
||||
#define NPCX_MFT_INPUT_LFCLK /* MFT use LFCLK for input clock */
|
||||
#define NPCX_I2C0_BUS2 0 /* 0:GPIOB4/B5 1:GPIOB2/B3 as I2C0 */
|
||||
#define NPCX_UART_MODULE2 0 /* 0:GPIO10/11 1:GPIO64/65 as UART */
|
||||
#define NPCX_JTAG_MODULE2 0 /* 0:GPIO21/17/16/20 1:GPIOD5/E2/D4/E5 as JTAG*/
|
||||
#define NPCX_TACH_SEL2 0 /* 0:GPIO40/A4 1:GPIO93/D3 as TACH */
|
||||
|
||||
/* Optional for testing */
|
||||
#undef CONFIG_PSTORE
|
||||
#undef CONFIG_LOW_POWER_IDLE /* Deep Sleep Support */
|
||||
|
||||
/* Single I2C port, where the EC is the master. */
|
||||
#define I2C_PORT_MASTER 0
|
||||
#define I2C_PORT_HOST 0
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
enum adc_channel {
|
||||
ADC_CH_0 = 0,
|
||||
ADC_CH_1,
|
||||
ADC_CH_2,
|
||||
ADC_CH_COUNT
|
||||
};
|
||||
|
||||
enum pwm_channel {
|
||||
PWM_CH_FAN,
|
||||
PWM_CH_KBLIGHT,
|
||||
/* Number of PWM channels */
|
||||
PWM_CH_COUNT
|
||||
};
|
||||
|
||||
enum fan_channel {
|
||||
FAN_CH_0,
|
||||
/* Number of FAN channels */
|
||||
FAN_CH_COUNT
|
||||
};
|
||||
|
||||
enum mft_channel {
|
||||
MFT_CH_0,
|
||||
/* Number of MFT channels */
|
||||
MFT_CH_COUNT
|
||||
};
|
||||
|
||||
#include "gpio_signal.h"
|
||||
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
|
||||
#endif /* __CROS_EC_BOARD_H */
|
||||
12
board/npcx_evb_arm/build.mk
Normal file
12
board/npcx_evb_arm/build.mk
Normal file
@@ -0,0 +1,12 @@
|
||||
# -*- makefile -*-
|
||||
# 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.
|
||||
#
|
||||
# Board specific files build
|
||||
#
|
||||
|
||||
# the IC is Nuvoton M-Series EC
|
||||
CHIP:=npcx
|
||||
|
||||
board-y=board.o
|
||||
23
board/npcx_evb_arm/ec.tasklist
Normal file
23
board/npcx_evb_arm/ec.tasklist
Normal file
@@ -0,0 +1,23 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* List of enabled tasks in the priority order
|
||||
*
|
||||
* The first one has the lowest priority.
|
||||
*
|
||||
* For each task, use the macro TASK_ALWAYS(n, r, d, s) for base tasks and
|
||||
* TASK_NOTEST(n, r, d, s) for tasks that can be excluded in test binaries,
|
||||
* where :
|
||||
* 'n' is the name of the task
|
||||
* 'r' is the main routine of the task
|
||||
* 'd' is an opaque parameter passed to the routine at startup
|
||||
* 's' is the stack size in bytes; must be a multiple of 8
|
||||
*/
|
||||
#define CONFIG_TASK_LIST \
|
||||
TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \
|
||||
TASK_ALWAYS(HOSTCMD, host_command_task, NULL, TASK_STACK_SIZE) \
|
||||
TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \
|
||||
TASK_NOTEST(KEYSCAN, keyboard_scan_task, NULL, TASK_STACK_SIZE)
|
||||
64
board/npcx_evb_arm/gpio.inc
Normal file
64
board/npcx_evb_arm/gpio.inc
Normal file
@@ -0,0 +1,64 @@
|
||||
/* -*- mode:c -*-
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/********************** Inputs with interrupt handlers are first for efficiency **********************/
|
||||
/* TODO: Redefine debug 2 inputs */
|
||||
GPIO_INT(RECOVERY_L, PIN(0, 0), GPIO_PULL_UP | GPIO_INT_BOTH, switch_interrupt) /* Recovery signal from servo */
|
||||
GPIO_INT(WP_L, PIN(9, 3), GPIO_PULL_DOWN | GPIO_INT_BOTH, switch_interrupt) /* Write protect input */
|
||||
/* Used for ARM based platform */
|
||||
GPIO_INT(SHI_CS_L, PIN(5, 3), GPIO_INT_FALLING,shi_cs_event) /* SHI CS Ready, Low Active. */
|
||||
/* For testing keyboard commands, we need the following 4 GPIOs */
|
||||
/* TODO: Redefine 4 inputs */
|
||||
GPIO_INT(POWER_BUTTON_L, PIN(0, 2), GPIO_PULL_UP | GPIO_INT_BOTH, power_button_interrupt) /* Power button */
|
||||
GPIO_INT(LID_OPEN, PIN(3, 3), GPIO_PULL_DOWN | GPIO_INT_BOTH, lid_interrupt) /* Lid switch */
|
||||
|
||||
/**************************** Need a empty line between GPIO_INT and GPIO ****************************/
|
||||
GPIO(ENTERING_RW, PIN(3, 6), GPIO_OUT_LOW) /* Indicate when EC is entering RW code */
|
||||
GPIO(PCH_WAKE_L, PIN(5, 0), GPIO_OUT_HIGH) /* Wake signal output to PCH */
|
||||
/* For testing keyboard mkbp */
|
||||
GPIO(EC_INT, PIN(7, 4), GPIO_ODR_HIGH) /* Interrupt pin for keyboard mkbp */
|
||||
/* Used for module testing */
|
||||
GPIO(PGOOD_FAN, PIN(C, 7), GPIO_PULL_UP | GPIO_INPUT) /* Power Good for FAN test */
|
||||
|
||||
/*
|
||||
* I2C pins should be configured as inputs until I2C module is
|
||||
* initialized. This will avoid driving the lines unintentionally.
|
||||
*/
|
||||
GPIO(MASTER_I2C_SCL, PIN(B, 5), GPIO_INPUT)
|
||||
GPIO(MASTER_I2C_SDA, PIN(B, 4), GPIO_INPUT)
|
||||
/* Used for board version command */
|
||||
GPIO(BOARD_VERSION1, PIN(6, 4), GPIO_INPUT) /* Board version stuffing resistor 1 */
|
||||
GPIO(BOARD_VERSION2, PIN(6, 5), GPIO_INPUT) /* Board version stuffing resistor 2 */
|
||||
GPIO(BOARD_VERSION3, PIN(6, 6), GPIO_INPUT) /* Board version stuffing resistor 3 */
|
||||
#ifdef CONFIG_KEYBOARD_COL2_INVERTED
|
||||
GPIO(KBD_KSO2, PIN(1, 7), GPIO_OUT_LOW) /* Negative edge triggered keyboard irq. */
|
||||
#endif
|
||||
|
||||
/**************************** Alternate pins for UART/I2C/ADC/SPI/PWM/MFT ****************************/
|
||||
/* Alternate pins for UART/I2C/ADC/SPI/PWM/MFT */
|
||||
#if NPCX_UART_MODULE2
|
||||
ALTERNATE(PIN_MASK(6, 0x30), 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO64/65 */
|
||||
#else
|
||||
ALTERNATE(PIN_MASK(1, 0x03), 1, MODULE_UART, 0) /* CR_SIN/SOUT GPIO10/11 */
|
||||
#endif
|
||||
#if NPCX_I2C0_BUS2
|
||||
ALTERNATE(PIN_MASK(B, 0x0C), 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB2/B3 */
|
||||
#else
|
||||
ALTERNATE(PIN_MASK(B, 0x30), 1, MODULE_I2C, 0) /* I2C0SDA/I2C0SCL GPIOB4/B5 */
|
||||
#endif
|
||||
ALTERNATE(PIN_MASK(8, 0x80), 1, MODULE_I2C, 0) /* I2C1SDA GPIO87 */
|
||||
ALTERNATE(PIN_MASK(9, 0x07), 1, MODULE_I2C, 0) /* I2C1SCL/I2C2SDA/I2C2SCL GPIO90/91/92 */
|
||||
ALTERNATE(PIN_MASK(4, 0x38), 1, MODULE_ADC, 0) /* ADC GPIO45/44/43 */
|
||||
ALTERNATE(PIN_MASK(A, 0x0A), 1, MODULE_SPI, 0) /* SPIP_MOSI/SPIP_SCLK GPIOA3/A1 */
|
||||
ALTERNATE(PIN_MASK(9, 0x20), 1, MODULE_SPI, 0) /* SPIP_MISO GPIO95 */
|
||||
ALTERNATE(PIN_MASK(C, 0x04), 3, MODULE_PWM_KBLIGHT, 0) /* PWM1 for PWM/KBLIGHT Test GPIOC2 */
|
||||
ALTERNATE(PIN_MASK(C, 0x08), 7, MODULE_PWM_FAN, 0) /* PWM0 for PWM/FAN Test GPIOC3 */
|
||||
#if NPCX_TACH_SEL2
|
||||
ALTERNATE(PIN_MASK(9, 0x08), 3, MODULE_PWM_FAN, 0) /* MFT-1/TA1_TACH1 for FAN GPIO93 */
|
||||
#else
|
||||
ALTERNATE(PIN_MASK(4, 0x01), 3, MODULE_PWM_FAN, 0) /* MFT-1/TA1_TACH1 for FAN Test GPIO40 */
|
||||
#endif
|
||||
@@ -12,7 +12,7 @@ CORE:=cortex-m
|
||||
CFLAGS_CPU+=-march=armv7e-m -mcpu=cortex-m4
|
||||
|
||||
# Required chip modules
|
||||
chip-y=clock.o gpio.o hwtimer.o jtag.o system.o uart.o
|
||||
chip-y=header.o clock.o gpio.o hwtimer.o jtag.o system.o uart.o
|
||||
|
||||
# Optional chip modules
|
||||
chip-$(CONFIG_ADC)+=adc.o
|
||||
@@ -21,17 +21,13 @@ chip-$(CONFIG_FLASH)+=flash.o
|
||||
chip-$(CONFIG_I2C)+=i2c.o
|
||||
chip-$(CONFIG_LPC)+=lpc.o
|
||||
chip-$(CONFIG_PECI)+=peci.o
|
||||
chip-$(CONFIG_SHI)+=shi.o
|
||||
# pwm functions are implemented with the fan functions
|
||||
chip-$(CONFIG_PWM)+=pwm.o fan.o
|
||||
chip-$(CONFIG_SPI)+=spi.o
|
||||
chip-$(CONFIG_WATCHDOG)+=watchdog.o
|
||||
chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o
|
||||
|
||||
# little FW for booting
|
||||
npcx-lfw=chip/npcx/lfw/ec_lfw
|
||||
npcx-lfw-bin=${out}/$(npcx-lfw).bin
|
||||
PROJECT_EXTRA+=${npcx-lfw-bin}
|
||||
|
||||
# spi flash program fw for openocd
|
||||
npcx-flash-fw=chip/npcx/spiflashfw/ec_npcxflash
|
||||
npcx-flash-fw-bin=${out}/$(npcx-flash-fw).bin
|
||||
|
||||
@@ -175,7 +175,7 @@ int clock_get_apb2_freq(void)
|
||||
void clock_wait_cycles(uint32_t cycles)
|
||||
{
|
||||
asm("1: subs %0, #1\n"
|
||||
" bne 1b\n" :: "r"(cycles));
|
||||
" bne 1b\n" : : "r"(cycles));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LOW_POWER_IDLE
|
||||
@@ -190,35 +190,30 @@ void clock_refresh_console_in_use(void)
|
||||
void clock_uart2gpio(void)
|
||||
{
|
||||
/* Is pimux to UART? */
|
||||
if (IS_BIT_SET(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL)) {
|
||||
if (npcx_is_uart()) {
|
||||
/* Change pinmux to GPIO and disable UART IRQ */
|
||||
task_disable_irq(NPCX_IRQ_UART);
|
||||
CLEAR_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL);
|
||||
|
||||
/*Enable MIWU for GPIO (UARTRX) */
|
||||
SET_BIT(NPCX_WKEN(1, 1), 0);
|
||||
/* Set to GPIO */
|
||||
npcx_uart2gpio();
|
||||
/* Enable MIWU for GPIO (UARTRX) */
|
||||
npcx_enable_wakeup(1);
|
||||
/* Clear Pending bit of GPIO (UARTRX) */
|
||||
if (IS_BIT_SET(NPCX_WKPND(1, 1), 0))
|
||||
SET_BIT(NPCX_WKPCL(1, 1), 0);
|
||||
/* Disable MIWU IRQ */
|
||||
task_disable_irq(NPCX_IRQ_WKINTB_1);
|
||||
npcx_clear_wakeup_event();
|
||||
}
|
||||
}
|
||||
|
||||
void clock_gpio2uart(void)
|
||||
{
|
||||
/* Is Pending bit of GPIO (UARTRX) */
|
||||
if (IS_BIT_SET(NPCX_WKPND(1, 1), 0)) {
|
||||
if (npcx_is_wakeup_from_gpio()) {
|
||||
/* Clear Pending bit of GPIO (UARTRX) */
|
||||
SET_BIT(NPCX_WKPCL(1, 1), 0);
|
||||
uart_clear_wakeup_event();
|
||||
/* Refresh console in-use timer */
|
||||
clock_refresh_console_in_use();
|
||||
/* Disable MIWU & IRQ for GPIO (UARTRX) */
|
||||
CLEAR_BIT(NPCX_WKEN(1, 1), 0);
|
||||
/* Enable MIWU IRQ */
|
||||
task_enable_irq(NPCX_IRQ_WKINTB_1);
|
||||
/* Disable MIWU for GPIO (UARTRX) */
|
||||
uart_enable_miwu_wakeup(0);
|
||||
/* Go back CR_SIN*/
|
||||
SET_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL);
|
||||
npcx_gpio2uart();
|
||||
/* Enable uart again */
|
||||
task_enable_irq(NPCX_IRQ_UART);
|
||||
}
|
||||
@@ -227,7 +222,7 @@ void clock_gpio2uart(void)
|
||||
/* Idle task. Executed when no tasks are ready to be scheduled. */
|
||||
void __idle(void)
|
||||
{
|
||||
#ifdef SUPPORT_JTAG
|
||||
#if (CHIP_VERSION < 3)
|
||||
while (1) {
|
||||
/*
|
||||
* TODO:(ML) JTAG bug: if debugger is connected,
|
||||
|
||||
@@ -35,9 +35,9 @@
|
||||
/*****************************************************************************/
|
||||
/* Memory mapping */
|
||||
#define CONFIG_RAM_BASE 0x200C0000 /* memory map address of data ram */
|
||||
#define CONFIG_RAM_SIZE 0x00008000 /* 32KB data ram */
|
||||
#define CONFIG_CDRAM_BASE 0x10088000 /* memory map address of code ram */
|
||||
#define CONFIG_CDRAM_SIZE 0x00020000 /* 128KB code ram */
|
||||
#define CONFIG_RAM_SIZE (0x00008000 - 0x800) /* 30KB data ram */
|
||||
#define CONFIG_CDRAM_BASE 0x100A8000 /* memory map address of code ram */
|
||||
#define CONFIG_CDRAM_SIZE 0x00018000 /* 96KB code ram */
|
||||
#define CONFIG_FLASH_BASE 0x64000000 /* memory address of spi-flash */
|
||||
#define CONFIG_LPRAM_BASE 0x40001600 /* memory address of low power ram */
|
||||
#define CONFIG_LPRAM_SIZE 0x00000620 /* 1568B low power ram */
|
||||
@@ -61,38 +61,44 @@
|
||||
#define CONFIG_FLASH_ERASE_SIZE 0x00001000 /* sector erase size 4K bytes */
|
||||
#define CONFIG_FLASH_WRITE_SIZE 0x00000001 /* minimum write size */
|
||||
|
||||
#define CONFIG_FLASH_WRITE_IDEAL_SIZE 256 /* one page size for write */
|
||||
#define CONFIG_FLASH_PHYSICAL_SIZE 0x00040000 /* 256KB Flash used for EC */
|
||||
#define CONFIG_FLASH_WRITE_IDEAL_SIZE 256 /* one page size for write */
|
||||
/* 128 KB alignment for SPI status registers protection */
|
||||
#define CONFIG_FLASH_PHYSICAL_SIZE 0x40000 /* 256 KB Flash used for EC */
|
||||
|
||||
/* No PSTATE; uses a real SPI flash */
|
||||
#undef CONFIG_FLASH_PSTATE
|
||||
|
||||
/* Header support which is used by booter to copy FW from flash to code ram */
|
||||
#define NPCX_RO_HEADER
|
||||
|
||||
/****************************************************************************/
|
||||
/* Define our flash layout. */
|
||||
/* Define npcx flash layout. */
|
||||
/* Size of one firmware image in flash */
|
||||
#ifndef CONFIG_FW_IMAGE_SIZE
|
||||
#define CONFIG_FW_IMAGE_SIZE (CONFIG_FLASH_PHYSICAL_SIZE / 2)
|
||||
#endif
|
||||
|
||||
/* RO firmware offset of flash */
|
||||
#define CONFIG_RO_MEM_OFF 0
|
||||
/* The storage offset of ec.RO.flat which is used for CONFIG_CDRAM_ARCH */
|
||||
#define CONFIG_RO_STORAGE_OFF 0
|
||||
#define CONFIG_RO_SIZE CONFIG_FW_IMAGE_SIZE
|
||||
#ifdef NPCX_RO_HEADER
|
||||
#define CONFIG_RO_HDR_MEM_OFF 0x0
|
||||
#define CONFIG_RO_HDR_SIZE 0x40
|
||||
/* RO firmware offset in flash */
|
||||
#define CONFIG_RO_MEM_OFF CONFIG_RO_HDR_SIZE
|
||||
#else
|
||||
#define CONFIG_RO_MEM_OFF 0x0
|
||||
#endif
|
||||
#define CONFIG_RO_SIZE CONFIG_CDRAM_SIZE /* 96KB for RO FW */
|
||||
#define CONFIG_FLASH_SIZE CONFIG_FLASH_PHYSICAL_SIZE
|
||||
|
||||
/* RW firmware is one firmware image offset from the start */
|
||||
#define CONFIG_RW_MEM_OFF CONFIG_FW_IMAGE_SIZE
|
||||
#define CONFIG_RW_STORAGE_OFF CONFIG_FW_IMAGE_SIZE
|
||||
#define CONFIG_RW_SIZE CONFIG_FW_IMAGE_SIZE
|
||||
/* The storage offset of ec.RW.flat which is used for CONFIG_CDRAM_ARCH */
|
||||
#define CONFIG_RW_STORAGE_OFF CONFIG_FW_IMAGE_SIZE /* 128 KB alignemnt */
|
||||
/* RW firmware offset in flash */
|
||||
#define CONFIG_RW_MEM_OFF CONFIG_RW_STORAGE_OFF
|
||||
#define CONFIG_RW_SIZE CONFIG_CDRAM_SIZE /* 96KB for RW FW */
|
||||
|
||||
#define CONFIG_WP_OFF CONFIG_RO_STORAGE_OFF
|
||||
#define CONFIG_WP_SIZE CONFIG_RO_SIZE
|
||||
|
||||
/*
|
||||
* The offset from top of flash wich used by booter
|
||||
* the main funcationality to copy iamge from spi-flash to code ram
|
||||
*/
|
||||
#define CONFIG_LFW_OFFSET 0x1000
|
||||
#define CONFIG_WP_SIZE CONFIG_FW_IMAGE_SIZE
|
||||
|
||||
/****************************************************************************/
|
||||
/* Customize the build */
|
||||
@@ -101,11 +107,9 @@
|
||||
#define CONFIG_ADC
|
||||
#define CONFIG_FPU
|
||||
#define CONFIG_I2C
|
||||
#define CONFIG_LPC
|
||||
#define CONFIG_PECI
|
||||
#define CONFIG_SWITCH
|
||||
#define CONFIG_MPU
|
||||
#define CONFIG_SPI
|
||||
|
||||
/* Compile for running from RAM instead of flash */
|
||||
/* #define COMPILE_FOR_RAM */
|
||||
|
||||
@@ -114,7 +114,7 @@ static void mft_startmeasure(int ch)
|
||||
int mft_ch = fan_op_ch(ch, NPCX_FAN_OP_MFT);
|
||||
|
||||
/* Start measurement */
|
||||
#ifdef CONFIG_MFT_INPUT_LFCLK
|
||||
#ifdef NPCX_MFT_INPUT_LFCLK
|
||||
/* Set the LFCLK clock. */
|
||||
if (NPCX_MFT_MODULE_PORT_TB == mft_channels[mft_ch].port)
|
||||
NPCX_TCKC(mft_channels[mft_ch].module) =
|
||||
@@ -199,7 +199,7 @@ static void mft_finalmeasure(int ch)
|
||||
* @return none
|
||||
* @notes changed when initial or HOOK_FREQ_CHANGE command
|
||||
*/
|
||||
#ifndef CONFIG_MFT_INPUT_LFCLK
|
||||
#ifndef NPCX_MFT_INPUT_LFCLK
|
||||
void mft_freq_changed(void)
|
||||
{
|
||||
uint16_t prescaler_divider = 0;
|
||||
@@ -243,7 +243,7 @@ static void fan_config(int ch, int enable_mft_read_rpm)
|
||||
& (~(((1<<3)-1)<<NPCX_TMCTRL_MDSEL)))
|
||||
| (NPCX_MFT_MDSEL_5<<NPCX_TMCTRL_MDSEL);
|
||||
|
||||
#ifndef CONFIG_MFT_INPUT_LFCLK
|
||||
#ifndef NPCX_MFT_INPUT_LFCLK
|
||||
/* Set MFT operation frequence */
|
||||
mft_freq_changed();
|
||||
/* Set the active power mode. */
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
int all_protected; /* Has all-flash protection been requested? */
|
||||
int addr_prot_start;
|
||||
int addr_prot_length;
|
||||
uint8_t flag_prot_inconsistent;
|
||||
|
||||
#define FLASH_ABORT_TIMEOUT 10000
|
||||
|
||||
@@ -179,15 +180,6 @@ static int reg_to_protect(uint8_t sr1, uint8_t sr2, unsigned int *start,
|
||||
if (sec && bp == 6)
|
||||
return EC_ERROR_INVAL;
|
||||
|
||||
/*
|
||||
* If SRP0 is not set, flash is not protected because status register
|
||||
* can be rewritten.
|
||||
*/
|
||||
if (!(sr1 & SPI_FLASH_SR1_SRP0)) {
|
||||
*start = *len = 0;
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
/* Determine granularity (4kb sector or 64kb block) */
|
||||
/* Computation using 2 * 1024 is correct */
|
||||
size = sec ? (2 * 1024) : (64 * 1024);
|
||||
@@ -212,6 +204,20 @@ static int reg_to_protect(uint8_t sr1, uint8_t sr2, unsigned int *start,
|
||||
*len = CONFIG_FLASH_SIZE - *len;
|
||||
}
|
||||
|
||||
/*
|
||||
* If SRP0 is not set, flash is not protected because status register
|
||||
* can be rewritten.
|
||||
*/
|
||||
if (!(sr1 & SPI_FLASH_SR1_SRP0)) {
|
||||
/* Set protection inconsistent if len != 0*/
|
||||
if (*len != 0)
|
||||
flag_prot_inconsistent = 1;
|
||||
*start = *len = 0;
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
/* Flag for checking protection inconsistent */
|
||||
flag_prot_inconsistent = 0;
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -385,6 +391,22 @@ void flash_burst_write(unsigned int dest_addr, unsigned int bytes,
|
||||
flash_cs_level(1);
|
||||
}
|
||||
|
||||
int flash_uma_lock(int enable)
|
||||
{
|
||||
UPDATE_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK, enable);
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
int flash_spi_sel_lock(int enable)
|
||||
{
|
||||
/*
|
||||
* F_SPI_QUAD, F_SPI_CS1_1/2, F_SPI_TRIS become read-only
|
||||
* if this bit is set
|
||||
*/
|
||||
UPDATE_BIT(NPCX_DEV_CTL4, NPCX_DEV_CTL4_F_SPI_SLLK, enable);
|
||||
return IS_BIT_SET(NPCX_DEV_CTL4, NPCX_DEV_CTL4_F_SPI_SLLK);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Physical layer APIs */
|
||||
|
||||
@@ -595,6 +617,10 @@ int flash_physical_erase(int offset, int size)
|
||||
int flash_physical_get_protect(int bank)
|
||||
{
|
||||
uint32_t addr = bank * CONFIG_FLASH_BANK_SIZE;
|
||||
/* All UMA transaction is locked means all banks are protected */
|
||||
if (IS_BIT_SET(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK))
|
||||
return EC_ERROR_ACCESS_DENIED;
|
||||
|
||||
return flash_check_prot_reg(addr, CONFIG_FLASH_BANK_SIZE);
|
||||
}
|
||||
|
||||
@@ -611,6 +637,8 @@ uint32_t flash_physical_get_protect_flags(void)
|
||||
* TODO: If status register protects a range, but SRP0 is not set,
|
||||
* flags should indicate EC_FLASH_PROTECT_ERROR_INCONSISTENT.
|
||||
*/
|
||||
if (flag_prot_inconsistent)
|
||||
flags |= EC_FLASH_PROTECT_ERROR_INCONSISTENT;
|
||||
|
||||
/* Read all-protected state from our shadow copy */
|
||||
if (all_protected)
|
||||
@@ -621,9 +649,18 @@ uint32_t flash_physical_get_protect_flags(void)
|
||||
|
||||
int flash_physical_protect_now(int all)
|
||||
{
|
||||
if (all)
|
||||
if (all) {
|
||||
all_protected = 1;
|
||||
|
||||
/*
|
||||
* Set UMA_LOCK bit for locking all UMA transaction.
|
||||
* But we still can read directly from flash mapping address
|
||||
*/
|
||||
flash_uma_lock(1);
|
||||
} else {
|
||||
all_protected = 0;
|
||||
/* Unlocking all UMA transaction */
|
||||
flash_uma_lock(0);
|
||||
}
|
||||
/* TODO: if all, disable SPI interface */
|
||||
|
||||
return EC_SUCCESS;
|
||||
@@ -634,14 +671,26 @@ int flash_physical_protect_at_boot(enum flash_wp_range range)
|
||||
{
|
||||
switch (range) {
|
||||
case FLASH_WP_NONE:
|
||||
/* Unlock UMA transactions */
|
||||
if (IS_BIT_SET(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK))
|
||||
CLEAR_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK);
|
||||
/* Clear protection bits in status register */
|
||||
return flash_set_status_for_prot(0, 0);
|
||||
case FLASH_WP_RO:
|
||||
/* Unlock UMA transactions */
|
||||
if (IS_BIT_SET(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK))
|
||||
CLEAR_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_UMA_LOCK);
|
||||
/* Protect read-only */
|
||||
return flash_write_prot_reg(
|
||||
WP_BANK_OFFSET*CONFIG_FLASH_BANK_SIZE,
|
||||
WP_BANK_COUNT*CONFIG_FLASH_BANK_SIZE);
|
||||
case FLASH_WP_ALL:
|
||||
/* Protect all */
|
||||
/*
|
||||
* Set UMA_LOCK bit for locking all UMA transaction.
|
||||
* But we still can read directly from flash mapping address
|
||||
*/
|
||||
return flash_uma_lock(1);
|
||||
default:
|
||||
return EC_ERROR_INVAL;
|
||||
}
|
||||
@@ -686,5 +735,43 @@ int flash_pre_init(void)
|
||||
CLEAR_BIT(NPCX_DEVCNT, NPCX_DEVCNT_F_SPI_TRIS);
|
||||
#endif
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Console commands */
|
||||
|
||||
static int command_flash_spi_sel_lock(int argc, char **argv)
|
||||
{
|
||||
int ena;
|
||||
|
||||
if (argc > 1) {
|
||||
if (!parse_bool(argv[1], &ena))
|
||||
return EC_ERROR_PARAM1;
|
||||
ena = flash_spi_sel_lock(ena);
|
||||
}
|
||||
ccprintf("Enabled: %d\n", ena);
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(flash_spi_sel_lock, command_flash_spi_sel_lock,
|
||||
"[0 | 1]",
|
||||
"Lock spi flash interface selection",
|
||||
NULL);
|
||||
|
||||
static int command_flash_tristate(int argc, char **argv)
|
||||
{
|
||||
int ena;
|
||||
|
||||
if (argc > 1) {
|
||||
if (!parse_bool(argv[1], &ena))
|
||||
return EC_ERROR_PARAM1;
|
||||
flash_tristate(ena);
|
||||
}
|
||||
ccprintf("Enabled: %d\n", ena);
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_CONSOLE_COMMAND(flash_tristate, command_flash_tristate,
|
||||
"[0 | 1]",
|
||||
"Tristate spi flash pins",
|
||||
NULL);
|
||||
|
||||
|
||||
@@ -218,12 +218,12 @@ struct gpio_alt_map {
|
||||
|
||||
const struct gpio_alt_map gpio_alt_table[] = {
|
||||
/* I2C Module */
|
||||
#if I2C0_BUS0
|
||||
{ NPCX_GPIO(B, 4), NPCX_ALT(2, I2C0_0_SL)}, /* SMB0SDA */
|
||||
{ NPCX_GPIO(B, 5), NPCX_ALT(2, I2C0_0_SL)}, /* SMB0SCL */
|
||||
#else
|
||||
#if NPCX_I2C0_BUS2
|
||||
{ NPCX_GPIO(B, 2), NPCX_ALT(2, I2C0_1_SL)}, /* SMB0SDA */
|
||||
{ NPCX_GPIO(B, 3), NPCX_ALT(2, I2C0_1_SL)}, /* SMB0SCL */
|
||||
#else
|
||||
{ NPCX_GPIO(B, 4), NPCX_ALT(2, I2C0_0_SL)}, /* SMB0SDA */
|
||||
{ NPCX_GPIO(B, 5), NPCX_ALT(2, I2C0_0_SL)}, /* SMB0SCL */
|
||||
#endif
|
||||
{ NPCX_GPIO(8, 7), NPCX_ALT(2, I2C1_0_SL)}, /* SMB1SDA */
|
||||
{ NPCX_GPIO(9, 0), NPCX_ALT(2, I2C1_0_SL)}, /* SMB1SCL */
|
||||
@@ -237,9 +237,14 @@ const struct gpio_alt_map gpio_alt_table[] = {
|
||||
{ NPCX_GPIO(4, 3), NPCX_ALT(6, ADC2_SL)}, /* ADC2 */
|
||||
{ NPCX_GPIO(4, 2), NPCX_ALT(6, ADC3_SL)}, /* ADC3 */
|
||||
{ NPCX_GPIO(4, 1), NPCX_ALT(6, ADC4_SL)}, /* ADC4 */
|
||||
/* UART Module */
|
||||
{ NPCX_GPIO(1, 0), NPCX_ALT(9, NO_KSO08_SL)}, /* CR_SIN/KSO09/GPIO10*/
|
||||
{ NPCX_GPIO(1, 1), NPCX_ALT(9, NO_KSO09_SL)}, /* CR_SOUT/KSO10/GPIO11*/
|
||||
/* UART Module 1/2 */
|
||||
#if NPCX_UART_MODULE2
|
||||
{ NPCX_GPIO(6, 4), NPCX_ALT(C, UART_SL2)}, /* CR_SIN */
|
||||
{ NPCX_GPIO(6, 5), NPCX_ALT(C, UART_SL2)}, /* CR_SOUT */
|
||||
#else
|
||||
{ NPCX_GPIO(1, 0), NPCX_ALT(9, NO_KSO08_SL)}, /* CR_SIN/KSO09 */
|
||||
{ NPCX_GPIO(1, 1), NPCX_ALT(9, NO_KSO09_SL)}, /* CR_SOUT/KSO10 */
|
||||
#endif
|
||||
/* SPI Module */
|
||||
{ NPCX_GPIO(9, 5), NPCX_ALT(0, SPIP_SL)}, /* SPIP_MISO */
|
||||
{ NPCX_GPIO(A, 5), NPCX_ALT(0, SPIP_SL)}, /* SPIP_CS1 */
|
||||
@@ -255,24 +260,24 @@ const struct gpio_alt_map gpio_alt_table[] = {
|
||||
{ NPCX_GPIO(C, 0), NPCX_ALT(4, PWM6_SL)}, /* PWM6 */
|
||||
{ NPCX_GPIO(6, 0), NPCX_ALT(4, PWM7_SL)}, /* PWM7 */
|
||||
/* MFT Module */
|
||||
#if TACH_SEL1
|
||||
{ NPCX_GPIO(4, 0), NPCX_ALT(3, TA1_TACH1_SL1)},/* TA1_TACH1 */
|
||||
{ NPCX_GPIO(A, 4), NPCX_ALT(3, TB1_TACH2_SL1)},/* TB1_TACH2 */
|
||||
#else
|
||||
#if NPCX_TACH_SEL2
|
||||
{ NPCX_GPIO(9, 3), NPCX_ALT(C, TA1_TACH1_SL2)},/* TA1_TACH1 */
|
||||
{ NPCX_GPIO(D, 3), NPCX_ALT(C, TB1_TACH2_SL2)},/* TB1_TACH2 */
|
||||
#else
|
||||
{ NPCX_GPIO(4, 0), NPCX_ALT(3, TA1_TACH1_SL1)},/* TA1_TACH1 */
|
||||
{ NPCX_GPIO(A, 4), NPCX_ALT(3, TB1_TACH2_SL1)},/* TB1_TACH2 */
|
||||
#endif
|
||||
/* JTAG Module */
|
||||
#if !(JTAG1)
|
||||
{ NPCX_GPIO(2, 1), NPCX_ALT(5, NJEN0_EN) }, /* TCLK */
|
||||
{ NPCX_GPIO(1, 7), NPCX_ALT(5, NJEN0_EN) }, /* TDI */
|
||||
{ NPCX_GPIO(1, 6), NPCX_ALT(5, NJEN0_EN) }, /* TDO */
|
||||
{ NPCX_GPIO(2, 0), NPCX_ALT(5, NJEN0_EN) }, /* TMS */
|
||||
#else
|
||||
#if NPCX_JTAG_MODULE2
|
||||
{ NPCX_GPIO(D, 5), NPCX_ALT(5, NJEN1_EN) }, /* TCLK */
|
||||
{ NPCX_GPIO(E, 2), NPCX_ALT(5, NJEN1_EN) }, /* TDI */
|
||||
{ NPCX_GPIO(D, 4), NPCX_ALT(5, NJEN1_EN) }, /* TDO */
|
||||
{ NPCX_GPIO(E, 5), NPCX_ALT(5, NJEN1_EN) }, /* TMS */
|
||||
#else
|
||||
{ NPCX_GPIO(2, 1), NPCX_ALT(5, NJEN0_EN) }, /* TCLK */
|
||||
{ NPCX_GPIO(1, 7), NPCX_ALT(5, NJEN0_EN) }, /* TDI */
|
||||
{ NPCX_GPIO(1, 6), NPCX_ALT(5, NJEN0_EN) }, /* TDO */
|
||||
{ NPCX_GPIO(2, 0), NPCX_ALT(5, NJEN0_EN) }, /* TMS */
|
||||
#endif
|
||||
/* 01 for PWRGD_OUT*/
|
||||
};
|
||||
@@ -560,6 +565,13 @@ void gpio_pre_init(void)
|
||||
SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_GPIO_NO_SPIP);
|
||||
SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_NO_F_SPI);
|
||||
|
||||
#ifdef CONFIG_SHI
|
||||
/* Switching to eSPI mode for SHI interface */
|
||||
NPCX_DEVCNT |= 0x08;
|
||||
/* Alternate Intel bus interface LPC/eSPI to GPIOs first */
|
||||
SET_BIT(NPCX_DEVALT(ALT_GROUP_1), NPCX_DEVALT1_NO_LPC_ESPI);
|
||||
#endif
|
||||
|
||||
/* Clear all pending bits of GPIOS*/
|
||||
for (i = 0; i < 2; i++)
|
||||
for (j = 0; j < 8; j++)
|
||||
|
||||
72
chip/npcx/header.c
Normal file
72
chip/npcx/header.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Booter header for Chrome EC.
|
||||
*
|
||||
* This header is used by Nuvoton EC Booter.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "registers.h"
|
||||
#include "config_chip.h"
|
||||
|
||||
/* Signature used by fw header */
|
||||
#define SIG_FW_EC 0x2A3B4D5E
|
||||
|
||||
/* Definition used by error detection configuration */
|
||||
#define CHECK_CRC 0x00
|
||||
#define CHECK_CHECKSUM 0x01
|
||||
#define ERROR_DETECTION_EN 0x02
|
||||
#define ERROR_DETECTION_DIS 0x00
|
||||
|
||||
/* Code RAM addresses use by header */
|
||||
#define FW_START_ADDR CONFIG_CDRAM_BASE /* Put FW at the begin of CODE RAM */
|
||||
|
||||
/* TODO: It will be filled automatically by ECST */
|
||||
/* The entry point of reset handler (filled by ECST tool)*/
|
||||
#define FW_ENTRY_ADDR 0x100A8169
|
||||
|
||||
/* Error detection addresses use by header (A offset relative to flash image) */
|
||||
#define ERRCHK_START_ADDR 0x0
|
||||
#define ERRCHK_END_ADDR 0x0
|
||||
|
||||
/* Firmware Size -> Booter loads RO region after hard reset (16 bytes aligned)*/
|
||||
#define FW_SIZE CONFIG_RO_SIZE
|
||||
|
||||
/* FW Header used by NPCX5M5G Booter */
|
||||
struct __packed fw_header_t {
|
||||
uint32_t anchor; /* A constant used to verify FW header */
|
||||
uint16_t ext_anchor; /* Enable/disable firmware header CRC check */
|
||||
uint8_t spi_max_freq; /* Spi maximum allowable clock frequency */
|
||||
uint8_t spi_read_mode; /* Spi read mode used for firmware loading */
|
||||
uint8_t cfg_err_detect; /* FW load error detection configuration */
|
||||
uint32_t fw_load_addr; /* Firmware load start address */
|
||||
uint32_t fw_entry; /* Firmware entry point */
|
||||
uint32_t err_detect_start_addr; /* FW error detect start address */
|
||||
uint32_t err_detect_end_addr; /* FW error detect end address */
|
||||
uint32_t fw_length; /* Firmware length in bytes */
|
||||
uint8_t flash_size; /* Indicate SPI flash size */
|
||||
uint8_t reserved[26]; /* Reserved bytes */
|
||||
uint32_t sig_header; /* The CRC signature of the firmware header */
|
||||
uint32_t sig_fw_image; /* The CRC or Checksum of the firmware image */
|
||||
} __aligned(1);
|
||||
|
||||
__attribute__ ((section(".header")))
|
||||
const struct fw_header_t fw_header = {
|
||||
/* 00 */ SIG_FW_EC,
|
||||
/* 04 */ 0x54E1, /* Header CRC check Enable/Disable -> AB1Eh/54E1h */
|
||||
/* 06 */ 0x04, /* 20/25/33/40/50 MHz -> 00/01/02/03/04h */
|
||||
/* 07 */ 0x03, /* Normal/Fast/Rev/D_IO/Q_IO Mode -> 00/01/02/03/04h */
|
||||
/* 08 */ 0x00, /* Disable CRC check functionality */
|
||||
/* 09 */ FW_START_ADDR,
|
||||
/* 0D */ FW_ENTRY_ADDR,/* Filling by ECST tool with -usearmrst option */
|
||||
/* 11 */ ERRCHK_START_ADDR,
|
||||
/* 15 */ ERRCHK_END_ADDR,
|
||||
/* 19 */ FW_SIZE,/* Filling by ECST tool */
|
||||
/* 1D */ 0x0F, /* Flash Size 1/2/4/8/16 Mbytes -> 01/03/07/0F/1Fh */
|
||||
/* 1E-3F Other fields are filled by ECST tool or reserved */
|
||||
};
|
||||
@@ -15,15 +15,15 @@
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
|
||||
/* (2^TICK_ITIM_DEPTH us) between 2 ticks of timer */
|
||||
#define TICK_ITIM_DEPTH 16 /* Depth of ITIM Unit: bits */
|
||||
#define TICK_INTERVAL (1 << TICK_ITIM_DEPTH) /* Unit: us */
|
||||
#define TICK_INTERVAL_MASK (TICK_INTERVAL - 1) /* Mask of interval */
|
||||
#define TICK_ITIM_MAX_CNT (TICK_INTERVAL - 1) /* Maximum counter value */
|
||||
/* Use ITIM32 as main hardware timer */
|
||||
#define TICK_ITIM32_MAX_CNT 0xFFFFFFFF
|
||||
|
||||
/* Depth of event timer */
|
||||
#define TICK_EVT_DEPTH 16 /* Depth of event timer Unit: bits */
|
||||
#define TICK_EVT_INTERVAL (1 << TICK_EVT_DEPTH) /* Unit: us */
|
||||
#define TICK_EVT_INTERVAL_MASK (TICK_EVT_INTERVAL - 1) /* Mask of interval */
|
||||
#define TICK_EVT_MAX_CNT (TICK_EVT_INTERVAL - 1) /* Maximum event counter */
|
||||
|
||||
/* 32-bits counter value */
|
||||
static volatile uint32_t cur_cnt_us;
|
||||
static volatile uint32_t pre_cnt_us;
|
||||
/* Time when event will be expired unit:us */
|
||||
static volatile uint32_t evt_expired_us;
|
||||
/* 32-bits event counter */
|
||||
@@ -36,20 +36,20 @@ static volatile uint32_t cur_cnt_us_dbg;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Internal functions */
|
||||
void init_hw_timer(int itim_no, enum ITIM16_SOURCE_CLOCK_T source)
|
||||
void init_hw_timer(int itim_no, enum ITIM_SOURCE_CLOCK_T source)
|
||||
{
|
||||
/* Use internal 32K clock/APB2 for ITIM16 */
|
||||
UPDATE_BIT(NPCX_ITCTS(itim_no), NPCX_ITIM16_CKSEL,
|
||||
source != ITIM16_SOURCE_CLOCK_APB2);
|
||||
UPDATE_BIT(NPCX_ITCTS(itim_no), NPCX_ITCTS_CKSEL,
|
||||
source != ITIM_SOURCE_CLOCK_APB2);
|
||||
|
||||
/* Clear timeout status */
|
||||
SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITIM16_TO_STS);
|
||||
SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITCTS_TO_STS);
|
||||
|
||||
/* ITIM timeout interrupt enable */
|
||||
SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITIM16_TO_IE);
|
||||
SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITCTS_TO_IE);
|
||||
|
||||
/* ITIM timeout wake-up enable */
|
||||
SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITIM16_TO_WUE);
|
||||
SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITCTS_TO_WUE);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -70,18 +70,18 @@ void __hw_clock_event_set(uint32_t deadline)
|
||||
#endif
|
||||
|
||||
/* Event module disable */
|
||||
CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITIM16_ITEN);
|
||||
CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN);
|
||||
/*
|
||||
* ITIM count down : event expired : Unit: 1/32768 sec
|
||||
* It must exceed evt_expired_us for process_timers function
|
||||
*/
|
||||
evt_cnt = ((uint32_t)(evt_cnt_us*inv_evt_tick)+1)-1;
|
||||
if (evt_cnt > TICK_ITIM_MAX_CNT)
|
||||
evt_cnt = TICK_ITIM_MAX_CNT;
|
||||
if (evt_cnt > TICK_EVT_MAX_CNT)
|
||||
evt_cnt = TICK_EVT_MAX_CNT;
|
||||
NPCX_ITCNT16(ITIM_EVENT_NO) = evt_cnt;
|
||||
|
||||
/* Event module enable */
|
||||
SET_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITIM16_ITEN);
|
||||
SET_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN);
|
||||
|
||||
/* Enable interrupt of ITIM */
|
||||
task_enable_irq(ITIM16_INT(ITIM_EVENT_NO));
|
||||
@@ -102,7 +102,7 @@ uint32_t __hw_clock_get_sleep_time(void)
|
||||
|
||||
interrupt_disable();
|
||||
/* Event has been triggered but timer ISR dosen't handle it */
|
||||
if (IS_BIT_SET(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITIM16_TO_STS))
|
||||
if (IS_BIT_SET(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_TO_STS))
|
||||
sleep_time = (uint32_t) (evt_cnt+1)*evt_tick;
|
||||
/* Event hasn't been triggered */
|
||||
else
|
||||
@@ -116,7 +116,7 @@ uint32_t __hw_clock_get_sleep_time(void)
|
||||
void __hw_clock_event_clear(void)
|
||||
{
|
||||
/* ITIM event module disable */
|
||||
CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITIM16_ITEN);
|
||||
CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN);
|
||||
|
||||
/* Disable interrupt of Event */
|
||||
task_disable_irq(ITIM16_INT(ITIM_EVENT_NO));
|
||||
@@ -129,21 +129,15 @@ void __hw_clock_event_clear(void)
|
||||
/* Irq for hwtimer event */
|
||||
void __hw_clock_event_irq(void)
|
||||
{
|
||||
int delay;
|
||||
/* Clear timeout status for event */
|
||||
SET_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITIM16_TO_STS);
|
||||
SET_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_TO_STS);
|
||||
|
||||
/* ITIM event module disable */
|
||||
CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITIM16_ITEN);
|
||||
CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN);
|
||||
|
||||
/* Disable interrupt of event */
|
||||
task_disable_irq(ITIM16_INT(ITIM_EVENT_NO));
|
||||
|
||||
/* Workaround for tick interrupt latency */
|
||||
delay = evt_expired_us - __hw_clock_source_read();
|
||||
if (delay > 0)
|
||||
cur_cnt_us += delay;
|
||||
|
||||
/* Clear event parameters */
|
||||
evt_expired_us = 0;
|
||||
evt_cnt = 0;
|
||||
@@ -160,49 +154,43 @@ DECLARE_IRQ(ITIM16_INT(ITIM_EVENT_NO) , __hw_clock_event_irq, 1);
|
||||
/* Returns the value of the free-running counter used as clock. */
|
||||
uint32_t __hw_clock_source_read(void)
|
||||
{
|
||||
uint32_t us;
|
||||
uint32_t cnt = NPCX_ITCNT16(ITIM_TIME_NO);
|
||||
/* Is timeout expired? - but timer ISR dosen't handle it */
|
||||
if (IS_BIT_SET(NPCX_ITCTS(ITIM_TIME_NO), NPCX_ITIM16_TO_STS))
|
||||
us = TICK_INTERVAL;
|
||||
else
|
||||
us = TICK_INTERVAL - cnt;
|
||||
|
||||
uint32_t cnt = NPCX_ITCNT32;
|
||||
#if DEBUG_TMR
|
||||
cur_cnt_us_dbg = cur_cnt_us + us;
|
||||
cur_cnt_us_dbg = TICK_ITIM32_MAX_CNT - cnt;
|
||||
#endif
|
||||
return cur_cnt_us + us;
|
||||
return TICK_ITIM32_MAX_CNT - cnt;
|
||||
}
|
||||
|
||||
/* Override the current value of the hardware counter */
|
||||
void __hw_clock_source_set(uint32_t ts)
|
||||
{
|
||||
#if DEBUG_TMR
|
||||
cur_cnt_us_dbg = TICK_ITIM32_MAX_CNT - ts;
|
||||
#endif
|
||||
/* ITIM32 module disable */
|
||||
CLEAR_BIT(NPCX_ITCTS(ITIM32), NPCX_ITCTS_ITEN);
|
||||
/* Set current time */
|
||||
cur_cnt_us = ts;
|
||||
NPCX_ITCNT32 = TICK_ITIM32_MAX_CNT - ts;
|
||||
/* ITIM32 module enable */
|
||||
SET_BIT(NPCX_ITCTS(ITIM32), NPCX_ITCTS_ITEN);
|
||||
|
||||
}
|
||||
|
||||
/* Irq for hwtimer tick */
|
||||
void __hw_clock_source_irq(void)
|
||||
{
|
||||
/* Is timeout trigger trigger? */
|
||||
if (IS_BIT_SET(NPCX_ITCTS(ITIM_TIME_NO), NPCX_ITIM16_TO_STS)) {
|
||||
if (IS_BIT_SET(NPCX_ITCTS(ITIM32), NPCX_ITCTS_TO_STS)) {
|
||||
/* Clear timeout status*/
|
||||
SET_BIT(NPCX_ITCTS(ITIM_TIME_NO), NPCX_ITIM16_TO_STS);
|
||||
|
||||
/* Store previous time counter value */
|
||||
pre_cnt_us = cur_cnt_us;
|
||||
/* Increase TICK_INTERVAL unit:us */
|
||||
cur_cnt_us += TICK_INTERVAL;
|
||||
|
||||
/* Is 32-bits timer count overflow? */
|
||||
if (pre_cnt_us > cur_cnt_us)
|
||||
process_timers(1);
|
||||
SET_BIT(NPCX_ITCTS(ITIM32), NPCX_ITCTS_TO_STS);
|
||||
/* 32-bits timer count overflow */
|
||||
process_timers(1);
|
||||
|
||||
} else { /* Handle soft trigger */
|
||||
process_timers(0);
|
||||
}
|
||||
}
|
||||
DECLARE_IRQ(NPCX_IRQ_ITIM16_1, __hw_clock_source_irq, 1);
|
||||
DECLARE_IRQ(NPCX_IRQ_ITIM32, __hw_clock_source_irq, 1);
|
||||
|
||||
static void update_prescaler(void)
|
||||
{
|
||||
@@ -211,7 +199,7 @@ static void update_prescaler(void)
|
||||
* Ttick_unit = (PRE_8+1) * Tapb2_clk
|
||||
* PRE_8 = (Ttick_unit/Tapb2_clk) -1
|
||||
*/
|
||||
NPCX_ITPRE(ITIM_TIME_NO) = (clock_get_apb2_freq() / SECOND) - 1;
|
||||
NPCX_ITPRE(ITIM32) = (clock_get_apb2_freq() / SECOND) - 1;
|
||||
/* Set event tick unit = 1/32768 sec */
|
||||
NPCX_ITPRE(ITIM_EVENT_NO) = 0;
|
||||
|
||||
@@ -230,14 +218,14 @@ int __hw_clock_source_init(uint32_t start_t)
|
||||
CGC_MODE_RUN | CGC_MODE_SLEEP);
|
||||
|
||||
/* init tick & event timer first */
|
||||
init_hw_timer(ITIM_TIME_NO, ITIM16_SOURCE_CLOCK_APB2);
|
||||
init_hw_timer(ITIM_EVENT_NO, ITIM16_SOURCE_CLOCK_32K);
|
||||
init_hw_timer(ITIM32, ITIM_SOURCE_CLOCK_APB2);
|
||||
init_hw_timer(ITIM_EVENT_NO, ITIM_SOURCE_CLOCK_32K);
|
||||
|
||||
/* Set initial prescaler */
|
||||
update_prescaler();
|
||||
|
||||
/* ITIM count down : TICK_INTERVAL expired*/
|
||||
NPCX_ITCNT16(ITIM_TIME_NO) = TICK_ITIM_MAX_CNT;
|
||||
/* ITIM count down : TICK_ITIM32_MAX_CNT us expired */
|
||||
NPCX_ITCNT32 = TICK_ITIM32_MAX_CNT;
|
||||
|
||||
/*
|
||||
* Override the count with the start value now that counting has
|
||||
@@ -246,10 +234,10 @@ int __hw_clock_source_init(uint32_t start_t)
|
||||
__hw_clock_source_set(start_t);
|
||||
|
||||
/* ITIM module enable */
|
||||
SET_BIT(NPCX_ITCTS(ITIM_TIME_NO), NPCX_ITIM16_ITEN);
|
||||
SET_BIT(NPCX_ITCTS(ITIM32), NPCX_ITCTS_ITEN);
|
||||
|
||||
/* Enable interrupt of ITIM */
|
||||
task_enable_irq(ITIM16_INT(ITIM_TIME_NO));
|
||||
task_enable_irq(NPCX_IRQ_ITIM32);
|
||||
|
||||
return ITIM16_INT(ITIM_TIME_NO);
|
||||
return NPCX_IRQ_ITIM32;
|
||||
}
|
||||
|
||||
@@ -8,19 +8,18 @@
|
||||
#ifndef __CROS_EC_HWTIMER_CHIP_H
|
||||
#define __CROS_EC_HWTIMER_CHIP_H
|
||||
|
||||
/* Channel definition for ITIM16 */
|
||||
#define ITIM_TIME_NO ITIM16_1
|
||||
#define ITIM_EVENT_NO ITIM16_2
|
||||
/* Channel definition for ITIM */
|
||||
#define ITIM_EVENT_NO ITIM16_1
|
||||
#define ITIM_WDG_NO ITIM16_5
|
||||
|
||||
/* Clock source for ITIM16 */
|
||||
enum ITIM16_SOURCE_CLOCK_T {
|
||||
ITIM16_SOURCE_CLOCK_APB2 = 0,
|
||||
ITIM16_SOURCE_CLOCK_32K = 1,
|
||||
enum ITIM_SOURCE_CLOCK_T {
|
||||
ITIM_SOURCE_CLOCK_APB2 = 0,
|
||||
ITIM_SOURCE_CLOCK_32K = 1,
|
||||
};
|
||||
|
||||
/* Initialize ITIM16 timer */
|
||||
void init_hw_timer(int itim_no, enum ITIM16_SOURCE_CLOCK_T source);
|
||||
void init_hw_timer(int itim_no, enum ITIM_SOURCE_CLOCK_T source);
|
||||
|
||||
/* Returns time delay cause of deep idle */
|
||||
uint32_t __hw_clock_get_sleep_time(void);
|
||||
|
||||
@@ -557,4 +557,4 @@ static void i2c_init(void)
|
||||
task_enable_irq(i2c_irqs[port]);
|
||||
}
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, i2c_init, HOOK_PRIO_DEFAULT);
|
||||
DECLARE_HOOK(HOOK_INIT, i2c_init, HOOK_PRIO_INIT_I2C);
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
void jtag_pre_init(void)
|
||||
{
|
||||
/* Setting for fixing JTAG issue */
|
||||
NPCX_DBGCTRL = 0x04;
|
||||
/* Enable automatic freeze mode */
|
||||
CLEAR_BIT(NPCX_DBGFRZEN3, NPCX_DBGFRZEN3_GLBL_FRZ_DIS);
|
||||
}
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
/* Copyright (c) 2014 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.
|
||||
*
|
||||
* NPCX5M5G SoC little FW used by booter
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "registers.h"
|
||||
#include "config_chip.h"
|
||||
#include "ec_lfw.h"
|
||||
#include "system_chip.h"
|
||||
|
||||
/* size of little FW */
|
||||
#define LFW_SIZE 0x1000
|
||||
/* signature used by booter */
|
||||
#define SIG_GOOGLE_EC 0x55AA650E
|
||||
/* little FW located on TOP of Flash - 4K */
|
||||
#define FW_ADDR (CONFIG_SPI_FLASH_SIZE - 0x1000)
|
||||
|
||||
/* Header used by NPCX5M5G Booter */
|
||||
struct booter_header_t {
|
||||
uint32_t signature; /* A constant used to verify FW pointer is valid */
|
||||
uint32_t pointer_fw;/* Holds the BootLoader location in the flash */
|
||||
};
|
||||
|
||||
__attribute__ ((section(".booter_pointer")))
|
||||
const struct booter_header_t booter_header = {
|
||||
/* 00 */ SIG_GOOGLE_EC,
|
||||
/* 04 */ FW_ADDR
|
||||
};
|
||||
|
||||
|
||||
/* Original sp during sysjump */
|
||||
uint32_t org_sp;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* flash internal functions */
|
||||
|
||||
void __attribute__ ((section(".instrucion_ram")))
|
||||
flash_burst_copy_fw_to_mram(uint32_t addr_flash, uint32_t addr_mram,
|
||||
uint32_t size)
|
||||
{
|
||||
uint32_t bit32_idx;
|
||||
uint32_t bit32_size;
|
||||
uint32_t *bit32_ptr_mram;
|
||||
|
||||
bit32_ptr_mram = (uint32_t *)addr_mram;
|
||||
|
||||
/* Round it up and get it in 4 bytes */
|
||||
bit32_size = (size+3) / 4;
|
||||
|
||||
/* Set chip select to low */
|
||||
CLEAR_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1);
|
||||
|
||||
/* Write flash address */
|
||||
NPCX_UMA_AB2 = (uint8_t)((addr_flash & 0xFF0000)>>16);
|
||||
NPCX_UMA_AB1 = (uint8_t)((addr_flash & 0xFF00)>>8);
|
||||
NPCX_UMA_AB0 = (uint8_t)((addr_flash & 0xFF));
|
||||
|
||||
NPCX_UMA_CODE = CMD_FAST_READ;
|
||||
NPCX_UMA_CTS = MASK_CMD_ADR_WR;
|
||||
/* wait for UMA to complete */
|
||||
while (IS_BIT_SET(NPCX_UMA_CTS, EXEC_DONE))
|
||||
;
|
||||
|
||||
/* Start to burst read and copy data to Code RAM */
|
||||
for (bit32_idx = 0; bit32_idx < bit32_size; bit32_idx++) {
|
||||
/* 1101 0100 - EXEC, RD, NO CMD, NO ADDR, 4 bytes */
|
||||
NPCX_UMA_CTS = MASK_RD_4BYTE;
|
||||
while (IS_BIT_SET(NPCX_UMA_CTS, EXEC_DONE))
|
||||
;
|
||||
/* copy data to Code RAM */
|
||||
bit32_ptr_mram[bit32_idx] = NPCX_UMA_DB0_3;
|
||||
}
|
||||
|
||||
/* Set chip select to high */
|
||||
SET_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1);
|
||||
}
|
||||
|
||||
void __attribute__ ((section(".instrucion_ram")))
|
||||
bin2ram(void)
|
||||
{
|
||||
/* copy image from RO base */
|
||||
if (IS_BIT_SET(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION))
|
||||
flash_burst_copy_fw_to_mram(CONFIG_RO_MEM_OFF,
|
||||
CONFIG_CDRAM_BASE, CONFIG_RO_SIZE - LFW_SIZE);
|
||||
/* copy image from RW base */
|
||||
else
|
||||
flash_burst_copy_fw_to_mram(CONFIG_RW_MEM_OFF,
|
||||
CONFIG_CDRAM_BASE, CONFIG_RW_SIZE - LFW_SIZE);
|
||||
|
||||
/* Disable FIU pins to tri-state */
|
||||
CLEAR_BIT(NPCX_DEVCNT, NPCX_DEVCNT_F_SPI_TRIS);
|
||||
|
||||
|
||||
/* Distinguish reboot or sysjump */
|
||||
if (org_sp < CONFIG_RAM_BASE) {
|
||||
/* restore sp from begin of RO image */
|
||||
asm volatile("ldr r0, =0x10088000\n"
|
||||
"ldr r1, [r0]\n"
|
||||
"mov sp, r1\n");
|
||||
} else {
|
||||
/* restore sp from sysjump */
|
||||
asm volatile("mov sp, %0" : : "r"(org_sp));
|
||||
}
|
||||
|
||||
/* Jump to reset ISR */
|
||||
asm volatile(
|
||||
"ldr r0, =0x10088004\n"
|
||||
"ldr r1, [r0]\n"
|
||||
"mov pc, r1\n");
|
||||
}
|
||||
|
||||
/* Entry function of little FW */
|
||||
void __attribute__ ((section(".startup_text"), noreturn))
|
||||
entry_lfw(void)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
/* Backup sp value */
|
||||
asm volatile("mov %0, sp" : "=r"(org_sp));
|
||||
/* initialize sp with Data RAM */
|
||||
asm volatile(
|
||||
"ldr r0, =0x100A8000\n"
|
||||
"mov sp, r0\n");
|
||||
|
||||
/* Copy the bin2ram code to RAM */
|
||||
for (i = 0; i < &__iram_fw_end - &__iram_fw_start; i++)
|
||||
*(&__iram_fw_start + i) = *(&__flash_fw_start + i);
|
||||
|
||||
/* Copy ram log of booter into bbram */
|
||||
NPCX_BBRAM(BBRM_DATA_INDEX_RAMLOG) = *((uint8_t *)ADDR_BOOT_RAMLOG);
|
||||
|
||||
/* Run code in RAM */
|
||||
bin2ram();
|
||||
|
||||
/* Should never reach this */
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
@@ -1,122 +0,0 @@
|
||||
/* Copyright (c) 2014 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.
|
||||
*
|
||||
* NPCX5M5G SoC little FW for booting
|
||||
*/
|
||||
|
||||
/* Memory Spaces Definitions */
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x647FF000, LENGTH = 4K - 256
|
||||
POINTER(r) : ORIGIN = 0x647FFF00, LENGTH = 256
|
||||
CODERAM(rx): ORIGIN = 0x100A7C00, LENGTH = 1K - 256
|
||||
RAM (xrw) : ORIGIN = 0x100A7F00, LENGTH = 256
|
||||
}
|
||||
|
||||
/*
|
||||
* The entry point is informative, for debuggers and simulators,
|
||||
* since the Cortex-M vector points to it anyway.
|
||||
*/
|
||||
ENTRY(entry_lfw)
|
||||
|
||||
/* Sections Definitions */
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
/*
|
||||
* The beginning of the startup code
|
||||
*/
|
||||
.startup_text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.startup_text ) /* Startup code */
|
||||
. = ALIGN(4);
|
||||
} >FLASH
|
||||
|
||||
|
||||
/*
|
||||
* The program code is stored in the .text section,
|
||||
* which goes to FLASH.
|
||||
*/
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.text .text.*) /* all remaining code */
|
||||
*(.rodata .rodata.*) /* read-only data (constants) */
|
||||
} >FLASH
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
__flash_fw_start = .;
|
||||
.instrucion_ram : AT(__flash_fw_start)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__iram_fw_start = .;
|
||||
*(.instrucion_ram .instrucion_ram.*) /* CODERAM in 0x200C0000 */
|
||||
__iram_fw_end = .;
|
||||
} > CODERAM
|
||||
|
||||
/*
|
||||
* The POINTER section used for booter
|
||||
*/
|
||||
.booter_pointer :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.booter_pointer)) /* Booter pointer in 0xFFFF00 */
|
||||
} > POINTER
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
|
||||
/*
|
||||
* This address is used by the startup code to
|
||||
* initialise the .data section.
|
||||
*/
|
||||
_sidata = _etext;
|
||||
|
||||
/*
|
||||
* The initialised data section.
|
||||
* The program executes knowing that the data is in the RAM
|
||||
* but the loader puts the initial values in the FLASH (inidata).
|
||||
* It is one task of the startup to copy the initial values from
|
||||
* FLASH to RAM.
|
||||
*/
|
||||
.data : AT ( _sidata )
|
||||
{
|
||||
. = ALIGN(4);
|
||||
|
||||
/* This is used by the startup code to initialise the .data section */
|
||||
__data_start__ = . ;
|
||||
*(.data_begin .data_begin.*)
|
||||
|
||||
*(.data .data.*)
|
||||
|
||||
*(.data_end .data_end.*)
|
||||
. = ALIGN(4);
|
||||
|
||||
/* This is used by the startup code to initialise the .data section */
|
||||
__data_end__ = . ;
|
||||
|
||||
} > RAM
|
||||
|
||||
|
||||
/*
|
||||
* The uninitialised data section. NOLOAD is used to avoid
|
||||
* the "section `.bss' type changed to PROGBITS" warning
|
||||
*/
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .; /* standard newlib definition */
|
||||
*(.bss_begin .bss_begin.*)
|
||||
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
|
||||
*(.bss_end .bss_end.*)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .; /* standard newlib definition */
|
||||
} >RAM
|
||||
}
|
||||
179
chip/npcx/lpc.c
179
chip/npcx/lpc.c
@@ -30,6 +30,15 @@
|
||||
|
||||
#define LPC_SYSJUMP_TAG 0x4c50 /* "LP" */
|
||||
|
||||
/* Timeout to wait PLTRST is deasserted */
|
||||
#define LPC_PLTRST_TIMEOUT_US 800000
|
||||
|
||||
/* Super-IO index and register definitions */
|
||||
#define SIO_OFFSET 0x4E
|
||||
#define INDEX_SID 0x20
|
||||
#define INDEX_CHPREV 0x24
|
||||
#define INDEX_SRID 0x27
|
||||
|
||||
static uint32_t host_events; /* Currently pending SCI/SMI events */
|
||||
static uint32_t event_mask[3]; /* Event masks for each type */
|
||||
static struct host_packet lpc_packet;
|
||||
@@ -46,7 +55,6 @@ static uint8_t * const cmd_params = (uint8_t *)shm_mem_host_cmd +
|
||||
static struct ec_lpc_host_args * const lpc_host_args =
|
||||
(struct ec_lpc_host_args *)shm_mem_host_cmd;
|
||||
|
||||
|
||||
#ifdef CONFIG_KEYBOARD_IRQ_GPIO
|
||||
static void keyboard_irq_assert(void)
|
||||
{
|
||||
@@ -358,12 +366,6 @@ void lpc_clear_acpi_status_mask(uint8_t mask)
|
||||
/* TODO (crbug.com/p/38224): Implement */
|
||||
}
|
||||
|
||||
int lpc_get_pltrst_asserted(void)
|
||||
{
|
||||
/* Read PLTRST status*/
|
||||
return (NPCX_MSWCTL1 & 0x04) ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle write to ACPI I/O port
|
||||
*
|
||||
@@ -544,6 +546,158 @@ static void lpc_post_sysjump(void)
|
||||
memcpy(event_mask, prev_mask, sizeof(event_mask));
|
||||
}
|
||||
|
||||
int lpc_get_pltrst_asserted(void)
|
||||
{
|
||||
/* Read PLTRST status */
|
||||
return (NPCX_MSWCTL1 & 0x04) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Super-IO read/write function */
|
||||
void lpc_sib_write_reg(uint8_t io_offset, uint8_t index_value,
|
||||
uint8_t io_data)
|
||||
{
|
||||
/* Disable interrupts */
|
||||
interrupt_disable();
|
||||
|
||||
/* Lock host CFG module */
|
||||
SET_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
|
||||
/* Enable Core-to-Host Modules Access */
|
||||
SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
|
||||
/* Enable Core access to CFG module */
|
||||
SET_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
|
||||
/* Verify Core read/write to host modules is not in progress */
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD))
|
||||
;
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
|
||||
;
|
||||
|
||||
/* Specify the io_offset A0 = 0. the index register is accessed */
|
||||
NPCX_IHIOA = io_offset;
|
||||
/* Write the data. This starts the write access to the host module */
|
||||
NPCX_IHD = index_value;
|
||||
/* Wait while Core write operation is in progress */
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
|
||||
;
|
||||
|
||||
/* Specify the io_offset A0 = 1. the data register is accessed */
|
||||
NPCX_IHIOA = io_offset+1;
|
||||
/* Write the data. This starts the write access to the host module */
|
||||
NPCX_IHD = io_data;
|
||||
/* Wait while Core write operation is in progress */
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
|
||||
;
|
||||
|
||||
/* Disable Core access to CFG module */
|
||||
CLEAR_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
|
||||
/* Disable Core-to-Host Modules Access */
|
||||
CLEAR_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
|
||||
/* unlock host CFG module */
|
||||
CLEAR_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
|
||||
|
||||
/* Enable interrupts */
|
||||
interrupt_enable();
|
||||
}
|
||||
|
||||
uint8_t lpc_sib_read_reg(uint8_t io_offset, uint8_t index_value)
|
||||
{
|
||||
uint8_t data_value;
|
||||
|
||||
/* Disable interrupts */
|
||||
interrupt_disable();
|
||||
|
||||
/* Lock host CFG module */
|
||||
SET_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
|
||||
/* Enable Core-to-Host Modules Access */
|
||||
SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
|
||||
/* Enable Core access to CFG module */
|
||||
SET_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
|
||||
/* Verify Core read/write to host modules is not in progress */
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD))
|
||||
;
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
|
||||
;
|
||||
|
||||
|
||||
/* Specify the io_offset A0 = 0. the index register is accessed */
|
||||
NPCX_IHIOA = io_offset;
|
||||
/* Write the data. This starts the write access to the host module */
|
||||
NPCX_IHD = index_value;
|
||||
/* Wait while Core write operation is in progress */
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
|
||||
;
|
||||
|
||||
/* Specify the io_offset A0 = 1. the data register is accessed */
|
||||
NPCX_IHIOA = io_offset+1;
|
||||
/* Start a Core read from host module */
|
||||
SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD);
|
||||
/* Wait while Core read operation is in progress */
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD))
|
||||
;
|
||||
/* Read the data */
|
||||
data_value = NPCX_IHD;
|
||||
|
||||
/* Disable Core access to CFG module */
|
||||
CLEAR_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
|
||||
/* Disable Core-to-Host Modules Access */
|
||||
CLEAR_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
|
||||
/* unlock host CFG module */
|
||||
CLEAR_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
|
||||
|
||||
/* Enable interrupts */
|
||||
interrupt_enable();
|
||||
|
||||
return data_value;
|
||||
}
|
||||
|
||||
/* For LPC host register initial via SIB module */
|
||||
void lpc_host_register_init(void){
|
||||
|
||||
timestamp_t deadline;
|
||||
|
||||
deadline.val = 0;
|
||||
deadline = get_time();
|
||||
deadline.val += LPC_PLTRST_TIMEOUT_US;
|
||||
|
||||
/* Make sure PLTRST is de-asserted. Or any setting for LPC is useless */
|
||||
while (lpc_get_pltrst_asserted())
|
||||
if (timestamp_expired(deadline, NULL)) {
|
||||
CPRINTS("PLTRST is asserted. LPC settings are ignored");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Setting PMC2 */
|
||||
/* LDN register = 0x12(PMC2) */
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0x07, 0x12);
|
||||
/* CMD port is 0x200 */
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0x60, 0x02);
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0x61, 0x00);
|
||||
/* Data port is 0x204 */
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0x62, 0x02);
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0x63, 0x04);
|
||||
/* enable PMC2 */
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0x30, 0x01);
|
||||
|
||||
/* Setting SHM */
|
||||
/* LDN register = 0x0F(SHM) */
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0x07, 0x0F);
|
||||
/* WIN1&2 mapping to IO */
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0xF1,
|
||||
lpc_sib_read_reg(SIO_OFFSET, 0xF1) | 0x30);
|
||||
/* Host Command on the IO:0x0800 */
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0xF7, 0x00);
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0xF6, 0x00);
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0xF5, 0x08);
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0xF4, 0x00);
|
||||
/* WIN1 as Host Command on the IO:0x0800 */
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0xFB, 0x00);
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0xFA, 0x00);
|
||||
/* WIN2 as MEMMAP on the IO:0x900 */
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0xF9, 0x09);
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0xF8, 0x00);
|
||||
/* enable SHM */
|
||||
lpc_sib_write_reg(SIO_OFFSET, 0x30, 0x01);
|
||||
}
|
||||
|
||||
static void lpc_init(void)
|
||||
{
|
||||
/* Enable clock for LPC peripheral */
|
||||
@@ -643,8 +797,17 @@ static void lpc_init(void)
|
||||
|
||||
update_host_event_status();
|
||||
|
||||
/*
|
||||
* TODO: For testing LPC with Chromebox, please make sure LPC_CLK is
|
||||
* generated before executing this function. EC needs LPC_CLK to access
|
||||
* LPC register through SIB module. For Chromebook platform, this
|
||||
* functionality should be done by BIOS or executed in hook function of
|
||||
* HOOK_CHIPSET_STARTUP
|
||||
*/
|
||||
#ifdef BOARD_NPCX_EVB
|
||||
/* initial IO port address via SIB-write modules */
|
||||
system_lpc_host_register_init();
|
||||
lpc_host_register_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Enable LPC ACPI-EC interrupts */
|
||||
|
||||
@@ -43,7 +43,7 @@ target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position \
|
||||
-work-area-size $_WORKAREASIZE
|
||||
|
||||
# JTAG speed
|
||||
adapter_khz 1000
|
||||
adapter_khz 100
|
||||
|
||||
adapter_nsrst_delay 100
|
||||
if {$using_jtag} {
|
||||
|
||||
@@ -10,15 +10,13 @@ source [find mem_helper.tcl]
|
||||
proc flash_npcx {image_path image_offset image_size spifw_image} {
|
||||
set UPLOAD_FLAG 0x200C4000;
|
||||
|
||||
# Clear whole 128KB Code RAM
|
||||
mwb 0x10088000 0xFF 0x20000
|
||||
# Clear whole 96KB Code RAM
|
||||
mwb 0x100A8000 0xFF 0x18000
|
||||
# Upload binary image to Code RAM
|
||||
fast_load_image $image_path 0x10088000
|
||||
fast_load
|
||||
load_image $image_path 0x100A8000
|
||||
|
||||
# Upload program spi image FW to lower 16KB Data RAM
|
||||
fast_load_image $spifw_image 0x200C0000
|
||||
fast_load
|
||||
load_image $spifw_image 0x200C0000
|
||||
|
||||
# Set sp to upper 16KB Data RAM
|
||||
reg sp 0x200C8000
|
||||
@@ -48,71 +46,67 @@ proc flash_npcx {image_path image_offset image_size spifw_image} {
|
||||
halt
|
||||
}
|
||||
|
||||
proc flash_npcx_ro {image_offset} {
|
||||
# 128 KB for RO& RW regions
|
||||
set fw_size 0x20000
|
||||
# images path
|
||||
set outdir ../../../build/npcx_evb
|
||||
set ro_image_path $outdir/ec.RO.flat
|
||||
set spifw_image $outdir/chip/npcx/spiflashfw/ec_npcxflash.bin
|
||||
|
||||
# Halt CPU first
|
||||
halt
|
||||
echo "*** Start to program RO region ***"
|
||||
# Write to lower 128kB from offset
|
||||
flash_npcx $ro_image_path $image_offset $fw_size $spifw_image
|
||||
echo "*** Finish program RO region ***"
|
||||
|
||||
# Reset CPU
|
||||
reset
|
||||
}
|
||||
|
||||
proc flash_npcx_evb {image_offset} {
|
||||
proc flash_npcx_ro {image_dir image_offset} {
|
||||
set MPU_RNR 0xE000ED98;
|
||||
set MPU_RASR 0xE000EDA0;
|
||||
|
||||
# 128 KB for RO& RW regions
|
||||
set fw_size 0x20000
|
||||
# 4K little FW
|
||||
set lfw_size 0x1000
|
||||
# 8M spi-flash
|
||||
set flash_size 0x800000
|
||||
|
||||
# 96 KB for RO& RW regions
|
||||
set fw_size 0x18000
|
||||
# images path
|
||||
set outdir ../../../build/npcx_evb
|
||||
set ro_image_path $outdir/ec.RO.flat
|
||||
set rw_image_path $outdir/ec.RW.bin
|
||||
set lfw_image_path $outdir/chip/npcx/lfw/ec_lfw.bin
|
||||
set spifw_image $outdir/chip/npcx/spiflashfw/ec_npcxflash.bin
|
||||
|
||||
# images offset
|
||||
set rw_image_offset [expr ($image_offset + $fw_size)]
|
||||
set lfw_image_offset [expr ($flash_size - $lfw_size)]
|
||||
set ro_image_path $image_dir/ec.RO.flat
|
||||
set spifw_image $image_dir/chip/npcx/spiflashfw/ec_npcxflash.bin
|
||||
|
||||
# Halt CPU first
|
||||
halt
|
||||
adapter_khz 1000
|
||||
|
||||
# diable MPU for Data RAM first
|
||||
# diable MPU for Data RAM
|
||||
mww $MPU_RNR 0x1
|
||||
mww $MPU_RASR 0x0
|
||||
|
||||
echo "*** Start to program RO region ***"
|
||||
# Write to lower 128kB from offset
|
||||
# Write to lower 96kB from offset
|
||||
flash_npcx $ro_image_path $image_offset $fw_size $spifw_image
|
||||
echo "*** Finish program RO region ***"
|
||||
|
||||
}
|
||||
|
||||
proc flash_npcx_all {image_dir image_offset} {
|
||||
set MPU_RNR 0xE000ED98;
|
||||
set MPU_RASR 0xE000EDA0;
|
||||
|
||||
# 96 KB for RO& RW regions
|
||||
set fw_size 0x18000
|
||||
# 8M spi-flash
|
||||
set flash_size 0x800000
|
||||
|
||||
# images path
|
||||
set ro_image_path $image_dir/ec.RO.flat
|
||||
set rw_image_path $image_dir/ec.RW.bin
|
||||
set spifw_image $image_dir/chip/npcx/spiflashfw/ec_npcxflash.bin
|
||||
|
||||
# images offset
|
||||
set rw_image_offset [expr ($image_offset + 0x20000)]
|
||||
|
||||
# Halt CPU first
|
||||
halt
|
||||
|
||||
adapter_khz 1000
|
||||
|
||||
# diable MPU for Data RAM
|
||||
mww $MPU_RNR 0x1
|
||||
mww $MPU_RASR 0x0
|
||||
|
||||
echo "*** Start to program RO region ***"
|
||||
# Write to lower 96kB from offset
|
||||
flash_npcx $ro_image_path $image_offset $fw_size $spifw_image
|
||||
echo "*** Finish program RO region ***\r\n"
|
||||
|
||||
echo "*** Start to program RW region ***"
|
||||
# Write to upper 128kB from offset
|
||||
# Write to upper 96kB from offset
|
||||
flash_npcx $rw_image_path $rw_image_offset $fw_size $spifw_image
|
||||
echo "*** Finish program RW region ***\r\n"
|
||||
|
||||
echo "*** Start to program LFW region ***"
|
||||
# Write to top of flash minus 4KB
|
||||
flash_npcx $lfw_image_path $lfw_image_offset $lfw_size $spifw_image
|
||||
echo "*** Finish program LFW region ***\r\n"
|
||||
|
||||
# Reset CPU
|
||||
reset
|
||||
}
|
||||
|
||||
proc halt_npcx_cpu { } {
|
||||
|
||||
@@ -65,7 +65,7 @@ void pwm_freq_changed(void)
|
||||
* Using PWM Frequency and Resolution we calculate
|
||||
* prescaler for input clock
|
||||
*/
|
||||
#ifdef CONFIG_PWM_INPUT_LFCLK
|
||||
#ifdef NPCX_PWM_INPUT_LFCLK
|
||||
prescaler_divider = (uint32_t)(32768 /
|
||||
(pwm_channels[pwm_init_ch].freq)
|
||||
/(pwm_channels[pwm_init_ch].cycle_pulses));
|
||||
@@ -226,7 +226,7 @@ void pwm_config(enum pwm_channel ch)
|
||||
| (NPCX_PWM_CLOCK_APB2_LFCLK<<NPCX_PWMCTLEX_FCK_SEL);
|
||||
|
||||
if (ch == PWM_CH_FAN) {
|
||||
#ifdef CONFIG_PWM_INPUT_LFCLK
|
||||
#ifdef NPCX_PWM_INPUT_LFCLK
|
||||
/* Select default LFCLK clock input to PWM module */
|
||||
SET_BIT(NPCX_PWMCTL(pwm_channels[ch].channel),
|
||||
NPCX_PWMCTL_CKSEL);
|
||||
|
||||
@@ -27,12 +27,7 @@
|
||||
*/
|
||||
|
||||
/* Global Definition */
|
||||
#define CHIP_NPCX5M5G
|
||||
#define SUPPORT_JTAG
|
||||
#define I2C0_BUS0 1 /* Use I2C0_SDA0/1 I2C0_SCL0/1 */
|
||||
#define TACH_SEL1 1 /* Use TACH_SEL1 or TACH_SEL2 */
|
||||
#define JTAG1 0 /* Use JTAG0/1 JTAG1 only support
|
||||
132-Pins package*/
|
||||
#define CHIP_VERSION 3 /* A3 version */
|
||||
#define I2C_7BITS_ADDR 0
|
||||
#define I2C_LEVEL_SUPPORT 1
|
||||
/* Switcher of features */
|
||||
@@ -49,6 +44,7 @@
|
||||
#define DEBUG_SPI 0
|
||||
#define DEBUG_FLH 0
|
||||
#define DEBUG_PECI 0
|
||||
#define DEBUG_SHI 1
|
||||
#define DEBUG_CLK 1
|
||||
|
||||
/* Modules Map */
|
||||
@@ -61,6 +57,7 @@
|
||||
#define NPCX_GLUE_REGS_BASE 0x400A5000
|
||||
#define NPCX_BBRAM_BASE_ADDR 0x400AF000
|
||||
#define NPCX_HFCG_BASE_ADDR 0x400B5000
|
||||
#define NPCX_SHI_BASE_ADDR 0x4000F000
|
||||
#define NPCX_MTC_BASE_ADDR 0x400B7000
|
||||
#define NPCX_MSWC_BASE_ADDR 0x400C1000
|
||||
#define NPCX_SCFG_BASE_ADDR 0x400C3000
|
||||
@@ -75,6 +72,7 @@
|
||||
#define NPCX_PWM_BASE_ADDR(mdl) (0x40080000 + ((mdl) * 0x2000L))
|
||||
#define NPCX_GPIO_BASE_ADDR(mdl) (0x40081000 + ((mdl) * 0x2000L))
|
||||
#define NPCX_ITIM16_BASE_ADDR(mdl) (0x400B0000 + ((mdl) * 0x2000L))
|
||||
#define NPCX_ITIM32_BASE_ADDR 0x400BC000
|
||||
#define NPCX_MIWU_BASE_ADDR(mdl) (0x400BB000 + ((mdl) * 0x2000L))
|
||||
#define NPCX_MFT_BASE_ADDR(mdl) (0x400E1000 + ((mdl) * 0x2000L))
|
||||
#define NPCX_PM_CH_BASE_ADDR(mdl) (0x400C9000 + ((mdl) * 0x2000L))
|
||||
@@ -168,7 +166,7 @@
|
||||
#define NPCX_IRQ_WKINTC_0 NPCX_IRQ_15
|
||||
#define NPCX_IRQ16_NOUSED NPCX_IRQ_16
|
||||
#define NPCX_IRQ_ITIM16_3 NPCX_IRQ_17
|
||||
#define NPCX_IRQ_ESPI NPCX_IRQ_18
|
||||
#define NPCX_IRQ_SHI NPCX_IRQ_18
|
||||
#define NPCX_IRQ19_NOUSED NPCX_IRQ_19
|
||||
#define NPCX_IRQ20_NOUSED NPCX_IRQ_20
|
||||
#define NPCX_IRQ_PS2 NPCX_IRQ_21
|
||||
@@ -196,7 +194,7 @@
|
||||
#define NPCX_IRQ_ITIM16_4 NPCX_IRQ_43
|
||||
#define NPCX_IRQ_ITIM16_5 NPCX_IRQ_44
|
||||
#define NPCX_IRQ_ITIM16_6 NPCX_IRQ_45
|
||||
#define NPCX_IRQ46_NOUSED NPCX_IRQ_46
|
||||
#define NPCX_IRQ_ITIM32 NPCX_IRQ_46
|
||||
#define NPCX_IRQ_WKINTA_1 NPCX_IRQ_47
|
||||
#define NPCX_IRQ_WKINTB_1 NPCX_IRQ_48
|
||||
#define NPCX_IRQ_KSI_WKINTC_1 NPCX_IRQ_49
|
||||
@@ -393,6 +391,7 @@ enum {
|
||||
#define GPIO_D GPIO_PORT_D
|
||||
#define GPIO_E GPIO_PORT_E
|
||||
#define GPIO_F GPIO_PORT_F
|
||||
#define DUMMY_GPIO_BANK GPIO_PORT_0
|
||||
|
||||
/******************************************************************************/
|
||||
/* MSWC Registers */
|
||||
@@ -411,6 +410,7 @@ enum {
|
||||
#define NPCX_RSTCTL REG8(NPCX_SCFG_BASE_ADDR + 0x002)
|
||||
#define NPCX_DEV_CTL4 REG8(NPCX_SCFG_BASE_ADDR + 0x006)
|
||||
#define NPCX_DEVALT(n) REG8(NPCX_SCFG_BASE_ADDR + 0x010 + n)
|
||||
#define NPCX_LFCGCALCNT REG8(NPCX_SCFG_BASE_ADDR + 0x021)
|
||||
#define NPCX_DEVPU0 REG8(NPCX_SCFG_BASE_ADDR + 0x028)
|
||||
#define NPCX_DEVPU1 REG8(NPCX_SCFG_BASE_ADDR + 0x029)
|
||||
#define NPCX_LV_GPIO_CTL0 REG8(NPCX_SCFG_BASE_ADDR + 0x02A)
|
||||
@@ -458,6 +458,7 @@ enum {
|
||||
#define NPCX_RSTCTL_VCC1_RST_SCRATCH 3
|
||||
#define NPCX_RSTCTL_LRESET_PLTRST_MODE 5
|
||||
#define NPCX_RSTCTL_HIPRST_MODE 6
|
||||
#define NPCX_DEV_CTL4_F_SPI_SLLK 2
|
||||
#define NPCX_DEV_CTL4_SPI_SP_SEL 4
|
||||
#define NPCX_DEVPU0_I2C0_0_PUE 0
|
||||
#define NPCX_DEVPU0_I2C0_1_PUE 1
|
||||
@@ -550,17 +551,21 @@ enum {
|
||||
#define NPCX_DEVALTA_32KCLKIN_SL 3
|
||||
#define NPCX_DEVALTA_NO_VCC1_RST 4
|
||||
#define NPCX_DEVALTA_NO_PECI_EN 6
|
||||
#define NPCX_DEVALTA_UART_SL 7
|
||||
#define NPCX_DEVALTA_UART_SL1 7
|
||||
|
||||
#define NPCX_DEVALTB_RXD_SL 0
|
||||
#define NPCX_DEVALTB_TXD_SL 1
|
||||
|
||||
#define NPCX_DEVALTC_UART_SL2 0
|
||||
#define NPCX_DEVALTC_SHI_SL 1
|
||||
#define NPCX_DEVALTC_PS2_3_SL2 3
|
||||
#define NPCX_DEVALTC_TA1_TACH1_SL2 4
|
||||
#define NPCX_DEVALTC_TB1_TACH2_SL2 5
|
||||
#define NPCX_DEVALTC_TA2_SL2 6
|
||||
#define NPCX_DEVALTC_TB2_SL2 7
|
||||
|
||||
#define NPCX_LFCGCALCNT_LPREG_CTL_EN 1
|
||||
|
||||
/******************************************************************************/
|
||||
/* Development and Debug Support (DBG) Registers */
|
||||
#define NPCX_DBGCTRL REG8(NPCX_SCFG_BASE_ADDR + 0x074)
|
||||
@@ -645,6 +650,17 @@ enum {
|
||||
#define NPCX_SMBADDR7_SAEN 7
|
||||
#define NPCX_SMBADDR8_SAEN 7
|
||||
|
||||
/*
|
||||
* SMB enumeration
|
||||
* I2C Port.
|
||||
*/
|
||||
enum NPCX_I2C_PORT_T {
|
||||
NPCX_I2C_PORT0 = 0, /* I2C port 0, bus 0/1*/
|
||||
NPCX_I2C_PORT1 = 1, /* I2C port 1 */
|
||||
NPCX_I2C_PORT2 = 2, /* I2C port 2 */
|
||||
NPCX_I2C_PORT3 = 3, /* I2C port 3 */
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/* Power Management Controller (PMC) Registers */
|
||||
#define NPCX_PMCSR REG8(NPCX_PMC_BASE_ADDR + 0x000)
|
||||
@@ -694,6 +710,7 @@ enum {
|
||||
#define NPCX_PWDWN_CTL4_PECI_PD 5
|
||||
#define NPCX_PWDWN_CTL4_PWM6_PD 6
|
||||
#define NPCX_PWDWN_CTL4_SPIP_PD 7
|
||||
#define NPCX_PWDWN_CTL5_SHI_PD 1
|
||||
#define NPCX_PWDWN_CTL5_MRFSH_DIS 2
|
||||
#define NPCX_PWDWN_CTL5_C2HACC_PD 3
|
||||
#define NPCX_PWDWN_CTL5_SHM_REG_PD 4
|
||||
@@ -724,6 +741,15 @@ enum {
|
||||
CGC_OFFSET_ESPI = 5,
|
||||
};
|
||||
|
||||
enum NPCX_PMC_PWDWN_CTL_T {
|
||||
NPCX_PMC_PWDWN_1 = 0,
|
||||
NPCX_PMC_PWDWN_2 = 1,
|
||||
NPCX_PMC_PWDWN_3 = 2,
|
||||
NPCX_PMC_PWDWN_4 = 3,
|
||||
NPCX_PMC_PWDWN_5 = 4,
|
||||
NPCX_PMC_PWDWN_6 = 5,
|
||||
};
|
||||
|
||||
#define CGC_KBS_MASK (1 << NPCX_PWDWN_CTL1_KBS_PD)
|
||||
#define CGC_UART_MASK (1 << NPCX_PWDWN_CTL1_UART_PD)
|
||||
#define CGC_FAN_MASK (1 << NPCX_PWDWN_CTL1_MFT1_PD)
|
||||
@@ -779,6 +805,7 @@ enum {
|
||||
#define NPCX_UMA_ECTS_SW_CS0 0
|
||||
#define NPCX_UMA_ECTS_SW_CS1 1
|
||||
#define NPCX_UMA_ECTS_SEC_CS 2
|
||||
#define NPCX_UMA_ECTS_UMA_LOCK 3
|
||||
|
||||
/******************************************************************************/
|
||||
/* Shared Memory (SHM) Registers */
|
||||
@@ -1072,7 +1099,7 @@ enum PM_CHANNEL_T {
|
||||
#define NPCX_TWUEN_TCWEN 2
|
||||
#define NPCX_TWUEN_TDWEN 3
|
||||
/******************************************************************************/
|
||||
/*ITIM16 Define*/
|
||||
/* ITIM16/32 Define */
|
||||
#define ITIM16_INT(module) CONCAT2(NPCX_IRQ_, module)
|
||||
|
||||
/* ITIM16 registers */
|
||||
@@ -1081,12 +1108,15 @@ enum PM_CHANNEL_T {
|
||||
#define NPCX_ITCNT16(n) REG16(NPCX_ITIM16_BASE_ADDR(n) + 0x002)
|
||||
#define NPCX_ITCTS(n) REG8(NPCX_ITIM16_BASE_ADDR(n) + 0x004)
|
||||
|
||||
/* ITIM32 registers */
|
||||
#define NPCX_ITCNT32 REG32(NPCX_ITIM32_BASE_ADDR + 0x008)
|
||||
|
||||
/* ITIM16 register fields */
|
||||
#define NPCX_ITIM16_TO_STS 0
|
||||
#define NPCX_ITIM16_TO_IE 2
|
||||
#define NPCX_ITIM16_TO_WUE 3
|
||||
#define NPCX_ITIM16_CKSEL 4
|
||||
#define NPCX_ITIM16_ITEN 7
|
||||
#define NPCX_ITCTS_TO_STS 0
|
||||
#define NPCX_ITCTS_TO_IE 2
|
||||
#define NPCX_ITCTS_TO_WUE 3
|
||||
#define NPCX_ITCTS_CKSEL 4
|
||||
#define NPCX_ITCTS_ITEN 7
|
||||
|
||||
/* ITIM16 enumeration*/
|
||||
enum ITIM16_MODULE_T {
|
||||
@@ -1096,9 +1126,61 @@ enum ITIM16_MODULE_T {
|
||||
ITIM16_4,
|
||||
ITIM16_5,
|
||||
ITIM16_6,
|
||||
ITIM16_MODULE_COUNT,
|
||||
ITIM32,
|
||||
ITIM_MODULE_COUNT,
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/* Serial Host Interface (SHI) Registers */
|
||||
#define NPCX_SHICFG1 REG8(NPCX_SHI_BASE_ADDR + 0x001)
|
||||
#define NPCX_SHICFG2 REG8(NPCX_SHI_BASE_ADDR + 0x002)
|
||||
#define NPCX_I2CADDR1 REG8(NPCX_SHI_BASE_ADDR + 0x003)
|
||||
#define NPCX_I2CADDR2 REG8(NPCX_SHI_BASE_ADDR + 0x004)
|
||||
#define NPCX_EVENABLE REG8(NPCX_SHI_BASE_ADDR + 0x005)
|
||||
#define NPCX_EVSTAT REG8(NPCX_SHI_BASE_ADDR + 0x006)
|
||||
#define NPCX_SHI_CAPABILITY REG8(NPCX_SHI_BASE_ADDR + 0x007)
|
||||
#define NPCX_STATUS REG8(NPCX_SHI_BASE_ADDR + 0x008)
|
||||
#define NPCX_IBUFSTAT REG8(NPCX_SHI_BASE_ADDR + 0x00A)
|
||||
#define NPCX_OBUFSTAT REG8(NPCX_SHI_BASE_ADDR + 0x00B)
|
||||
#define NPCX_ADVCFG REG8(NPCX_SHI_BASE_ADDR + 0x00E)
|
||||
#define NPCX_OBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x020 + (n))
|
||||
#define NPCX_IBUF(n) REG8(NPCX_SHI_BASE_ADDR + 0x060 + (n))
|
||||
|
||||
/* SHI register fields */
|
||||
#define NPCX_SHICFG1_EN 0
|
||||
#define NPCX_SHICFG1_MODE 1
|
||||
#define NPCX_SHICFG1_WEN 2
|
||||
#define NPCX_SHICFG1_AUTIBF 3
|
||||
#define NPCX_SHICFG1_AUTOBE 4
|
||||
#define NPCX_SHICFG1_DAS 5
|
||||
#define NPCX_SHICFG1_CPOL 6
|
||||
#define NPCX_SHICFG1_IWRAP 7
|
||||
#define NPCX_SHICFG2_SIMUL 0
|
||||
#define NPCX_SHICFG2_BUSY 1
|
||||
#define NPCX_SHICFG2_ONESHOT 2
|
||||
#define NPCX_SHICFG2_SLWU 3
|
||||
#define NPCX_SHICFG2_REEN 4
|
||||
#define NPCX_SHICFG2_RESTART 5
|
||||
#define NPCX_SHICFG2_REEVEN 6
|
||||
#define NPCX_EVENABLE_OBEEN 0
|
||||
#define NPCX_EVENABLE_OBHEEN 1
|
||||
#define NPCX_EVENABLE_IBFEN 2
|
||||
#define NPCX_EVENABLE_IBHFEN 3
|
||||
#define NPCX_EVENABLE_EOREN 4
|
||||
#define NPCX_EVENABLE_EOWEN 5
|
||||
#define NPCX_EVENABLE_STSREN 6
|
||||
#define NPCX_EVENABLE_IBOREN 7
|
||||
#define NPCX_EVSTAT_OBE 0
|
||||
#define NPCX_EVSTAT_OBHE 1
|
||||
#define NPCX_EVSTAT_IBF 2
|
||||
#define NPCX_EVSTAT_IBHF 3
|
||||
#define NPCX_EVSTAT_EOR 4
|
||||
#define NPCX_EVSTAT_EOW 5
|
||||
#define NPCX_EVSTAT_STSR 6
|
||||
#define NPCX_EVSTAT_IBOR 7
|
||||
#define NPCX_STATUS_OBES 6
|
||||
#define NPCX_STATUS_IBFS 7
|
||||
|
||||
/******************************************************************************/
|
||||
/* Monotonic Counter (MTC) Registers */
|
||||
#define NPCX_TTC REG32(NPCX_MTC_BASE_ADDR + 0x000)
|
||||
@@ -1114,6 +1196,12 @@ enum ITIM16_MODULE_T {
|
||||
/* Low Power RAM definitions */
|
||||
#define NPCX_LPRAM_CTRL REG32(0x40001044)
|
||||
|
||||
/******************************************************************************/
|
||||
/* Nuvoton internal used only registers */
|
||||
#define NPCX_INTERNAL_CTRL1 REG8(0x400DB000)
|
||||
#define NPCX_INTERNAL_CTRL2 REG8(0x400DD000)
|
||||
#define NPCX_INTERNAL_CTRL3 REG8(0x400DF000)
|
||||
|
||||
/******************************************************************************/
|
||||
/* Optional M4 Registers */
|
||||
#define CPU_DHCSR REG32(0xE000EDF0)
|
||||
@@ -1196,4 +1284,76 @@ enum ITIM16_MODULE_T {
|
||||
#define MASK_CMD_WR_ADR (MASK(EXEC_DONE) | FLASH_SEL | MASK(RD_WR) \
|
||||
| MASK(A_SIZE))
|
||||
|
||||
/******************************************************************************/
|
||||
/* Inline functions */
|
||||
/* This routine checks pending bit of GPIO wake-up functionality */
|
||||
static inline int uart_is_wakeup_from_gpio(void)
|
||||
{
|
||||
#if NPCX_UART_MODULE2
|
||||
return IS_BIT_SET(NPCX_WKPND(1, 6), 4);
|
||||
#else
|
||||
return IS_BIT_SET(NPCX_WKPND(1, 1), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This routine clear pending bit of GPIO wake-up functionality */
|
||||
static inline void uart_clear_wakeup_event(void)
|
||||
{
|
||||
#if NPCX_UART_MODULE2
|
||||
SET_BIT(NPCX_WKPND(1, 6), 4);
|
||||
#else
|
||||
SET_BIT(NPCX_WKPND(1, 1), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This routine checks wake-up functionality from GPIO is enabled or not */
|
||||
static inline int uart_is_enable_wakeup(void)
|
||||
{
|
||||
#if NPCX_UART_MODULE2
|
||||
return IS_BIT_SET(NPCX_WKEN(1, 6), 4);
|
||||
#else
|
||||
return IS_BIT_SET(NPCX_WKEN(1, 1), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This routine enables wake-up functionality from GPIO on UART rx pin */
|
||||
static inline void uart_enable_wakeup(int enable)
|
||||
{
|
||||
#if NPCX_UART_MODULE2
|
||||
UPDATE_BIT(NPCX_WKEN(1, 6), 4, enable);
|
||||
#else
|
||||
UPDATE_BIT(NPCX_WKEN(1, 1), 0, enable);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This routine checks functionality is UART rx or not */
|
||||
static inline int npcx_is_uart(void)
|
||||
{
|
||||
#if NPCX_UART_MODULE2
|
||||
return IS_BIT_SET(NPCX_DEVALT(0x0C), NPCX_DEVALTC_UART_SL2);
|
||||
#else
|
||||
return IS_BIT_SET(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This routine switches the functionality from UART rx to GPIO */
|
||||
static inline void npcx_uart2gpio(void)
|
||||
{
|
||||
#if NPCX_UART_MODULE2
|
||||
CLEAR_BIT(NPCX_DEVALT(0x0C), NPCX_DEVALTC_UART_SL2);
|
||||
#else
|
||||
CLEAR_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This routine switches the functionality from GPIO to UART rx */
|
||||
static inline void npcx_gpio2uart(void)
|
||||
{
|
||||
#if NPCX_UART_MODULE2
|
||||
CLEAR_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL1);
|
||||
SET_BIT(NPCX_DEVALT(0x0C), NPCX_DEVALTC_UART_SL2);
|
||||
#else
|
||||
SET_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL1);
|
||||
#endif
|
||||
}
|
||||
#endif /* __CROS_EC_REGISTERS_H */
|
||||
|
||||
66
chip/npcx/rom_chip.h
Normal file
66
chip/npcx/rom_chip.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
#ifndef __CROS_EC_ROM_CHIP_H_
|
||||
#define __CROS_EC_ROM_CHIP_H_
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Enumerations of ROM api functions
|
||||
*/
|
||||
enum API_SIGN_OPTIONS_T {
|
||||
SIGN_NO_CHECK = 0,
|
||||
SIGN_CRC_CHECK = 1,
|
||||
};
|
||||
|
||||
enum API_RETURN_STATUS_T {
|
||||
/* Successful download */
|
||||
API_RET_STATUS_OK = 0,
|
||||
/* Address is outside of flash or not 4 bytes aligned. */
|
||||
API_RET_STATUS_INVALID_SRC_ADDR = 1,
|
||||
/* Address is outside of RAM or not 4 bytes aligned. */
|
||||
API_RET_STATUS_INVALID_DST_ADDR = 2,
|
||||
/* Size is 0 or not 4 bytes aligned. */
|
||||
API_RET_STATUS_INVALID_SIZE = 3,
|
||||
/* Flash Address + Size is out of flash. */
|
||||
API_RET_STATUS_INVALID_SIZE_OUT_OF_FLASH = 4,
|
||||
/* RAM Address + Size is out of RAM. */
|
||||
API_RET_STATUS_INVALID_SIZE_OUT_OF_RAM = 5,
|
||||
/* Wrong sign option. */
|
||||
API_RET_STATUS_INVALID_SIGN = 6,
|
||||
/* Error during Code copy. */
|
||||
API_RET_STATUS_COPY_FAILED = 7,
|
||||
/* Execution Address is outside of RAM */
|
||||
API_RET_STATUS_INVALID_EXE_ADDR = 8,
|
||||
/* Bad CRC value */
|
||||
API_RET_STATUS_INVALID_SIGNATURE = 9,
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Macro functions of ROM api functions
|
||||
*/
|
||||
#define ADDR_DOWNLOAD_FROM_FLASH (*(volatile uint32_t *) 0x40)
|
||||
#define download_from_flash(src_offset, dest_addr, size, sign, exe_addr, \
|
||||
status) \
|
||||
(((download_from_flash_ptr) ADDR_DOWNLOAD_FROM_FLASH) \
|
||||
(src_offset, dest_addr, size, sign, exe_addr, status))
|
||||
|
||||
/******************************************************************************/
|
||||
/*
|
||||
* Declarations of ROM api functions
|
||||
*/
|
||||
typedef void (*download_from_flash_ptr) (
|
||||
uint32_t src_offset, /* The offset of the data to be downloaded */
|
||||
uint32_t dest_addr, /* The address of the downloaded data in the RAM*/
|
||||
uint32_t size, /* Number of bytes to download */
|
||||
enum API_SIGN_OPTIONS_T sign, /* Need CRC check or not */
|
||||
uint32_t exe_addr, /* jump to this address after download if not zero */
|
||||
enum API_RETURN_STATUS_T *status /* Status fo download */
|
||||
);
|
||||
|
||||
|
||||
|
||||
#endif /* __CROS_EC_ROM_CHIP_H_ */
|
||||
859
chip/npcx/shi.c
Normal file
859
chip/npcx/shi.c
Normal file
@@ -0,0 +1,859 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SHI driver for Chrome EC.
|
||||
*
|
||||
* This uses Input/Output buffer to handle SPI transmission and reception.
|
||||
*/
|
||||
|
||||
#include "chipset.h"
|
||||
#include "clock.h"
|
||||
#include "console.h"
|
||||
#include "gpio.h"
|
||||
#include "task.h"
|
||||
#include "hooks.h"
|
||||
#include "host_command.h"
|
||||
#include "registers.h"
|
||||
#include "spi.h"
|
||||
#include "system.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
|
||||
#if !(DEBUG_SHI)
|
||||
#define CPUTS(...)
|
||||
#define CPRINTS(...)
|
||||
#define CPRINTF(...)
|
||||
#else
|
||||
#define CPUTS(outstr) cputs(CC_SPI, outstr)
|
||||
#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args)
|
||||
#define CPRINTF(format, args...) cprintf(CC_SPI, format, ## args)
|
||||
#endif
|
||||
|
||||
/* SHI Bus definition */
|
||||
#define SHI_OBUF_FULL_SIZE 64 /* Full output buffer size */
|
||||
#define SHI_IBUF_FULL_SIZE 64 /* Full input buffer size */
|
||||
#define SHI_OBUF_HALF_SIZE (SHI_OBUF_FULL_SIZE/2) /* Half output buffer size */
|
||||
#define SHI_IBUF_HALF_SIZE (SHI_IBUF_FULL_SIZE/2) /* Half input buffer size */
|
||||
|
||||
/* Start address of SHI output buffer */
|
||||
#define SHI_OBUF_START_ADDR (volatile uint8_t *)(NPCX_SHI_BASE_ADDR + 0x020)
|
||||
/* Middle address of SHI output buffer */
|
||||
#define SHI_OBUF_HALF_ADDR (SHI_OBUF_START_ADDR + SHI_OBUF_HALF_SIZE)
|
||||
/* Top address of SHI output buffer */
|
||||
#define SHI_OBUF_FULL_ADDR (SHI_OBUF_START_ADDR + SHI_IBUF_FULL_SIZE)
|
||||
/*
|
||||
* Valid offset of SHI output buffer to write.
|
||||
* When SIMUL bit is set, IBUFPTR can be used instead of OBUFPTR
|
||||
*/
|
||||
#define SHI_OBUF_VALID_OFFSET ((NPCX_IBUFSTAT + SHI_OUT_PREAMBLE_LENGTH) % \
|
||||
SHI_OBUF_FULL_SIZE)
|
||||
/* Start address of SHI input buffer */
|
||||
#define SHI_IBUF_START_ADDR (volatile uint8_t *)(NPCX_SHI_BASE_ADDR + 0x060)
|
||||
/* Current address of SHI input buffer */
|
||||
#define SHI_IBUF_CUR_ADDR (SHI_IBUF_START_ADDR + NPCX_IBUFSTAT)
|
||||
|
||||
/*
|
||||
* Timeout to wait for SHI request packet
|
||||
*
|
||||
* This affects the slowest SPI clock we can support. A delay of 8192 us
|
||||
* permits a 512-byte request at 500 KHz, assuming the master starts sending
|
||||
* bytes as soon as it asserts chip select. That's as slow as we would
|
||||
* practically want to run the SHI interface, since running it slower
|
||||
* significantly impacts firmware update times.
|
||||
*/
|
||||
#define SHI_CMD_RX_TIMEOUT_US 8192
|
||||
|
||||
/* Timeout for glitch case. Make sure it will exceed 8 SPI clocks */
|
||||
#define SHI_GLITCH_TIMEOUT_US 10
|
||||
|
||||
/*
|
||||
* Max data size for a version 3 request/response packet. This is big enough
|
||||
* to handle a request/response header, flash write offset/size, and 512 bytes
|
||||
* of flash data.
|
||||
*/
|
||||
#define SHI_MAX_REQUEST_SIZE 0x220
|
||||
#define SHI_MAX_RESPONSE_SIZE 0x220
|
||||
|
||||
/*
|
||||
* The AP blindly clocks back bytes over the SPI interface looking for a
|
||||
* framing byte. So this preamble must always precede the actual response
|
||||
* packet.
|
||||
*/
|
||||
|
||||
#define SHI_OUT_PREAMBLE_LENGTH 2
|
||||
/*
|
||||
* Space allocation of the past-end status byte (EC_SPI_PAST_END) in the out_msg
|
||||
* buffer.
|
||||
*/
|
||||
#define EC_SPI_PAST_END_LENGTH 1
|
||||
/*
|
||||
* Space allocation of the frame status byte (EC_SPI_FRAME_START) in the out_msg
|
||||
* buffer.
|
||||
*/
|
||||
#define EC_SPI_FRAME_START_LENGTH 1
|
||||
|
||||
/*
|
||||
* Offset of output parameters needs to account for pad and framing bytes and
|
||||
* one last past-end byte at the end so any additional bytes clocked out by
|
||||
* the AP will have a known and identifiable value.
|
||||
*/
|
||||
#define SHI_PROTO2_OFFSET (EC_PROTO2_RESPONSE_HEADER_BYTES + 1)
|
||||
#define SHI_PROTO2_OVERHEAD (SHI_PROTO2_OFFSET + \
|
||||
EC_PROTO2_RESPONSE_TRAILER_BYTES + 1)
|
||||
#define SHI_PROTO3_OVERHEAD (EC_SPI_PAST_END_LENGTH + EC_SPI_FRAME_START_LENGTH)
|
||||
|
||||
/*
|
||||
* Our input and output msg buffers. These must be large enough for our largest
|
||||
* message, including protocol overhead, and must be 32-bit aligned.
|
||||
*/
|
||||
static uint8_t out_msg[SHI_MAX_RESPONSE_SIZE];
|
||||
static uint8_t in_msg[SHI_MAX_REQUEST_SIZE];
|
||||
|
||||
/* Parameters used by host protocols */
|
||||
static struct host_cmd_handler_args args;
|
||||
static struct host_packet shi_packet;
|
||||
|
||||
/* Function pointer for handler of host request */
|
||||
void (*request_handler)(void);
|
||||
|
||||
enum shi_state {
|
||||
/* SHI not enabled (initial state, and when chipset is off) */
|
||||
SHI_STATE_DISABLED = 0,
|
||||
/* Ready to receive next request */
|
||||
SHI_STATE_READY_TO_RECV,
|
||||
/* Complete transaction but need to initialize */
|
||||
SHI_STATE_NOT_READY,
|
||||
/* Receiving request */
|
||||
SHI_STATE_RECEIVING,
|
||||
/* Processing request */
|
||||
SHI_STATE_PROCESSING,
|
||||
/* Sending response */
|
||||
SHI_STATE_SENDING,
|
||||
/* State machine mismatch, timeout, or protocol we can't handle. */
|
||||
SHI_STATE_ERROR,
|
||||
} state;
|
||||
|
||||
/* SHI bus parameters */
|
||||
struct shi_bus_parameters {
|
||||
uint8_t *rx_msg; /* Entry pointer of msg rx buffer */
|
||||
uint8_t *tx_msg; /* Entry pointer of msg tx buffer */
|
||||
volatile uint8_t *rx_buf; /* Entry pointer of receive buffer */
|
||||
volatile uint8_t *tx_buf; /* Entry pointer of transmit buffer */
|
||||
uint16_t sz_received; /* Size of received data in bytes */
|
||||
uint16_t sz_sending; /* Size of sending data in bytes */
|
||||
uint16_t sz_request; /* request bytes need to receive */
|
||||
uint16_t sz_response; /* response bytes need to receive */
|
||||
timestamp_t rx_deadline; /* deadline of receiving */
|
||||
uint8_t pre_ibufstat; /* Previous IBUFSTAT value */
|
||||
} shi_params;
|
||||
|
||||
/* Forward declaraction */
|
||||
static void shi_reset_prepare(void);
|
||||
static void shi_error(int need_reset);
|
||||
static void shi_fill_out_status(uint8_t status);
|
||||
static void shi_write_half_outbuf(void);
|
||||
static void shi_write_outbuf_wait(uint16_t szbytes);
|
||||
static int shi_read_inbuf_wait(uint16_t szbytes);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* V2 protocol layer functions */
|
||||
|
||||
/**
|
||||
* The format of a reply is as per the command interface, with a number of
|
||||
* preamble bytes before it.
|
||||
*
|
||||
* The format of a reply is a sequence of bytes:
|
||||
*
|
||||
* <hdr> <status> <len> <msg bytes> <sum> [<postamble byte>...]
|
||||
*
|
||||
* The hdr byte is just a tag to indicate that the real message follows. It
|
||||
* signals the end of any preamble required by the interface.
|
||||
*
|
||||
* The length is the entire packet size, including the header, length bytes,
|
||||
* message payload, checksum, and postamble byte.
|
||||
*
|
||||
* We keep an eye on the SHI_CS_L line - if this goes high then the transaction
|
||||
* is over so there is no point in trying to send the reply.
|
||||
*/
|
||||
static void shi_reply_response(enum ec_status status, uint8_t *msg_ptr,
|
||||
int msg_len)
|
||||
{
|
||||
int need_copy = msg_ptr != out_msg + SHI_PROTO2_OFFSET;
|
||||
int sum, i;
|
||||
|
||||
ASSERT(msg_len + SHI_PROTO2_OVERHEAD <= sizeof(out_msg));
|
||||
|
||||
/* Add our header bytes - the first one might not actually be sent */
|
||||
out_msg[0] = EC_SPI_FRAME_START;
|
||||
out_msg[1] = status;
|
||||
out_msg[2] = msg_len & 0xff;
|
||||
|
||||
/*
|
||||
* Calculate the checksum; includes the status and message length bytes
|
||||
* but not the pad and framing bytes since those are stripped by the AP
|
||||
* driver.
|
||||
*/
|
||||
sum = status + msg_len;
|
||||
for (i = 0; i < msg_len; i++) {
|
||||
int ch = msg_ptr[i];
|
||||
sum += ch;
|
||||
if (need_copy)
|
||||
out_msg[i + SHI_PROTO2_OFFSET] = ch;
|
||||
}
|
||||
|
||||
/* Add the checksum and get ready to send */
|
||||
out_msg[SHI_PROTO2_OFFSET + msg_len] = sum & 0xff;
|
||||
out_msg[SHI_PROTO2_OFFSET + msg_len + 1] = EC_SPI_PAST_END;
|
||||
|
||||
/* Computing sending bytes of response */
|
||||
shi_params.sz_response = msg_len + SHI_PROTO2_OVERHEAD;
|
||||
|
||||
/*
|
||||
* Before the state is set to SENDING, any CS de-assertion would
|
||||
* give up sending.
|
||||
*/
|
||||
if (state == SHI_STATE_PROCESSING) {
|
||||
/*
|
||||
* Disable SHI interrupt until we have prepared
|
||||
* the first package to output
|
||||
*/
|
||||
task_disable_irq(NPCX_IRQ_SHI);
|
||||
/* Transmit the reply */
|
||||
state = SHI_STATE_SENDING;
|
||||
CPRINTF("SND-");
|
||||
/* Start to fill output buffer with msg buffer */
|
||||
shi_write_outbuf_wait(shi_params.sz_response);
|
||||
/* Enable SHI interrupt */
|
||||
task_enable_irq(NPCX_IRQ_SHI);
|
||||
}
|
||||
/*
|
||||
* If we're not processing, then the AP has already terminated the
|
||||
* transaction, and won't be listening for a response.
|
||||
*/
|
||||
else {
|
||||
/* Reset SHI and prepare to next transaction again */
|
||||
shi_reset_prepare();
|
||||
CPRINTF("END\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called for V2 protocol to indicate that a command has completed
|
||||
*
|
||||
* Some commands can continue for a while. This function is called by
|
||||
* host_command when it completes.
|
||||
*
|
||||
*/
|
||||
static void shi_send_response(struct host_cmd_handler_args *args)
|
||||
{
|
||||
enum ec_status result = args->result;
|
||||
|
||||
if (args->response_size > args->response_max)
|
||||
result = EC_RES_INVALID_RESPONSE;
|
||||
|
||||
/* Transmit the reply */
|
||||
args->response_size += (EC_SPI_PAST_END_LENGTH +
|
||||
EC_SPI_FRAME_START_LENGTH);
|
||||
shi_reply_response(result, args->response, args->response_size);
|
||||
}
|
||||
|
||||
void shi_handle_host_command(void)
|
||||
{
|
||||
uint16_t sz_inbuf_int = shi_params.sz_request / SHI_IBUF_HALF_SIZE;
|
||||
uint16_t cnt_inbuf_int = shi_params.sz_received / SHI_IBUF_HALF_SIZE;
|
||||
if (sz_inbuf_int - cnt_inbuf_int)
|
||||
/* Need to receive data from buffer */
|
||||
return;
|
||||
else {
|
||||
uint16_t remain_bytes = shi_params.sz_request
|
||||
- shi_params.sz_received;
|
||||
/* Move to processing state immediately */
|
||||
state = SHI_STATE_PROCESSING;
|
||||
CPRINTF("PRC-");
|
||||
/* Read remaining bytes from input buffer directly */
|
||||
if (!shi_read_inbuf_wait(remain_bytes))
|
||||
return shi_error(1);
|
||||
}
|
||||
|
||||
/* Fill output buffer to indicate we`re processing request */
|
||||
shi_fill_out_status(EC_SPI_PROCESSING);
|
||||
|
||||
/* Set up parameters for host request */
|
||||
args.params = in_msg + 3;
|
||||
args.send_response = shi_send_response;
|
||||
|
||||
/* Allow room for the header bytes */
|
||||
args.response = out_msg + SHI_PROTO2_OFFSET;
|
||||
args.response_max = sizeof(out_msg) - SHI_PROTO2_OVERHEAD;
|
||||
args.response_size = 0;
|
||||
args.result = EC_RES_SUCCESS;
|
||||
|
||||
/* Go to common-layer to handle request */
|
||||
host_command_received(&args);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* V3 protocol layer functions */
|
||||
|
||||
/**
|
||||
* Called to send a response back to the host.
|
||||
*
|
||||
* Some commands can continue for a while. This function is called by
|
||||
* host_command when it completes.
|
||||
*
|
||||
*/
|
||||
static void shi_send_response_packet(struct host_packet *pkt)
|
||||
{
|
||||
/* Append our past-end byte, which we reserved space for. */
|
||||
((uint8_t *) pkt->response)[pkt->response_size + 0] = EC_SPI_PAST_END;
|
||||
|
||||
/* Computing sending bytes of response */
|
||||
shi_params.sz_response = pkt->response_size + SHI_PROTO3_OVERHEAD;
|
||||
|
||||
/*
|
||||
* Before the state is set to SENDING, any CS de-assertion would
|
||||
* give up sending.
|
||||
*/
|
||||
if (state == SHI_STATE_PROCESSING) {
|
||||
/*
|
||||
* Disable SHI interrupt until we have prepared
|
||||
* the first package to output
|
||||
*/
|
||||
task_disable_irq(NPCX_IRQ_SHI);
|
||||
/* Transmit the reply */
|
||||
state = SHI_STATE_SENDING;
|
||||
CPRINTF("SND-");
|
||||
/* Start to fill output buffer with msg buffer */
|
||||
shi_write_outbuf_wait(shi_params.sz_response);
|
||||
/* Enable SHI interrupt */
|
||||
task_enable_irq(NPCX_IRQ_SHI);
|
||||
}
|
||||
/*
|
||||
* If we're not processing, then the AP has already terminated the
|
||||
* transaction, and won't be listening for a response.
|
||||
*/
|
||||
else {
|
||||
/* Reset SHI and prepare to next transaction again */
|
||||
shi_reset_prepare();
|
||||
CPRINTF("END\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void shi_handle_host_package(void)
|
||||
{
|
||||
uint16_t sz_inbuf_int = shi_params.sz_request / SHI_IBUF_HALF_SIZE;
|
||||
uint16_t cnt_inbuf_int = shi_params.sz_received / SHI_IBUF_HALF_SIZE;
|
||||
if (sz_inbuf_int - cnt_inbuf_int)
|
||||
/* Need to receive data from buffer */
|
||||
return;
|
||||
else {
|
||||
uint16_t remain_bytes = shi_params.sz_request
|
||||
- shi_params.sz_received;
|
||||
/* Move to processing state immediately */
|
||||
state = SHI_STATE_PROCESSING;
|
||||
CPRINTF("PRC-");
|
||||
/* Read remaining bytes from input buffer directly */
|
||||
if (!shi_read_inbuf_wait(remain_bytes))
|
||||
return shi_error(1);
|
||||
}
|
||||
/* Fill output buffer to indicate we`re processing request */
|
||||
shi_fill_out_status(EC_SPI_PROCESSING);
|
||||
|
||||
/* Set up parameters for host request */
|
||||
shi_packet.send_response = shi_send_response_packet;
|
||||
|
||||
shi_packet.request = in_msg;
|
||||
shi_packet.request_temp = NULL;
|
||||
shi_packet.request_max = sizeof(in_msg);
|
||||
shi_packet.request_size = shi_params.sz_request;
|
||||
|
||||
/* Put FRAME_START in first byte */
|
||||
out_msg[0] = EC_SPI_FRAME_START;
|
||||
shi_packet.response = out_msg + 1;
|
||||
|
||||
/* Reserve space for frame start and trailing past-end byte */
|
||||
shi_packet.response_max = sizeof(out_msg) - SHI_PROTO3_OVERHEAD;
|
||||
shi_packet.response_size = 0;
|
||||
shi_packet.driver_result = EC_RES_SUCCESS;
|
||||
|
||||
/* Go to common-layer to handle request */
|
||||
host_packet_receive(&shi_packet);
|
||||
}
|
||||
|
||||
/* Parse header for version of spi-protocol */
|
||||
static void shi_parse_header(void)
|
||||
{
|
||||
/* Wait for version, command, length bytes */
|
||||
if (!shi_read_inbuf_wait(3))
|
||||
return shi_error(1);
|
||||
|
||||
if (in_msg[0] == EC_HOST_REQUEST_VERSION) {
|
||||
/* Protocol version 3 */
|
||||
struct ec_host_request *r = (struct ec_host_request *) in_msg;
|
||||
int pkt_size;
|
||||
/*
|
||||
* If request is over 32 bytes,
|
||||
* we need to modified the algorithm again.
|
||||
*/
|
||||
ASSERT(sizeof(*r) < SHI_IBUF_HALF_SIZE);
|
||||
|
||||
/* Wait for the rest of the command header */
|
||||
if (!shi_read_inbuf_wait(sizeof(*r) - 3))
|
||||
return shi_error(1);
|
||||
|
||||
/* Check how big the packet should be */
|
||||
pkt_size = host_request_expected_size(r);
|
||||
if (pkt_size == 0 || pkt_size > sizeof(in_msg))
|
||||
return shi_error(0);
|
||||
|
||||
/* Computing total bytes need to receive */
|
||||
shi_params.sz_request = pkt_size;
|
||||
|
||||
/* Set handler for host_package */
|
||||
request_handler = shi_handle_host_package;
|
||||
|
||||
} else if (in_msg[0] >= EC_CMD_VERSION0) {
|
||||
/*
|
||||
* Protocol version 2
|
||||
* TODO(crosbug.com/p/20257): Remove once kernel supports
|
||||
* version 3.
|
||||
*/
|
||||
args.version = in_msg[0] - EC_CMD_VERSION0;
|
||||
args.command = in_msg[1];
|
||||
args.params_size = in_msg[2];
|
||||
|
||||
/* Computing remaining received bytes */
|
||||
shi_params.sz_request = args.params_size + 3;
|
||||
|
||||
/* Set handler for host_command */
|
||||
request_handler = shi_handle_host_command;
|
||||
} else {
|
||||
/* Invalid version number */
|
||||
return shi_error(0);
|
||||
}
|
||||
/* run receiving handler */
|
||||
request_handler();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* IC specific low-level driver */
|
||||
|
||||
/* This routine fills out all SHI output buffer with status byte */
|
||||
static void shi_fill_out_status(uint8_t status)
|
||||
{
|
||||
uint16_t i;
|
||||
uint16_t offset = SHI_OBUF_VALID_OFFSET;
|
||||
|
||||
/* Fill out all output buffer with status byte */
|
||||
for (i = offset; i < SHI_OBUF_FULL_SIZE; i++)
|
||||
NPCX_OBUF(i) = status;
|
||||
for (i = 0; i < offset; i++)
|
||||
NPCX_OBUF(i) = status;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine write SHI next half output buffer from msg buffer
|
||||
*/
|
||||
static void shi_write_half_outbuf(void)
|
||||
{
|
||||
uint16_t i;
|
||||
uint16_t size = MIN(SHI_OBUF_HALF_SIZE,
|
||||
shi_params.sz_response - shi_params.sz_sending);
|
||||
/* Fill half output buffer */
|
||||
for (i = 0; i < size; i++, shi_params.sz_sending++)
|
||||
*(shi_params.tx_buf++) = *(shi_params.tx_msg++);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine write SHI output buffer from msg buffer until
|
||||
* we have sent a certain number of bytes or output buffer is full
|
||||
*/
|
||||
static void shi_write_outbuf_wait(uint16_t szbytes)
|
||||
{
|
||||
uint16_t i;
|
||||
static uint16_t offset, size;
|
||||
offset = SHI_OBUF_VALID_OFFSET;
|
||||
shi_params.tx_buf = SHI_OBUF_START_ADDR + offset;
|
||||
|
||||
/* Fill half output buffer */
|
||||
size = MIN(SHI_OBUF_HALF_SIZE - (offset % SHI_OBUF_HALF_SIZE),
|
||||
szbytes - shi_params.sz_sending);
|
||||
for (i = 0; i < size; i++, shi_params.sz_sending++)
|
||||
*(shi_params.tx_buf++) = *(shi_params.tx_msg++);
|
||||
|
||||
/* Write data from bottom address again */
|
||||
if (shi_params.tx_buf == SHI_OBUF_FULL_ADDR)
|
||||
shi_params.tx_buf = SHI_OBUF_START_ADDR;
|
||||
|
||||
/* Fill next half output buffer */
|
||||
size = MIN(SHI_OBUF_HALF_SIZE, szbytes - shi_params.sz_sending);
|
||||
for (i = 0; i < size; i++, shi_params.sz_sending++)
|
||||
*(shi_params.tx_buf++) = *(shi_params.tx_msg++);
|
||||
}
|
||||
|
||||
/* This routine copies SHI half input buffer data to msg buffer */
|
||||
static void shi_read_half_inbuf(void)
|
||||
{
|
||||
/*
|
||||
* Copy to read buffer until reaching middle/top address of
|
||||
* input buffer or completing receiving data
|
||||
*/
|
||||
do {
|
||||
/* Restore data to msg buffer */
|
||||
*(shi_params.rx_msg++) = *(shi_params.rx_buf++);
|
||||
shi_params.sz_received++;
|
||||
} while (shi_params.sz_received % SHI_IBUF_HALF_SIZE
|
||||
&& shi_params.sz_received != shi_params.sz_request);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine make sure input buffer status register is valid or it will
|
||||
* return flase after timeout
|
||||
*/
|
||||
static int shi_check_inbuf_valid(void)
|
||||
{
|
||||
timestamp_t deadline = get_time();
|
||||
deadline.val += SHI_GLITCH_TIMEOUT_US;
|
||||
/*
|
||||
* If input buffer pointer is no changed after timeout, it will
|
||||
* return false
|
||||
*/
|
||||
while (NPCX_IBUFSTAT == shi_params.pre_ibufstat)
|
||||
if (timestamp_expired(deadline, NULL))
|
||||
return 0;
|
||||
/* valid package */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine read SHI input buffer to msg buffer until
|
||||
* we have received a certain number of bytes
|
||||
*/
|
||||
static int shi_read_inbuf_wait(uint16_t szbytes)
|
||||
{
|
||||
uint16_t i;
|
||||
|
||||
/* Copy data to msg buffer from input buffer */
|
||||
for (i = 0; i < szbytes; i++, shi_params.sz_received++) {
|
||||
/*
|
||||
* If input buffer pointer equals pointer which wants to read,
|
||||
* it means data is not ready.
|
||||
*/
|
||||
while (shi_params.rx_buf == SHI_IBUF_CUR_ADDR)
|
||||
if (timestamp_expired(shi_params.rx_deadline, NULL))
|
||||
return 0;
|
||||
/* Restore data to msg buffer */
|
||||
*(shi_params.rx_msg++) = *(shi_params.rx_buf++);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This routine handles bus error condition */
|
||||
static void shi_error(int need_reset)
|
||||
{
|
||||
uint16_t i;
|
||||
/* State machine mismatch, timeout, or protocol we can't handle. */
|
||||
shi_fill_out_status(EC_SPI_RX_BAD_DATA);
|
||||
state = SHI_STATE_ERROR;
|
||||
|
||||
CPRINTS("ERR-[");
|
||||
CPRINTF("in_msg=[");
|
||||
for (i = 0; i < shi_params.sz_received; i++)
|
||||
CPRINTF("%02x ", in_msg[i]);
|
||||
CPRINTF("]\n");
|
||||
|
||||
/*
|
||||
* If glitch occurred or losing clocks, EVSTAT_EOR/W
|
||||
* will not generate. We need to reset SHI bus here.
|
||||
*/
|
||||
if (need_reset)
|
||||
shi_reset_prepare();
|
||||
}
|
||||
|
||||
/* This routine handles all interrupts of this module */
|
||||
void shi_int_handler(void)
|
||||
{
|
||||
uint8_t stat_reg;
|
||||
|
||||
/* Read status register and clear interrupt status early*/
|
||||
stat_reg = NPCX_EVSTAT;
|
||||
NPCX_EVSTAT = stat_reg;
|
||||
|
||||
/*
|
||||
* End of data for read/write transaction. ie SHI_CS is deasserted.
|
||||
* Host completed or aborted transaction
|
||||
*/
|
||||
if (IS_BIT_SET(stat_reg, NPCX_EVSTAT_EOR)) {
|
||||
/* Already reset in shi_error or not */
|
||||
if (state != SHI_STATE_READY_TO_RECV)
|
||||
/*
|
||||
* Mark not ready to prevent the other
|
||||
* transaction immediately
|
||||
*/
|
||||
NPCX_OBUF(0) = EC_SPI_NOT_READY;
|
||||
CPRINTF("CSH-");
|
||||
/*
|
||||
* If the buffer is still used by the host command.
|
||||
* Change tx buffer to NOT_READY
|
||||
*/
|
||||
if (state == SHI_STATE_PROCESSING) {
|
||||
/*
|
||||
* Mark state to NOT_READY for waiting host executes
|
||||
* response function
|
||||
*/
|
||||
state = SHI_STATE_NOT_READY;
|
||||
CPRINTF("WAIT-");
|
||||
return;
|
||||
}
|
||||
/* reset SHI and prepare to next transaction again */
|
||||
shi_reset_prepare();
|
||||
CPRINTF("END\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Indicate input/output buffer pointer reaches the half buffer size.
|
||||
* Transaction is processing.
|
||||
*/
|
||||
if (IS_BIT_SET(stat_reg, NPCX_EVSTAT_IBHF)) {
|
||||
if (state == SHI_STATE_RECEIVING) {
|
||||
/* Read data from input to msg buffer */
|
||||
shi_read_half_inbuf();
|
||||
return request_handler();
|
||||
} else if (state == SHI_STATE_SENDING) {
|
||||
/* Write data from bottom address again */
|
||||
shi_params.tx_buf = SHI_OBUF_START_ADDR;
|
||||
/* Write data from msg buffer to output buffer */
|
||||
return shi_write_half_outbuf();
|
||||
} else if (state == SHI_STATE_PROCESSING)
|
||||
/* Wait for host handles request */
|
||||
return;
|
||||
else
|
||||
/* Unexpected status */
|
||||
return shi_error(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Indicate input/output buffer pointer reaches the full buffer size.
|
||||
* Transaction is processing.
|
||||
*/
|
||||
if (IS_BIT_SET(stat_reg, NPCX_EVSTAT_IBF)) {
|
||||
if (state == SHI_STATE_RECEIVING) {
|
||||
/* read data from input to msg buffer */
|
||||
shi_read_half_inbuf();
|
||||
/* Read to bottom address again */
|
||||
shi_params.rx_buf = SHI_IBUF_START_ADDR;
|
||||
return request_handler();
|
||||
} else if (state == SHI_STATE_SENDING)
|
||||
/* Write data from msg buffer to output buffer */
|
||||
return shi_write_half_outbuf();
|
||||
else if (state == SHI_STATE_PROCESSING)
|
||||
/* Wait for host handles request */
|
||||
return;
|
||||
else
|
||||
/* Unexpected status */
|
||||
return shi_error(1);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The interrupt priority for SHI interrupt should be higher than
|
||||
* GPIO. Then we could receive CS-deasserted event even in CS-asserted ISR.
|
||||
*/
|
||||
DECLARE_IRQ(NPCX_IRQ_SHI, shi_int_handler, 0);
|
||||
|
||||
/* Handle an CS assert event on the SHI_CS_L pin */
|
||||
void shi_cs_event(enum gpio_signal signal)
|
||||
{
|
||||
/* If not enabled, ignore glitches on SHI_CS_L */
|
||||
if (state == SHI_STATE_DISABLED)
|
||||
return;
|
||||
|
||||
/*
|
||||
* TODO (ML): Glitches on SHI_CS_L will cause SHI doesn`t generate
|
||||
* 'End of data for read/write transaction interrupt' and IBUFSTAT will
|
||||
* keep previous value without clocks. (Workaround) Need to reset it
|
||||
* manually in CS assert ISR.
|
||||
*/
|
||||
if (NPCX_IBUFSTAT == shi_params.pre_ibufstat) {
|
||||
if (!shi_check_inbuf_valid()) {
|
||||
CPRINTS("ERR-GTH");
|
||||
shi_reset_prepare();
|
||||
CPRINTS("END\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Chip select is low = asserted */
|
||||
if (state != SHI_STATE_READY_TO_RECV) {
|
||||
/*
|
||||
* AP started a transaction but we weren't ready for it.
|
||||
* Tell AP we weren't ready, and ignore the received data.
|
||||
* The driver should change status later when complete handling
|
||||
* response from host
|
||||
*/
|
||||
NPCX_OBUF(0) = EC_SPI_NOT_READY;
|
||||
CPRINTS("CSL-NRDY");
|
||||
/*
|
||||
* If status still is error, reset SHI Bus and
|
||||
* abort this transaction.
|
||||
*/
|
||||
if (state == SHI_STATE_ERROR) {
|
||||
CPRINTS("ERR-");
|
||||
shi_reset_prepare();
|
||||
CPRINTS("END\n");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* We're now inside a transaction */
|
||||
state = SHI_STATE_RECEIVING;
|
||||
CPRINTF("CSL-RV-");
|
||||
|
||||
/* Setup deadline time for receiving */
|
||||
shi_params.rx_deadline = get_time();
|
||||
shi_params.rx_deadline.val += SHI_CMD_RX_TIMEOUT_US;
|
||||
|
||||
/* Read first three bytes to parse which protocol is receiving */
|
||||
shi_parse_header();
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Hook functions for chipset and initialization */
|
||||
|
||||
/* Reset SHI bus and prepare next transaction */
|
||||
static void shi_reset_prepare(void)
|
||||
{
|
||||
uint16_t i;
|
||||
state = SHI_STATE_NOT_READY;
|
||||
|
||||
/* Initialize parameters of next transaction */
|
||||
shi_params.rx_msg = in_msg;
|
||||
shi_params.tx_msg = out_msg;
|
||||
shi_params.rx_buf = SHI_IBUF_START_ADDR;
|
||||
shi_params.tx_buf = SHI_OBUF_HALF_ADDR;
|
||||
shi_params.sz_received = 0;
|
||||
shi_params.sz_sending = 0;
|
||||
shi_params.sz_request = 0;
|
||||
shi_params.sz_response = 0;
|
||||
/* Record last IBUFSTAT for glitch case */
|
||||
shi_params.pre_ibufstat = NPCX_IBUFSTAT;
|
||||
|
||||
/*
|
||||
* Fill output buffer to indicate we`re
|
||||
* ready to receive next transaction
|
||||
*/
|
||||
for (i = 1; i < SHI_OBUF_FULL_SIZE; i++)
|
||||
NPCX_OBUF(i) = EC_SPI_RECEIVING;
|
||||
NPCX_OBUF(0) = EC_SPI_OLD_READY;
|
||||
|
||||
/* Enable SHI & WEN functionality */
|
||||
NPCX_SHICFG1 = 0x85;
|
||||
|
||||
/* Ready to receive */
|
||||
state = SHI_STATE_READY_TO_RECV;
|
||||
CPRINTF("RDY-");
|
||||
}
|
||||
DECLARE_HOOK(HOOK_CHIPSET_RESUME, shi_reset_prepare, HOOK_PRIO_DEFAULT);
|
||||
|
||||
/* Disable SHI bus */
|
||||
static void shi_disable(void)
|
||||
{
|
||||
state = SHI_STATE_DISABLED;
|
||||
|
||||
/* Disable pullup and interrupts on SHI_CS_L */
|
||||
gpio_set_flags(GPIO_SHI_CS_L, GPIO_INPUT);
|
||||
|
||||
/* Set SPI pins to inputs so we don't leak power when AP is off */
|
||||
gpio_config_module(MODULE_SPI, 0);
|
||||
}
|
||||
DECLARE_HOOK(HOOK_CHIPSET_SUSPEND, shi_disable, HOOK_PRIO_DEFAULT);
|
||||
|
||||
static void shi_init(void)
|
||||
{
|
||||
/* Power on SHI module first */
|
||||
CLEAR_BIT(NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_5), NPCX_PWDWN_CTL5_SHI_PD);
|
||||
/*
|
||||
* Mux SHI related pins
|
||||
* SHI_SDI SHI_SDO SHI_CS# SHI_SCLK are selected to device pins
|
||||
*/
|
||||
SET_BIT(NPCX_DEVALT(ALT_GROUP_C), NPCX_DEVALTC_SHI_SL);
|
||||
|
||||
/*
|
||||
* SHICFG1 (SHI Configuration 1) setting
|
||||
* [7] - IWRAP = 1: Wrap input buffer to the first address
|
||||
* [6] - CPOL = 0: Sampling on rising edge and output on falling edge
|
||||
* [5] - DAS = 0: return STATUS reg data after Status command
|
||||
* [4] - AUTOBE = 0: Automatically update the OBES bit in STATUS reg
|
||||
* [3] - AUTIBF = 0: Automatically update the IBFS bit in STATUS reg
|
||||
* [2] - WEN = 0: Enable host write to input buffer
|
||||
* [1] - Reserved 0
|
||||
* [0] - ENABLE = 0: Disable SHI at the beginning
|
||||
*/
|
||||
NPCX_SHICFG1 = 0x80;
|
||||
|
||||
/*
|
||||
* SHICFG2 (SHI Configuration 2) setting
|
||||
* [7] - Reserved 0
|
||||
* [6] - REEVEN = 0: Restart events are not used
|
||||
* [5] - Reserved 0
|
||||
* [4] - REEN = 0: Restart transactions are not used
|
||||
* [3] - SLWU = 0: Seem-less wake-up is enabled by default
|
||||
* [2] - ONESHOT= 0: WEN is cleared at the end of a write transaction
|
||||
* [1] - BUSY = 0: SHI bus is busy 0: idle.
|
||||
* [0] - SIMUL = 1: Turn on simultaneous Read/Write
|
||||
*/
|
||||
NPCX_SHICFG2 = 0x01;
|
||||
|
||||
/*
|
||||
* EVENABLE (Event Enable) setting
|
||||
* [7] - IBOREN = 0: Input buffer overrun interrupt enable
|
||||
* [6] - STSREN = 0: status read interrupt disable
|
||||
* [5] - EOWEN = 0: End-of-Data for Write Transaction Interrupt Enable
|
||||
* [4] - EOREN = 1: End-of-Data for Read Transaction Interrupt Enable
|
||||
* [3] - IBHFEN = 1: Input Buffer Half Full Interrupt Enable
|
||||
* [2] - IBFEN = 1: Input Buffer Full Interrupt Enable
|
||||
* [1] - OBHEEN = 0: Output Buffer Half Empty Interrupt Enable
|
||||
* [0] - OBEEN = 0: Output Buffer Empty Interrupt Enable
|
||||
*/
|
||||
NPCX_EVENABLE = 0x1C;
|
||||
|
||||
/* Clear SHI events status register */
|
||||
NPCX_EVSTAT = 0XFF;
|
||||
|
||||
/* Enable SHI_CS_L interrupt */
|
||||
gpio_enable_interrupt(GPIO_SHI_CS_L);
|
||||
|
||||
/* If chipset is already on, prepare for transactions */
|
||||
#if !(DEBUG_SHI)
|
||||
if (chipset_in_state(CHIPSET_STATE_ON))
|
||||
#endif
|
||||
shi_reset_prepare();
|
||||
}
|
||||
DECLARE_HOOK(HOOK_INIT, shi_init, HOOK_PRIO_DEFAULT);
|
||||
|
||||
/**
|
||||
* Get protocol information
|
||||
*/
|
||||
static int shi_get_protocol_info(struct host_cmd_handler_args *args)
|
||||
{
|
||||
struct ec_response_get_protocol_info *r = args->response;
|
||||
|
||||
memset(r, 0, sizeof(*r));
|
||||
r->protocol_versions = (1 << 2) | (1 << 3);
|
||||
r->max_request_packet_size = SHI_MAX_REQUEST_SIZE;
|
||||
r->max_response_packet_size = SHI_MAX_RESPONSE_SIZE;
|
||||
r->flags = EC_PROTOCOL_INFO_IN_PROGRESS_SUPPORTED;
|
||||
|
||||
args->response_size = sizeof(*r);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_HOST_COMMAND(EC_CMD_GET_PROTOCOL_INFO, shi_get_protocol_info,
|
||||
EC_VER_MASK(0));
|
||||
21
chip/npcx/shi_chip.h
Normal file
21
chip/npcx/shi_chip.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
/* NPCX-specific SHI module for Chrome EC */
|
||||
|
||||
#ifndef SHI_CHIP_H_
|
||||
#define SHI_CHIP_H_
|
||||
|
||||
#ifdef CONFIG_SHI
|
||||
/**
|
||||
* Called when the NSS level changes, signalling the start of a SHI
|
||||
* transaction.
|
||||
*
|
||||
* @param signal GPIO signal that changed
|
||||
*/
|
||||
void shi_cs_event(enum gpio_signal signal);
|
||||
#endif
|
||||
|
||||
#endif /* SHI_CHIP_H_ */
|
||||
@@ -18,17 +18,12 @@
|
||||
#include "util.h"
|
||||
#include "hwtimer_chip.h"
|
||||
#include "system_chip.h"
|
||||
#include "rom_chip.h"
|
||||
|
||||
/* Flags for BBRM_DATA_INDEX_WAKE */
|
||||
#define HIBERNATE_WAKE_MTC (1 << 0) /* MTC alarm */
|
||||
#define HIBERNATE_WAKE_PIN (1 << 1) /* Wake pin */
|
||||
|
||||
/* Super-IO index and register definitions */
|
||||
#define SIO_OFFSET 0x4E
|
||||
#define INDEX_SID 0x20
|
||||
#define INDEX_CHPREV 0x24
|
||||
#define INDEX_SRID 0x27
|
||||
|
||||
/* equivalent to 250us according to 48MHz core clock */
|
||||
#define MTC_TTC_LOAD_DELAY 1500
|
||||
#define MTC_ALARM_MASK ((1 << 25) - 1)
|
||||
@@ -38,109 +33,16 @@
|
||||
/* ROM address of chip revision */
|
||||
#define CHIP_REV_ADDR 0x00007FFC
|
||||
|
||||
/* Console output macros */
|
||||
#define CPUTS(outstr) cputs(CC_SYSTEM, outstr)
|
||||
#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
|
||||
|
||||
/* Begin address for the .lpram section; defined in linker script */
|
||||
uintptr_t __lpram_fw_start = CONFIG_LPRAM_BASE;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Internal functions */
|
||||
|
||||
/* Super-IO read/write function */
|
||||
void system_sib_write_reg(uint8_t io_offset, uint8_t index_value,
|
||||
uint8_t io_data)
|
||||
{
|
||||
/* Disable interrupts */
|
||||
interrupt_disable();
|
||||
|
||||
/* Lock host CFG module */
|
||||
SET_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
|
||||
/* Enable Core-to-Host Modules Access */
|
||||
SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
|
||||
/* Enable Core access to CFG module */
|
||||
SET_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
|
||||
/* Verify Core read/write to host modules is not in progress */
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD))
|
||||
;
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
|
||||
;
|
||||
|
||||
/* Specify the io_offset A0 = 0. the index register is accessed */
|
||||
NPCX_IHIOA = io_offset;
|
||||
/* Write the data. This starts the write access to the host module */
|
||||
NPCX_IHD = index_value;
|
||||
/* Wait while Core write operation is in progress */
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
|
||||
;
|
||||
|
||||
/* Specify the io_offset A0 = 1. the data register is accessed */
|
||||
NPCX_IHIOA = io_offset+1;
|
||||
/* Write the data. This starts the write access to the host module */
|
||||
NPCX_IHD = io_data;
|
||||
/* Wait while Core write operation is in progress */
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
|
||||
;
|
||||
|
||||
/* Disable Core access to CFG module */
|
||||
CLEAR_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
|
||||
/* Disable Core-to-Host Modules Access */
|
||||
CLEAR_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
|
||||
/* unlock host CFG module */
|
||||
CLEAR_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
|
||||
|
||||
/* Enable interrupts */
|
||||
interrupt_enable();
|
||||
}
|
||||
|
||||
uint8_t system_sib_read_reg(uint8_t io_offset, uint8_t index_value)
|
||||
{
|
||||
uint8_t data_value;
|
||||
|
||||
/* Disable interrupts */
|
||||
interrupt_disable();
|
||||
|
||||
/* Lock host CFG module */
|
||||
SET_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
|
||||
/* Enable Core-to-Host Modules Access */
|
||||
SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
|
||||
/* Enable Core access to CFG module */
|
||||
SET_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
|
||||
/* Verify Core read/write to host modules is not in progress */
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD))
|
||||
;
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
|
||||
;
|
||||
|
||||
|
||||
/* Specify the io_offset A0 = 0. the index register is accessed */
|
||||
NPCX_IHIOA = io_offset;
|
||||
/* Write the data. This starts the write access to the host module */
|
||||
NPCX_IHD = index_value;
|
||||
/* Wait while Core write operation is in progress */
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSWR))
|
||||
;
|
||||
|
||||
/* Specify the io_offset A0 = 1. the data register is accessed */
|
||||
NPCX_IHIOA = io_offset+1;
|
||||
/* Start a Core read from host module */
|
||||
SET_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD);
|
||||
/* Wait while Core read operation is in progress */
|
||||
while (IS_BIT_SET(NPCX_SIBCTRL, NPCX_SIBCTRL_CSRD))
|
||||
;
|
||||
/* Read the data */
|
||||
data_value = NPCX_IHD;
|
||||
|
||||
/* Disable Core access to CFG module */
|
||||
CLEAR_BIT(NPCX_CRSMAE, NPCX_CRSMAE_CFGAE);
|
||||
/* Disable Core-to-Host Modules Access */
|
||||
CLEAR_BIT(NPCX_SIBCTRL, NPCX_SIBCTRL_CSAE);
|
||||
/* unlock host CFG module */
|
||||
CLEAR_BIT(NPCX_LKSIOHA, NPCX_LKSIOHA_LKCFG);
|
||||
|
||||
/* Enable interrupts */
|
||||
interrupt_enable();
|
||||
|
||||
return data_value;
|
||||
}
|
||||
|
||||
void system_watchdog_reset(void)
|
||||
{
|
||||
/* Unlock & stop watchdog registers */
|
||||
@@ -277,17 +179,11 @@ void system_check_reset_cause(void)
|
||||
}
|
||||
|
||||
/* Watchdog Reset */
|
||||
#ifndef CHIP_NPCX5M5G
|
||||
if (IS_BIT_SET(NPCX_T0CSR, NPCX_T0CSR_WDRST_STS)) {
|
||||
flags |= RESET_FLAG_WATCHDOG;
|
||||
/* Clear watchdog reset status initially*/
|
||||
SET_BIT(NPCX_T0CSR, NPCX_T0CSR_WDRST_STS);
|
||||
}
|
||||
#else
|
||||
/* Workaround method to check watchdog reset */
|
||||
if (NPCX_BBRAM(BBRM_DATA_INDEX_RAMLOG) & 0x04)
|
||||
flags |= RESET_FLAG_WATCHDOG;
|
||||
#endif
|
||||
|
||||
if ((hib_wake_flags & HIBERNATE_WAKE_PIN))
|
||||
flags |= RESET_FLAG_WAKE_PIN;
|
||||
@@ -356,12 +252,12 @@ __enter_hibernate_in_lpram(void)
|
||||
{
|
||||
|
||||
/* Disable Code RAM first */
|
||||
SET_BIT(NPCX_PWDWN_CTL(5), NPCX_PWDWN_CTL5_MRFSH_DIS);
|
||||
SET_BIT(NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_5), NPCX_PWDWN_CTL5_MRFSH_DIS);
|
||||
SET_BIT(NPCX_DISIDL_CTL, NPCX_DISIDL_CTL_RAM_DID);
|
||||
|
||||
while (1) {
|
||||
/* Set deep idle - instant wake-up mode*/
|
||||
NPCX_PMCSR = 0x7;
|
||||
/* Set deep idle mode*/
|
||||
NPCX_PMCSR = 0x6;
|
||||
/* Enter deep idle, wake-up by GPIOxx or RTC */
|
||||
asm("wfi");
|
||||
|
||||
@@ -424,11 +320,11 @@ void __enter_hibernate(uint32_t seconds, uint32_t microseconds)
|
||||
interrupt_disable();
|
||||
|
||||
/* ITIM event module disable */
|
||||
CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITIM16_ITEN);
|
||||
CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN);
|
||||
/* ITIM time module disable */
|
||||
CLEAR_BIT(NPCX_ITCTS(ITIM_TIME_NO), NPCX_ITIM16_ITEN);
|
||||
CLEAR_BIT(NPCX_ITCTS(ITIM32), NPCX_ITCTS_ITEN);
|
||||
/* ITIM watchdog warn module disable */
|
||||
CLEAR_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITIM16_ITEN);
|
||||
CLEAR_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_ITEN);
|
||||
|
||||
/*
|
||||
* Set RTC interrupt in time to wake up before
|
||||
@@ -545,12 +441,21 @@ void system_pre_init(void)
|
||||
*/
|
||||
|
||||
/* Power-down the modules we don't need */
|
||||
NPCX_PWDWN_CTL(0) = 0xF9; /* Skip SDP_PD FIU_PD */
|
||||
NPCX_PWDWN_CTL(1) = 0xFF;
|
||||
NPCX_PWDWN_CTL(2) = 0x8F;
|
||||
NPCX_PWDWN_CTL(3) = 0xF4; /* Skip ITIM2/1_PD */
|
||||
NPCX_PWDWN_CTL(4) = 0xF8;
|
||||
NPCX_PWDWN_CTL(5) = 0x85; /* Skip ITIM5_PD */
|
||||
NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_1) = 0xF9; /* Skip SDP_PD FIU_PD */
|
||||
NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_2) = 0xFF;
|
||||
NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_3) = 0x0F; /* Skip GDMA */
|
||||
NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_4) = 0xF4; /* Skip ITIM2/1_PD */
|
||||
NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_5) = 0xF8;
|
||||
NPCX_PWDWN_CTL(NPCX_PMC_PWDWN_6) = 0x85; /* Skip ITIM5_PD */
|
||||
|
||||
/* Power down the modules used internally */
|
||||
NPCX_INTERNAL_CTRL1 = 0x03;
|
||||
NPCX_INTERNAL_CTRL2 = 0x03;
|
||||
NPCX_INTERNAL_CTRL3 = 0x03;
|
||||
|
||||
/* Enable low-power regulator */
|
||||
CLEAR_BIT(NPCX_LFCGCALCNT, NPCX_LFCGCALCNT_LPREG_CTL_EN);
|
||||
SET_BIT(NPCX_LFCGCALCNT, NPCX_LFCGCALCNT_LPREG_CTL_EN);
|
||||
|
||||
/*
|
||||
* Configure LPRAM in the MPU as a regular memory
|
||||
@@ -637,12 +542,9 @@ const char *system_get_chip_name(void)
|
||||
const char *system_get_chip_revision(void)
|
||||
{
|
||||
static char rev[4];
|
||||
#ifndef CHIP_NPCX5M5G
|
||||
uint8_t rev_num = system_sib_read_reg(SIO_OFFSET, INDEX_CHPREV);
|
||||
#else
|
||||
/* Read ROM data for chip revision directly */
|
||||
uint8_t rev_num = *((uint8_t *)CHIP_REV_ADDR);
|
||||
#endif
|
||||
|
||||
*(rev) = 'A';
|
||||
*(rev + 1) = '.';
|
||||
*(rev + 2) = system_to_hex((rev_num & 0xF0) >> 4);
|
||||
@@ -789,58 +691,53 @@ DECLARE_HOST_COMMAND(EC_CMD_RTC_SET_VALUE,
|
||||
system_rtc_set_value,
|
||||
EC_VER_MASK(0));
|
||||
|
||||
/* For LPC host register initial via SIB module */
|
||||
void system_lpc_host_register_init(void){
|
||||
/* Setting PMC2 */
|
||||
/* LDN register = 0x12(PMC2) */
|
||||
system_sib_write_reg(SIO_OFFSET, 0x07, 0x12);
|
||||
/* CMD port is 0x200 */
|
||||
system_sib_write_reg(SIO_OFFSET, 0x60, 0x02);
|
||||
system_sib_write_reg(SIO_OFFSET, 0x61, 0x00);
|
||||
/* Data port is 0x204 */
|
||||
system_sib_write_reg(SIO_OFFSET, 0x62, 0x02);
|
||||
system_sib_write_reg(SIO_OFFSET, 0x63, 0x04);
|
||||
/* enable PMC2 */
|
||||
system_sib_write_reg(SIO_OFFSET, 0x30, 0x01);
|
||||
|
||||
/* Setting SHM */
|
||||
/* LDN register = 0x0F(SHM) */
|
||||
system_sib_write_reg(SIO_OFFSET, 0x07, 0x0F);
|
||||
/* WIN1&2 mapping to IO */
|
||||
system_sib_write_reg(SIO_OFFSET, 0xF1,
|
||||
system_sib_read_reg(SIO_OFFSET, 0xF1) | 0x30);
|
||||
/* Host Command on the IO:0x0800 */
|
||||
system_sib_write_reg(SIO_OFFSET, 0xF7, 0x00);
|
||||
system_sib_write_reg(SIO_OFFSET, 0xF6, 0x00);
|
||||
system_sib_write_reg(SIO_OFFSET, 0xF5, 0x08);
|
||||
system_sib_write_reg(SIO_OFFSET, 0xF4, 0x00);
|
||||
/* WIN1 as Host Command on the IO:0x0800 */
|
||||
system_sib_write_reg(SIO_OFFSET, 0xFB, 0x00);
|
||||
system_sib_write_reg(SIO_OFFSET, 0xFA, 0x00);
|
||||
/* WIN2 as MEMMAP on the IO:0x900 */
|
||||
system_sib_write_reg(SIO_OFFSET, 0xF9, 0x09);
|
||||
system_sib_write_reg(SIO_OFFSET, 0xF8, 0x00);
|
||||
/* enable SHM */
|
||||
system_sib_write_reg(SIO_OFFSET, 0x30, 0x01);
|
||||
}
|
||||
#ifdef CONFIG_CODERAM_ARCH
|
||||
uint32_t system_get_lfw_address(void)
|
||||
void system_jump_to_booter(void)
|
||||
{
|
||||
/* Little FW located on top of flash - 4K */
|
||||
uint32_t jump_addr = (CONFIG_FLASH_BASE + CONFIG_SPI_FLASH_SIZE
|
||||
- CONFIG_LFW_OFFSET + 1);
|
||||
enum API_RETURN_STATUS_T status;
|
||||
static uint32_t flash_offset;
|
||||
static uint32_t flash_used;
|
||||
static uint32_t addr_entry;
|
||||
|
||||
/* RO region FW */
|
||||
if (IS_BIT_SET(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION)) {
|
||||
flash_offset = CONFIG_RO_MEM_OFF;
|
||||
flash_used = CONFIG_RO_SIZE;
|
||||
} else { /* RW region FW */
|
||||
flash_offset = CONFIG_RW_MEM_OFF;
|
||||
flash_used = CONFIG_RW_SIZE;
|
||||
}
|
||||
|
||||
/* Make sure the reset vector is inside the destination image */
|
||||
addr_entry = *(uintptr_t *)(flash_offset + CONFIG_FLASH_BASE + 4);
|
||||
|
||||
download_from_flash(
|
||||
flash_offset, /* The offset of the data in spi flash */
|
||||
CONFIG_CDRAM_BASE, /* The address of the downloaded data */
|
||||
flash_used, /* Number of bytes to download */
|
||||
SIGN_NO_CHECK, /* Need CRC check or not */
|
||||
addr_entry, /* jump to this address after download */
|
||||
&status /* Status fo download */
|
||||
);
|
||||
}
|
||||
|
||||
uint32_t system_get_lfw_address()
|
||||
{
|
||||
/*
|
||||
* In A3 version, we don't use little FW anymore
|
||||
* We provide the alternative function in ROM
|
||||
*/
|
||||
uint32_t jump_addr = (uint32_t)system_jump_to_booter;
|
||||
return jump_addr;
|
||||
}
|
||||
|
||||
void system_set_image_copy(enum system_image_copy_t copy)
|
||||
{
|
||||
/* Jump to RO region -- set flag */
|
||||
if (copy == SYSTEM_IMAGE_RO)
|
||||
SET_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION);
|
||||
else /* Jump to RW region -- clear flag */
|
||||
/* Jump to RW region -- clear flag */
|
||||
if (copy == SYSTEM_IMAGE_RW)
|
||||
CLEAR_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION);
|
||||
|
||||
else /* Jump to RO region -- set flag */
|
||||
SET_BIT(NPCX_FWCTRL, NPCX_FWCTRL_RO_REGION);
|
||||
}
|
||||
|
||||
enum system_image_copy_t system_get_shrspi_image_copy(void)
|
||||
|
||||
@@ -18,8 +18,6 @@ enum bbram_data_index {
|
||||
BBRM_DATA_INDEX_RAMLOG = 32, /* RAM log for Booter */
|
||||
};
|
||||
|
||||
/* Init lpc register through SIB */
|
||||
void system_lpc_host_register_init(void);
|
||||
/* Issue a watchdog reset*/
|
||||
void system_watchdog_reset(void);
|
||||
/* Check reset cause and return reset flags */
|
||||
|
||||
@@ -26,13 +26,11 @@ int uart_init_done(void)
|
||||
|
||||
void uart_tx_start(void)
|
||||
{
|
||||
if (IS_BIT_SET(NPCX_WKEN(1, 1), 0)) {
|
||||
/* disable MIWU*/
|
||||
CLEAR_BIT(NPCX_WKEN(1, 1), 0);
|
||||
/* go back to original setting */
|
||||
task_enable_irq(NPCX_IRQ_WKINTB_1);
|
||||
/* Go back CR_SIN*/
|
||||
SET_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL);
|
||||
if (uart_is_enable_wakeup()) {
|
||||
/* disable MIWU */
|
||||
uart_enable_wakeup(0);
|
||||
/* Set pin-mask for UART */
|
||||
npcx_gpio2uart();
|
||||
/* enable uart again from MIWU mode */
|
||||
task_enable_irq(NPCX_IRQ_UART);
|
||||
}
|
||||
@@ -146,9 +144,16 @@ static void uart_config(void)
|
||||
{
|
||||
uint32_t div, opt_dev, min_deviation, clk, calc_baudrate, deviation;
|
||||
uint8_t prescalar, opt_prescalar, i;
|
||||
/* Enable the port */
|
||||
|
||||
/* Configure pins from GPIOs to CR_UART */
|
||||
gpio_config_module(MODULE_UART, 1);
|
||||
/* Enable MIWU IRQ of UART*/
|
||||
#if NPCX_UART_MODULE2
|
||||
task_enable_irq(NPCX_IRQ_WKINTG_1);
|
||||
#else
|
||||
task_enable_irq(NPCX_IRQ_WKINTB_1);
|
||||
|
||||
#endif
|
||||
|
||||
/* Calculated UART baudrate , clock source from APB2 */
|
||||
opt_prescalar = opt_dev = 0;
|
||||
@@ -193,8 +198,7 @@ void uart_init(void)
|
||||
clock_enable_peripheral(CGC_OFFSET_UART, mask, CGC_MODE_ALL);
|
||||
|
||||
/* Set pin-mask for UART */
|
||||
SET_BIT(NPCX_DEVALT(0x0A), NPCX_DEVALTA_UART_SL);
|
||||
gpio_config_module(MODULE_UART, 1);
|
||||
npcx_gpio2uart();
|
||||
|
||||
/* Configure UARTs (identically) */
|
||||
uart_config();
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
void watchdog_init_warning_timer(void)
|
||||
{
|
||||
/* init watchdog timer first */
|
||||
init_hw_timer(ITIM_WDG_NO, ITIM16_SOURCE_CLOCK_32K);
|
||||
init_hw_timer(ITIM_WDG_NO, ITIM_SOURCE_CLOCK_32K);
|
||||
|
||||
/*
|
||||
* prescaler to TIMER_TICK
|
||||
@@ -40,7 +40,7 @@ void watchdog_init_warning_timer(void)
|
||||
/* ITIM count down : event expired*/
|
||||
NPCX_ITCNT16(ITIM_WDG_NO) = CONFIG_WATCHDOG_PERIOD_MS-1;
|
||||
/* Event module enable */
|
||||
SET_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITIM16_ITEN);
|
||||
SET_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_ITEN);
|
||||
/* Enable interrupt of ITIM */
|
||||
task_enable_irq(ITIM16_INT(ITIM_WDG_NO));
|
||||
}
|
||||
@@ -49,7 +49,7 @@ void __keep watchdog_check(uint32_t excep_lr, uint32_t excep_sp)
|
||||
{
|
||||
int wd_cnt;
|
||||
/* Clear timeout status for event */
|
||||
SET_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITIM16_TO_STS);
|
||||
SET_BIT(NPCX_ITCTS(ITIM_WDG_NO), NPCX_ITCTS_TO_STS);
|
||||
|
||||
/* Read watchdog counter from TWMWD */
|
||||
wd_cnt = NPCX_TWMWD;
|
||||
|
||||
@@ -14,7 +14,13 @@ MEMORY
|
||||
SECTIONS
|
||||
{
|
||||
. = ALIGN(CONFIG_FLASH_BANK_SIZE);
|
||||
#if defined(NPCX_RO_HEADER)
|
||||
/* Replace *_MEM_OFF with *_STORAGE_OFF to indicate flat file contains header
|
||||
* or some struture which doesn't belong to FW */
|
||||
.image.RO : AT(CONFIG_FLASH_BASE + CONFIG_RO_STORAGE_OFF) {
|
||||
#else
|
||||
.image.RO : AT(CONFIG_FLASH_BASE + CONFIG_RO_MEM_OFF) {
|
||||
#endif
|
||||
*(.image.RO)
|
||||
} > FLASH =0xff
|
||||
. = ALIGN(CONFIG_FLASH_BANK_SIZE);
|
||||
|
||||
@@ -20,7 +20,12 @@
|
||||
* For address containing CONFIG_FLASH_BASE (symbols in *.RO.lds.S and
|
||||
* variable), this computes the offset to the start of the image on flash.
|
||||
*/
|
||||
|
||||
#ifdef NPCX_RO_HEADER
|
||||
#define RELATIVE_RO(addr) ((addr) - CONFIG_CDRAM_BASE)
|
||||
#else
|
||||
#define RELATIVE_RO(addr) ((addr) - CONFIG_FLASH_BASE - CONFIG_RO_MEM_OFF)
|
||||
#endif
|
||||
|
||||
struct fmap_header {
|
||||
char fmap_signature[FMAP_SIGNATURE_SIZE];
|
||||
|
||||
@@ -18,6 +18,15 @@ OUTPUT_ARCH(BFD_ARCH)
|
||||
ENTRY(reset)
|
||||
MEMORY
|
||||
{
|
||||
#if defined(SECTION_IS_RO) && defined(NPCX_RO_HEADER)
|
||||
/*
|
||||
* Header structure used by npcx booter in RO region.
|
||||
* Please notice the location of header must be in front of FW
|
||||
* which needs copy. But header itself won't be copied to code ram
|
||||
* by booter.
|
||||
*/
|
||||
FLASH_HDR (rx) : ORIGIN = FW_OFF(RO_HDR), LENGTH = FW_SIZE(RO_HDR)
|
||||
#endif
|
||||
FLASH (rx) : ORIGIN = FW_OFF(SECTION), LENGTH = FW_SIZE(SECTION)
|
||||
IRAM (rw) : ORIGIN = CONFIG_RAM_BASE, LENGTH = CONFIG_RAM_SIZE
|
||||
#ifdef CONFIG_CODERAM_ARCH
|
||||
@@ -45,6 +54,11 @@ MEMORY
|
||||
}
|
||||
SECTIONS
|
||||
{
|
||||
#if defined(SECTION_IS_RO) && defined(NPCX_RO_HEADER)
|
||||
.header : {
|
||||
KEEP(*(.header))
|
||||
} > FLASH_HDR
|
||||
#endif
|
||||
.text : {
|
||||
OUTDIR/core/CORE/init.o (.text.vecttable)
|
||||
. = ALIGN(4);
|
||||
@@ -66,7 +80,7 @@ SECTIONS
|
||||
/* Entering deep idle FW for better power consumption */
|
||||
KEEP(*(.lowpower_ram))
|
||||
__flash_lpfw_end = .;
|
||||
} > CDRAM AT > FLASH
|
||||
} > CDRAM AT > FLASH
|
||||
#else
|
||||
#ifdef COMPILE_FOR_RAM
|
||||
} > IRAM
|
||||
@@ -182,7 +196,7 @@ SECTIONS
|
||||
#endif
|
||||
. = ALIGN(4);
|
||||
#ifdef CONFIG_CODERAM_ARCH
|
||||
} > CDRAM AT > FLASH
|
||||
} > CDRAM AT > FLASH
|
||||
#else
|
||||
#ifdef COMPILE_FOR_RAM
|
||||
} > IRAM
|
||||
@@ -219,7 +233,6 @@ SECTIONS
|
||||
.data : {
|
||||
#else
|
||||
#ifdef CONFIG_CODERAM_ARCH
|
||||
__data_start = . ;
|
||||
.data : AT(LOADADDR(.rodata) + SIZEOF(.rodata)) {
|
||||
#else
|
||||
.data : AT(ADDR(.rodata) + SIZEOF(.rodata)) {
|
||||
|
||||
@@ -82,6 +82,7 @@ BOARDS_STM32_DFU=(
|
||||
|
||||
BOARDS_NPCX=(
|
||||
npcx_evb
|
||||
npcx_evb_arm
|
||||
)
|
||||
|
||||
BOARDS_MEC1322=(
|
||||
@@ -389,6 +390,7 @@ function flash_lm4() {
|
||||
|
||||
function flash_npcx() {
|
||||
OCD_PATH="${EC_DIR}/chip/npcx/openocd"
|
||||
IMG_PATH="${EC_DIR}/build/${BOARD}"
|
||||
setup_openocd
|
||||
|
||||
dut_control jtag_buf_on_flex_en:on
|
||||
@@ -396,12 +398,12 @@ function flash_npcx() {
|
||||
|
||||
if [ "${FLAGS_ro}" = ${FLAGS_TRUE} ] ; then
|
||||
# Program RO region only
|
||||
OCD_CMDS="init; flash_npcx_ro ${FLAGS_offset}; shutdown;"
|
||||
OCD_CMDS="init; flash_npcx_ro ${IMG_PATH} ${FLAGS_offset}; shutdown;"
|
||||
sudo openocd -s "${OCD_PATH}" -f "${OCD_CFG}" -c "${OCD_CMDS}" || \
|
||||
die "Failed to program ${IMG}"
|
||||
else
|
||||
# Program all EC regions
|
||||
OCD_CMDS="init; flash_npcx_evb ${FLAGS_offset}; shutdown;"
|
||||
OCD_CMDS="init; flash_npcx_all ${IMG_PATH} ${FLAGS_offset}; shutdown;"
|
||||
sudo openocd -s "${OCD_PATH}" -f "${OCD_CFG}" -c "${OCD_CMDS}" || \
|
||||
die "Failed to program ${IMG}"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user