summaryrefslogtreecommitdiff
path: root/chip/stm32/i2c_ite_flash_support.c
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2021-11-04 12:11:58 -0600
committerCommit Bot <commit-bot@chromium.org>2021-11-05 04:22:34 +0000
commit252457d4b21f46889eebad61d4c0a65331919cec (patch)
tree01856c4d31d710b20e85a74c8d7b5836e35c3b98 /chip/stm32/i2c_ite_flash_support.c
parent08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff)
downloadchrome-ec-factory-guybrush-14600.B-ish.tar.gz
In the interest of making long-term branch maintenance incur as little technical debt on us as possible, we should not maintain any files on the branch we are not actually using. This has the added effect of making it extremely clear when merging CLs from the main branch when changes have the possibility to affect us. The follow-on CL adds a convenience script to actually pull updates from the main branch and generate a CL for the update. BUG=b:204206272 BRANCH=ish TEST=make BOARD=arcada_ish && make BOARD=drallion_ish Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'chip/stm32/i2c_ite_flash_support.c')
-rw-r--r--chip/stm32/i2c_ite_flash_support.c356
1 files changed, 0 insertions, 356 deletions
diff --git a/chip/stm32/i2c_ite_flash_support.c b/chip/stm32/i2c_ite_flash_support.c
deleted file mode 100644
index 916a8c364c..0000000000
--- a/chip/stm32/i2c_ite_flash_support.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/* Copyright 2020 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.
- */
-/* STM implementation for flashing ITE-based ECs over i2c */
-
-#include "i2c_ite_flash_support.h"
-#include "i2c.h"
-#include "registers.h"
-#include "time.h"
-
-/*
- * As of 2018-11-27 the default for both is 60 bytes. These larger values allow
- * for reflashing of ITE EC chips over I2C
- * (https://issuetracker.google.com/79684405) in reasonably speedy fashion. If
- * the EC firmware defaults are ever raised significantly, consider removing
- * these overrides.
- *
- * As of 2018-11-27 the actual maximum write size supported by the I2C-over-USB
- * protocol is (1<<12)-1, and the maximum read size supported is
- * (1<<15)-1. However compile time assertions require that these values be
- * powers of 2 after overheads are included. Thus, the write limit set here
- * /should/ be (1<<12)-4 and the read limit should be (1<<15)-6, however those
- * ideal limits are not actually possible because stm32 lacks sufficient
- * spare memory for them. With symmetrical limits, the maximum that currently
- * fits is (1<<11)-4 write limit and (1<<11)-6 read limit, leaving 1404 bytes of
- * RAM available.
- *
- * However even with a sufficiently large write value here, the maximum that
- * actually works as of 2018-12-03 is 255 bytes. Additionally, ITE EC firmware
- * image verification requires exactly 256 byte reads. Thus the only useful
- * powers-of-2-minus-overhead limits to set here are (1<<9)-4 writes and
- * (1<<9)-6 reads, leaving 6012 bytes of RAM available, down from 7356 bytes of
- * RAM available with the default 60 byte limits.
- */
-#if CONFIG_USB_I2C_MAX_WRITE_COUNT != ((1<<9) - 4)
-#error Must set CONFIG_USB_I2C_MAX_WRITE_COUNT to ((1<<9) - 4)
-#endif
-#if CONFIG_USB_I2C_MAX_READ_COUNT != ((1<<9) - 6)
-#error Must set CONFIG_USB_I2C_MAX_WRITE_COUNT to ((1<<9) - 6)
-#endif
-
-/*
- * iteflash requires 256 byte reads for verifying ITE EC firmware. Without this
- * the limit is CONFIG_I2C_CHIP_MAX_TRANSFER_SIZE which is 255 for STM32F0 due
- * to an 8 bit field, per src/platform/ec/include/config.h comment.
- */
-#ifndef CONFIG_I2C_XFER_LARGE_TRANSFER
-#error Must define CONFIG_I2C_XFER_LARGE_TRANSFER
-#endif
-
-#define KHz 1000
-#define MHz (1000 * KHz)
-
-/*
- * These constants are values that one might want to try changing if
- * enable_ite_dfu stops working, or does not work on a new ITE EC chip revision.
- */
-
-#define ITE_DFU_I2C_CMD_ADDR_FLAGS 0x5A
-#define ITE_DFU_I2C_DATA_ADDR_FLAGS 0x35
-
-#define SMCLK_WAVEFORM_PERIOD_HZ (100 * KHz)
-#define SMDAT_WAVEFORM_PERIOD_HZ (200 * KHz)
-
-#define START_DELAY_MS 5
-#define SPECIAL_WAVEFORM_MS 50
-#define PLL_STABLE_MS 10
-
-/*
- * Digital line levels to hold before (PRE_) or after (POST_) sending the
- * special waveforms. 0 for low, 1 for high.
- */
-#define SMCLK_PRE_LEVEL 0
-#define SMDAT_PRE_LEVEL 0
-#define SMCLK_POST_LEVEL 0
-#define SMDAT_POST_LEVEL 0
-
-/* The caller should hold the i2c_lock() for ite_dfu_config.i2c_port. */
-static int ite_i2c_read_register(uint8_t register_offset, uint8_t *output)
-{
- /*
- * Ideally the write and read would be done in one I2C transaction, as
- * is normally done when reading from the same I2C address that the
- * write was sent to. The ITE EC is abnormal in that regard, with its
- * different 7-bit addresses for writes vs reads.
- *
- * i2c_xfer() does not support that. Its I2C_XFER_START and
- * I2C_XFER_STOP flag bits do not cleanly support that scenario, they
- * are for continuing transfers without either of STOP or START
- * in-between.
- *
- * For what it's worth, the iteflash.c FTDI-based implementation of this
- * does the same thing, issuing a STOP between the write and read. This
- * works, even if perhaps it should not.
- */
- int ret;
- /* Tell the ITE EC which register we want to read. */
- ret = i2c_xfer_unlocked(ite_dfu_config.i2c_port,
- ITE_DFU_I2C_CMD_ADDR_FLAGS,
- &register_offset, sizeof(register_offset),
- NULL, 0, I2C_XFER_SINGLE);
- if (ret != EC_SUCCESS)
- return ret;
- /* Read in the 1 byte register value. */
- ret = i2c_xfer_unlocked(ite_dfu_config.i2c_port,
- ITE_DFU_I2C_DATA_ADDR_FLAGS,
- NULL, 0,
- output, sizeof(*output), I2C_XFER_SINGLE);
- return ret;
-}
-
-/* Helper function to read ITE chip ID, for verifying ITE DFU mode. */
-static int cprint_ite_chip_id(void)
-{
- /*
- * Per i2c_read8() implementation, use an array even for single byte
- * reads to ensure alignment for DMA on STM32.
- */
- uint8_t chipid1[1];
- uint8_t chipid2[1];
- uint8_t chipver[1];
-
- int ret;
- int chip_version;
- int flash_kb;
-
- i2c_lock(ite_dfu_config.i2c_port, 1);
-
- /* Read the CHIPID1 register. */
- ret = ite_i2c_read_register(0x00, chipid1);
- if (ret != EC_SUCCESS)
- goto unlock;
-
- /* Read the CHIPID2 register. */
- ret = ite_i2c_read_register(0x01, chipid2);
- if (ret != EC_SUCCESS)
- goto unlock;
-
- /* Read the CHIPVER register. */
- ret = ite_i2c_read_register(0x02, chipver);
-
-unlock:
- i2c_lock(ite_dfu_config.i2c_port, 0);
- if (ret != EC_SUCCESS)
- return ret;
-
- /*
- * Compute chip version and embedded flash size from the CHIPVER value.
- *
- * Chip version is mapping from bit 3-0
- * Flash size is mapping from bit 7-4
- *
- * Chip Version (bits 3-0)
- * 0: AX
- * 1: BX
- * 2: CX
- * 3: DX
- *
- * CX or prior flash size (bits 7-4)
- * 0:128KB
- * 4:192KB
- * 8:256KB
- *
- * DX flash size (bits 7-4)
- * 0:128KB
- * 2:192KB
- * 4:256KB
- * 6:384KB
- * 8:512KB
- */
- chip_version = chipver[0] & 0x07;
- if (chip_version < 0x3) {
- /* Chip version is CX or earlier. */
- switch (chipver[0] >> 4) {
- case 0:
- flash_kb = 128;
- break;
- case 4:
- flash_kb = 192;
- break;
- case 8:
- flash_kb = 256;
- break;
- default:
- flash_kb = -2;
- }
- } else if (chip_version == 0x3) {
- /* Chip version is DX. */
- switch (chipver[0] >> 4) {
- case 0:
- flash_kb = 128;
- break;
- case 2:
- flash_kb = 192;
- break;
- case 4:
- flash_kb = 256;
- break;
- case 6:
- flash_kb = 384;
- break;
- case 8:
- flash_kb = 512;
- break;
- default:
- flash_kb = -3;
- }
- } else {
- /* Unrecognized chip version. */
- flash_kb = -1;
- }
-
- ccprintf("ITE EC info: CHIPID1=0x%02X CHIPID2=0x%02X CHIPVER=0x%02X ",
- chipid1[0], chipid2[0], chipver[0]);
- ccprintf("version=%d flash_bytes=%d\n", chip_version, flash_kb << 10);
-
- /*
- * IT8320_eflash_SMBus_Programming_Guide.pdf says it is an error if
- * CHIPID1 != 0x83.
- */
- if (chipid1[0] != 0x83)
- ret = EC_ERROR_HW_INTERNAL;
-
- return ret;
-}
-
-/* Enable ITE direct firmware update (DFU) mode. */
-static int command_enable_ite_dfu(int argc, char **argv)
-{
- if (argc > 1)
- return EC_ERROR_PARAM_COUNT;
-
- /* Ensure we can perform the dfu operation */
- if (ite_dfu_config.access_allow && !ite_dfu_config.access_allow())
- return EC_ERROR_ACCESS_DENIED;
-
- /* Enable peripheral clocks. */
- STM32_RCC_APB2ENR |=
- STM32_RCC_APB2ENR_TIM16EN | STM32_RCC_APB2ENR_TIM17EN;
-
- /* Reset timer registers which are not otherwise set below. */
- STM32_TIM_CR2(16) = 0x0000;
- STM32_TIM_CR2(17) = 0x0000;
- STM32_TIM_DIER(16) = 0x0000;
- STM32_TIM_DIER(17) = 0x0000;
- STM32_TIM_SR(16) = 0x0000;
- STM32_TIM_SR(17) = 0x0000;
- STM32_TIM_CNT(16) = 0x0000;
- STM32_TIM_CNT(17) = 0x0000;
- STM32_TIM_RCR(16) = 0x0000;
- STM32_TIM_RCR(17) = 0x0000;
- STM32_TIM_DCR(16) = 0x0000;
- STM32_TIM_DCR(17) = 0x0000;
- STM32_TIM_DMAR(16) = 0x0000;
- STM32_TIM_DMAR(17) = 0x0000;
-
- /* Prescale to 1 MHz and use ARR to achieve NNN KHz periods. */
- /* This approach is seen in STM's documentation. */
- STM32_TIM_PSC(16) = (CPU_CLOCK / MHz) - 1;
- STM32_TIM_PSC(17) = (CPU_CLOCK / MHz) - 1;
-
- /* Set the waveform periods based on 1 MHz prescale. */
- STM32_TIM_ARR(16) = (MHz / SMCLK_WAVEFORM_PERIOD_HZ) - 1;
- STM32_TIM_ARR(17) = (MHz / SMDAT_WAVEFORM_PERIOD_HZ) - 1;
-
- /* Set output compare 1 mode to PWM mode 1 and enable preload. */
- STM32_TIM_CCMR1(16) =
- STM32_TIM_CCMR1_OC1M_PWM_MODE_1 | STM32_TIM_CCMR1_OC1PE;
- STM32_TIM_CCMR1(17) =
- STM32_TIM_CCMR1_OC1M_PWM_MODE_1 | STM32_TIM_CCMR1_OC1PE;
-
- /*
- * Enable output compare 1 (or its N counterpart). Note that if only
- * OC1N is enabled, then it is not complemented. From datasheet:
- * "When only OCxN is enabled (CCxE=0, CCxNE=1), it is not complemented"
- *
- * Note: we want the rising edge of SDA to be in the middle of SCL, so
- * invert the SDA (faster) signal.
- */
- if (ite_dfu_config.use_complement_timer_channel) {
- STM32_TIM_CCER(16) = STM32_TIM_CCER_CC1NE;
- STM32_TIM_CCER(17) = STM32_TIM_CCER_CC1NE |
- STM32_TIM_CCER_CC1NP;
- } else {
- STM32_TIM_CCER(16) = STM32_TIM_CCER_CC1E;
- STM32_TIM_CCER(17) = STM32_TIM_CCER_CC1E | STM32_TIM_CCER_CC1P;
- }
-
- /* Enable main output. */
- STM32_TIM_BDTR(16) = STM32_TIM_BDTR_MOE;
- STM32_TIM_BDTR(17) = STM32_TIM_BDTR_MOE;
-
- /* Update generation (reinitialize counters). */
- STM32_TIM_EGR(16) = STM32_TIM_EGR_UG;
- STM32_TIM_EGR(17) = STM32_TIM_EGR_UG;
-
- /* Set duty cycle to 0% or 100%, pinning each channel low or high. */
- STM32_TIM_CCR1(16) = SMCLK_PRE_LEVEL ? 0xFFFF : 0x0000;
- STM32_TIM_CCR1(17) = SMDAT_PRE_LEVEL ? 0xFFFF : 0x0000;
-
- /* Enable timer counters. */
- STM32_TIM_CR1(16) = STM32_TIM_CR1_CEN;
- STM32_TIM_CR1(17) = STM32_TIM_CR1_CEN;
-
- /* Set GPIO to alternate mode TIM(16|17)_CH1(N)? */
- gpio_config_pin(MODULE_I2C_TIMERS, ite_dfu_config.scl, 1);
- gpio_config_pin(MODULE_I2C_TIMERS, ite_dfu_config.sda, 1);
-
- msleep(START_DELAY_MS);
-
- /* Set pulse width to half of waveform period. */
- STM32_TIM_CCR1(16) = (MHz / SMCLK_WAVEFORM_PERIOD_HZ) / 2;
- STM32_TIM_CCR1(17) = (MHz / SMDAT_WAVEFORM_PERIOD_HZ) / 2;
-
- msleep(SPECIAL_WAVEFORM_MS);
-
- /* Set duty cycle to 0% or 100%, pinning each channel low or high. */
- STM32_TIM_CCR1(16) = SMCLK_POST_LEVEL ? 0xFFFF : 0x0000;
- STM32_TIM_CCR1(17) = SMDAT_POST_LEVEL ? 0xFFFF : 0x0000;
-
- msleep(PLL_STABLE_MS);
-
- /* Set GPIO back to alternate mode I2C. */
- gpio_config_pin(MODULE_I2C, ite_dfu_config.scl, 1);
- gpio_config_pin(MODULE_I2C, ite_dfu_config.sda, 1);
-
- /* Disable timer counters. */
- STM32_TIM_CR1(16) = 0x0000;
- STM32_TIM_CR1(17) = 0x0000;
-
- /* Disable peripheral clocks. */
- STM32_RCC_APB2ENR &=
- ~(STM32_RCC_APB2ENR_TIM16EN | STM32_RCC_APB2ENR_TIM17EN);
-
- return cprint_ite_chip_id();
-}
-DECLARE_CONSOLE_COMMAND(
- enable_ite_dfu, command_enable_ite_dfu, "",
- "Enable ITE Direct Firmware Update (DFU) mode");
-
-/* Read ITE chip ID. Can be used to verify ITE DFU mode. */
-static int command_get_ite_chipid(int argc, char **argv)
-{
- if (argc > 1)
- return EC_ERROR_PARAM_COUNT;
-
- /* Ensure we can perform the dfu operation */
- if (ite_dfu_config.access_allow && !ite_dfu_config.access_allow())
- return EC_ERROR_ACCESS_DENIED;
-
- return cprint_ite_chip_id();
-}
-DECLARE_CONSOLE_COMMAND(
- get_ite_chipid, command_get_ite_chipid, "",
- "Read ITE EC chip ID, version, flash size (must be in DFU mode)");