diff options
Diffstat (limited to 'baseboard/kukui/emmc_ite.c')
-rw-r--r-- | baseboard/kukui/emmc_ite.c | 205 |
1 files changed, 0 insertions, 205 deletions
diff --git a/baseboard/kukui/emmc_ite.c b/baseboard/kukui/emmc_ite.c deleted file mode 100644 index 8c3e63064c..0000000000 --- a/baseboard/kukui/emmc_ite.c +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "chipset.h" -#include "console.h" -#include "endian.h" -#include "gpio.h" -#include "hooks.h" -#include "hwtimer.h" -#include "intc.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -#include "bootblock_data.h" - -#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args) - -enum emmc_cmd { - EMMC_ERROR = -1, - EMMC_IDLE = 0, - EMMC_PRE_IDLE, - EMMC_BOOT, -}; - -static void emmc_reset_spi_tx(void) -{ - /* Reset TX FIFO and count monitor */ - IT83XX_SPI_TXFCR = IT83XX_SPI_TXFR | IT83XX_SPI_TXFCMR; - /* Send idle state (high/0xff) if master clocks in data. */ - IT83XX_SPI_FCR = 0; -} - -static void emmc_reset_spi_rx(void) -{ - /* End Rx FIFO access */ - IT83XX_SPI_TXRXFAR = 0; - /* Reset RX FIFO and count monitor */ - IT83XX_SPI_FCR = IT83XX_SPI_RXFR | IT83XX_SPI_RXFCMR; -} - -/* - * Set SPI module work as eMMC Alternative Boot Mode. - * (CS# pin isn't required, and dropping data until CMD goes low) - */ -static void emmc_enable_spi(void) -{ - /* Set SPI pin mux to eMMC (GPM2:CLK, GPM3:CMD, GPM6:DATA0) */ - IT83XX_GCTRL_PIN_MUX0 |= BIT(7); - /* Enable eMMC Alternative Boot Mode */ - IT83XX_SPI_EMMCBMR |= IT83XX_SPI_EMMCABM; - /* Reset TX and RX FIFO */ - emmc_reset_spi_tx(); - emmc_reset_spi_rx(); - /* Response idle state (high) */ - IT83XX_SPI_SPISRDR = 0xff; - /* FIFO will be overwritten once it's full */ - IT83XX_SPI_GCR2 = 0; - /* Write to clear pending interrupt bits */ - IT83XX_SPI_ISR = 0xff; - IT83XX_SPI_RX_VLISR = IT83XX_SPI_RVLI; - /* Enable RX fifo full interrupt */ - IT83XX_SPI_IMR = 0xff; - IT83XX_SPI_RX_VLISMR |= IT83XX_SPI_RVLIM; - IT83XX_SPI_IMR &= ~IT83XX_SPI_RX_FIFO_FULL; - /* - * Enable interrupt to detect AP's BOOTBLOCK_EN_L. So EC is able to - * switch SPI module back to communication mode once BOOTBLOCK_EN_L - * goes high (AP Jumped to bootloader). - */ - gpio_clear_pending_interrupt(GPIO_BOOTBLOCK_EN_L); - gpio_enable_interrupt(GPIO_BOOTBLOCK_EN_L); - - disable_sleep(SLEEP_MASK_EMMC); - CPRINTS("eMMC emulation enabled"); -} -DECLARE_HOOK(HOOK_CHIPSET_STARTUP, emmc_enable_spi, HOOK_PRIO_FIRST); - -static void emmc_init_spi(void) -{ - /* Enable alternate function */ - gpio_config_module(MODULE_SPI_FLASH, 1); -} -DECLARE_HOOK(HOOK_INIT, emmc_init_spi, HOOK_PRIO_INIT_SPI + 1); - -static void emmc_send_data_over_spi(uint8_t *tx, int tx_size, int rst_tx) -{ - int i; - - /* Reset TX FIFO and count monitor */ - if (rst_tx) - IT83XX_SPI_TXFCR = IT83XX_SPI_TXFR | IT83XX_SPI_TXFCMR; - /* CPU access TX FIFO1 and FIFO2 */ - IT83XX_SPI_TXRXFAR = IT83XX_SPI_CPUTFA; - - /* Write response data to TX FIFO */ - for (i = 0; i < tx_size; i += 4) - IT83XX_SPI_CPUWTFDB0 = *(uint32_t *)(tx + i); - /* - * After writing data to TX FIFO is finished, this bit will - * be to indicate the SPI slave controller. - */ - IT83XX_SPI_TXFCR = IT83XX_SPI_TXFS; - /* End CPU access TX FIFO */ - IT83XX_SPI_TXRXFAR = 0; - /* SPI module access TX FIFO */ - IT83XX_SPI_FCR = IT83XX_SPI_SPISRTXF; -} - -static void emmc_bootblock_transfer(void) -{ - int tx_size, sent = 0, remaining = sizeof(bootblock_raw_data); - uint8_t *raw = (uint8_t *)bootblock_raw_data; - const uint32_t timeout_us = 200; - uint32_t start; - - /* - * HW will transmit the data of FIFO1 or FIFO2 in turn. - * So when a FIFO is empty, we need to fill the FIFO out - * immediately. - */ - emmc_send_data_over_spi(&raw[sent], 256, 1); - sent += 256; - - while (sent < remaining) { - /* Wait for FIFO1 or FIFO2 have been transmitted */ - start = __hw_clock_source_read(); - while (!(IT83XX_SPI_TXFSR & BIT(0)) && - (__hw_clock_source_read() - start < timeout_us)) - ; - /* Abort an ongoing transfer due to a command is received. */ - if (IT83XX_SPI_ISR & IT83XX_SPI_RX_FIFO_FULL) - break; - /* fill out next 128 bytes to FIFO1 or FIFO2 */ - tx_size = (remaining - sent) < 128 ? (remaining - sent) : 128; - emmc_send_data_over_spi(&raw[sent], tx_size, 0); - sent += tx_size; - } -} - -static enum emmc_cmd emmc_parse_command(int index, uint32_t *cmd0) -{ - int32_t shift0; - uint32_t data[3]; - - data[0] = htobe32(cmd0[index]); - data[1] = htobe32(cmd0[index+1]); - data[2] = htobe32(cmd0[index+2]); - - if ((data[0] & 0xff000000) != 0x40000000) { - /* Figure out alignment (cmd starts with 01) */ - /* Number of leading ones. */ - shift0 = __builtin_clz(~data[0]); - - data[0] = (data[0] << shift0) | (data[1] >> (32-shift0)); - data[1] = (data[1] << shift0) | (data[2] >> (32-shift0)); - } - - if (data[0] == 0x40000000 && data[1] == 0x0095ffff) { - /* 400000000095 GO_IDLE_STATE */ - CPRINTS("goIdle"); - return EMMC_IDLE; - } - - if (data[0] == 0x40f0f0f0 && data[1] == 0xf0fdffff) { - /* 40f0f0f0f0fd GO_PRE_IDLE_STATE */ - CPRINTS("goPreIdle"); - return EMMC_PRE_IDLE; - } - - if (data[0] == 0x40ffffff && data[1] == 0xfae5ffff) { - /* 40fffffffae5 BOOT_INITIATION */ - CPRINTS("bootInit"); - return EMMC_BOOT; - } - - CPRINTS("eMMC error"); - return EMMC_ERROR; -} - -void spi_emmc_cmd0_isr(uint32_t *cmd0_payload) -{ - enum emmc_cmd cmd; - - for (int i = 0; i < 8; i++) { - if (cmd0_payload[i] == 0xffffffff) - continue; - - cmd = emmc_parse_command(i, &cmd0_payload[i]); - - if (cmd == EMMC_IDLE || cmd == EMMC_PRE_IDLE) { - /* Abort an ongoing transfer. */ - emmc_reset_spi_tx(); - break; - } - - if (cmd == EMMC_BOOT) { - emmc_bootblock_transfer(); - break; - } - } -} |