drivers: sdhc: add driver support for emmc host controller

add host controller driver support for emmc version 5.1.
The driver expose zephyr sdhc api interface for emmc host controller.

Signed-off-by: Najumon B.A <najumon.ba@intel.com>
This commit is contained in:
Najumon B.A 2023-08-03 14:46:54 +05:30 committed by Carles Cufí
parent c5094776e9
commit a14bc241c0
6 changed files with 1719 additions and 2 deletions

View file

@ -7,5 +7,5 @@ zephyr_library_sources_ifdef(CONFIG_IMX_USDHC imx_usdhc.c)
zephyr_library_sources_ifdef(CONFIG_SPI_SDHC sdhc_spi.c)
zephyr_library_sources_ifdef(CONFIG_MCUX_SDIF mcux_sdif.c)
zephyr_library_sources_ifdef(CONFIG_SAM_HSMCI sam_hsmci.c)
zephyr_library_sources_ifdef(CONFIG_INTEL_EMMC_HOST intel_emmc_host.c)
endif()

View file

@ -12,6 +12,7 @@ source "drivers/sdhc/Kconfig.imx"
source "drivers/sdhc/Kconfig.spi"
source "drivers/sdhc/Kconfig.mcux_sdif"
source "drivers/sdhc/Kconfig.sam_hsmci"
source "drivers/sdhc/Kconfig.intel"
config SDHC_INIT_PRIORITY
int "SDHC driver init priority"
@ -50,5 +51,4 @@ module = SDHC
module-str = sdhc
source "subsys/logging/Kconfig.template.log_config"
endif # SDHC

View file

@ -0,0 +1,58 @@
# Copyright (c) 2023 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
config INTEL_EMMC_HOST
bool "EMMC driver"
select SDHC_SUPPORTS_NATIVE_MODE
select EVENTS
default y
depends on DT_HAS_INTEL_EMMC_HOST_ENABLED
help
EMMC driver support. Though this driver can be easily port to
any HW which is complaint to eMMC spec, currently it is only
validated using intel's EMMC host controller.
if INTEL_EMMC_HOST
config INTEL_EMMC_HOST_INTR
bool "EMMC host controller interrupt mode"
default y
help
EMMC host controller interrupt mode support.
config INTEL_EMMC_HOST_DMA
bool "EMMC host controller DMA mode"
select DCACHE
help
EMMC host controller DMA mode support.
config INTEL_EMMC_HOST_ADMA
bool "EMMC host controller ADMA mode"
depends on INTEL_EMMC_HOST_DMA
help
EMMC host controller ADMA mode support.
config INTEL_EMMC_HOST_ADMA_DESC_SIZE
int "EMMC host controller ADMA Descriptor size"
depends on INTEL_EMMC_HOST_ADMA
default 32
help
EMMC host controller ADMA Descriptor size.
config INTEL_EMMC_HOST_AUTO_STOP
bool "auto stop command mode"
default y
help
Auto stop command mode support.
config INTEL_EMMC_HOST_BLOCK_GAP
bool "Block gap mode"
depends on INTEL_EMMC_HOST_DMA
help
Block gap mode support.
config INTEL_EMMC_HOST_TUNING
bool "Host tuning"
help
Host tuning support.
endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,303 @@
/*
* Copyright (c) 2023 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_DRIVERS_DISK_EMMC_HOST_H_
#define ZEPHYR_DRIVERS_DISK_EMMC_HOST_H_
/* Bit map for command Register */
#define EMMC_HOST_CMD_RESP_TYPE_LOC 0
#define EMMC_HOST_CMD_CRC_CHECK_EN_LOC 3
#define EMMC_HOST_CMD_IDX_CHECK_EN_LOC 4
#define EMMC_HOST_CMD_DATA_PRESENT_LOC 5
#define EMMC_HOST_CMD_TYPE_LOC 6
#define EMMC_HOST_CMD_INDEX_LOC 8
/* Bit map for Transfer Mode Register */
#define EMMC_HOST_XFER_DMA_EN_LOC 0
#define EMMC_HOST_XFER_BLOCK_CNT_EN_LOC 1
#define EMMC_HOST_XFER_AUTO_CMD_EN_LOC 2
#define EMMC_HOST_XFER_DATA_DIR_LOC 4
#define EMMC_HOST_XFER_MULTI_BLOCK_SEL_LOC 5
#define EMMC_HOST_XFER_DMA_EN_MASK 0x01
#define EMMC_HOST_XFER_BLOCK_CNT_EN_MASK 0x01
#define EMMC_HOST_XFER_AUTO_CMD_EN_MASK 0x03
#define EMMC_HOST_XFER_DATA_DIR_MASK 0x01
#define EMMC_HOST_XFER_MULTI_BLOCK_SEL_MASK 0x01
/* Bit map for Block Size and GAP Register */
#define EMMC_HOST_BLOCK_SIZE_LOC 0
#define EMMC_HOST_BLOCK_SIZE_MASK 0xFFF
#define EMMC_HOST_DMA_BUF_SIZE_LOC 12
#define EMMC_HOST_DMA_BUF_SIZE_MASK 0x07
#define EMMC_HOST_BLOCK_GAP_LOC 3
#define EMMC_HOST_BLOCK_GAP_MASK 0x01
#define EMMC_HOST_ADMA_BUFF_ADD_LOC 32
#define EMMC_HOST_ADMA_BUFF_LEN_LOC 16
#define EMMC_HOST_ADMA_BUFF_LINK_NEXT (0x3 << 4)
#define EMMC_HOST_ADMA_BUFF_LINK_LAST (0x2 << 4)
#define EMMC_HOST_ADMA_INTR_EN BIT(2)
#define EMMC_HOST_ADMA_BUFF_LAST BIT(1)
#define EMMC_HOST_ADMA_BUFF_VALID BIT(0)
/* Bit Map and length details for Clock Control Register */
#define EMMC_HOST_CLK_SDCLCK_FREQ_SEL_LOC 8
#define EMMC_HOST_CLK_SDCLCK_FREQ_SEL_UPPER_LOC 6
#define EMMC_HOST_CLK_SDCLCK_FREQ_SEL_MASK 0xFF
#define EMMC_HOST_CLK_SDCLCK_FREQ_SEL_UPPER_MASK 0x03
/* Bit Map for Host Control 1 Register */
#define EMMC_HOST_CTRL1_DAT_WIDTH_LOC 1
#define EMMC_HOST_CTRL1_DMA_SEL_LOC 3
#define EMMC_HOST_CTRL1_EXT_DAT_WIDTH_LOC 5
#define EMMC_HOST_CTRL1_DMA_SEL_MASK 0x03
#define EMMC_HOST_CTRL1_EXT_DAT_WIDTH_MASK 0x01
#define EMMC_HOST_CTRL1_DAT_WIDTH_MASK 0x01
/** Constants Software Reset register */
#define EMMC_HOST_SW_RESET_REG_ALL BIT(0)
#define EMMC_HOST_SW_RESET_REG_CMD BIT(1)
#define EMMC_HOST_SW_RESET_REG_DATA BIT(2)
#define EMMC_HOST_RESPONSE_SIZE 4
#define EMMC_HOST_OCR_BUSY_BIT BIT(31)
#define EMMC_HOST_OCR_CAPACITY_MASK 0x40000000U
#define EMMC_HOST_DUAL_VOLTAGE_RANGE 0x40FF8080U
#define EMMC_HOST_BLOCK_SIZE 512
#define EMMC_HOST_RCA_SHIFT 16
#define EMMC_HOST_EXTCSD_SEC_COUNT 53
#define EMMC_HOST_EXTCSD_GENERIC_CMD6_TIME 62
#define EMMC_HOST_EXTCSD_BUS_WIDTH_ADDR 0xB7
#define EMMC_HOST_EXTCSD_HS_TIMING_ADDR 0xB9
#define EMMC_HOST_BUS_SPEED_HIGHSPEED 1
#define EMMC_HOST_CMD_COMPLETE_RETRY 10000
#define EMMC_HOST_XFR_COMPLETE_RETRY 2000000
#define EMMC_HOST_CMD1_RETRY_TIMEOUT 1000
#define EMMC_HOST_CMD6_TIMEOUT_MULT 10
#define EMMC_HOST_NORMAL_INTR_MASK 0x3f
#define EMMC_HOST_ERROR_INTR_MASK 0x13ff
#define EMMC_HOST_NORMAL_INTR_MASK_CLR 0x60ff
#define EMMC_HOST_POWER_CTRL_SD_BUS_POWER 0x1
#define EMMC_HOST_POWER_CTRL_SD_BUS_VOLT_SEL 0x5
#define EMMC_HOST_UHSMODE_SDR12 0x0
#define EMMC_HOST_UHSMODE_SDR25 0x1
#define EMMC_HOST_UHSMODE_SDR50 0x2
#define EMMC_HOST_UHSMODE_SDR104 0x3
#define EMMC_HOST_UHSMODE_DDR50 0x4
#define EMMC_HOST_UHSMODE_HS400 0x5
#define EMMC_HOST_CTRL2_1P8V_SIG_EN 1
#define EMMC_HOST_CTRL2_1P8V_SIG_LOC 3
#define EMMC_HOST_CTRL2_UHS_MODE_SEL_LOC 0
#define EMMC_HOST_CTRL2_UHS_MODE_SEL_MASK 0x07
/* Event/command status */
#define EMMC_HOST_CMD_COMPLETE BIT(0)
#define EMMC_HOST_XFER_COMPLETE BIT(1)
#define EMMC_HOST_BLOCK_GAP_INTR BIT(2)
#define EMMC_HOST_DMA_INTR BIT(3)
#define EMMC_HOST_BUF_WR_READY BIT(4)
#define EMMC_HOST_BUF_RD_READY BIT(5)
#define EMMC_HOST_CMD_TIMEOUT_ERR BIT(0)
#define EMMC_HOST_CMD_CRC_ERR BIT(1)
#define EMMC_HOST_CMD_END_BIT_ERR BIT(2)
#define EMMC_HOST_CMD_IDX_ERR BIT(3)
#define EMMC_HOST_DATA_TIMEOUT_ERR BIT(4)
#define EMMC_HOST_DATA_CRC_ERR BIT(5)
#define EMMC_HOST_DATA_END_BIT_ERR BIT(6)
#define EMMC_HOST_CUR_LMT_ERR BIT(7)
#define EMMC_HOST_DMA_TXFR_ERR BIT(12)
#define EMMC_HOST_ERR_STATUS 0xFFF
/** PState register bits */
#define EMMC_HOST_PSTATE_CMD_INHIBIT BIT(0)
#define EMMC_HOST_PSTATE_DAT_INHIBIT BIT(1)
#define EMMC_HOST_PSTATE_DAT_LINE_ACTIVE BIT(2)
#define EMMC_HOST_PSTATE_WR_DMA_ACTIVE BIT(8)
#define EMMC_HOST_PSTATE_RD_DMA_ACTIVE BIT(9)
#define EMMC_HOST_PSTATE_BUF_READ_EN BIT(11)
#define EMMC_HOST_PSTATE_BUF_WRITE_EN BIT(10)
#define EMMC_HOST_PSTATE_CARD_INSERTED BIT(16)
#define EMMC_HOST_MAX_TIMEOUT 0xe
#define EMMC_HOST_MSEC_DELAY 1000
/** Constants for Clock Control register */
#define EMMC_HOST_INTERNAL_CLOCK_EN BIT(0)
#define EMMC_HOST_INTERNAL_CLOCK_STABLE BIT(1)
#define EMMC_HOST_SD_CLOCK_EN BIT(2)
/** Clock frequency */
#define EMMC_HOST_CLK_FREQ_400K 0.4
#define EMMC_HOST_CLK_FREQ_25M 25
#define EMMC_HOST_CLK_FREQ_50M 50
#define EMMC_HOST_CLK_FREQ_100M 100
#define EMMC_HOST_CLK_FREQ_200M 200
#define EMMC_HOST_TUNING_SUCCESS BIT(7)
#define EMMC_HOST_START_TUNING BIT(6)
#define EMMC_HOST_VOL_3_3_V_SUPPORT BIT(24)
#define EMMC_HOST_VOL_3_3_V_SELECT (7 << 1)
#define EMMC_HOST_VOL_3_0_V_SUPPORT BIT(25)
#define EMMC_HOST_VOL_3_0_V_SELECT (6 << 1)
#define EMMC_HOST_VOL_1_8_V_SUPPORT BIT(26)
#define EMMC_HOST_VOL_1_8_V_SELECT (5 << 1)
#define EMMC_HOST_CMD_WAIT_TIMEOUT_US 3000
#define EMMC_HOST_CMD_CMPLETE_TIMEOUT_US 9000
#define EMMC_HOST_XFR_CMPLETE_TIMEOUT_US 1000
#define EMMC_HOST_SDMA_BOUNDARY 0x0
#define EMMC_HOST_RCA_ADDRESS 0x2
#define EMMC_HOST_RESP_MASK (0xFF000000U)
#define EMMC_HOST_SET_RESP(resp0, resp1) (resp0 >> 1) | ((resp1 & 1) << 30)
#define SET_BITS(reg, pos, bit_width, val) \
reg &= ~(bit_width << pos); \
reg |= ((val & bit_width) << pos)
/* get value from certain bit
*/
#define GET_BITS(reg_name, start, width) ((reg_name) & (((1 << (width)) - 1) << (start)))
#define ERR_INTR_STATUS_EVENT(reg_bits) reg_bits << 16
#define ADDRESS_32BIT_MASK 0xFFFFFFFF
struct emmc_reg {
volatile uint32_t sdma_sysaddr; /**< SDMA System Address */
volatile uint16_t block_size; /**< Block Size */
volatile uint16_t block_count; /**< Block Count */
volatile uint32_t argument; /**< Argument */
volatile uint16_t transfer_mode; /**< Transfer Mode */
volatile uint16_t cmd; /**< Command */
volatile uint32_t resp_01; /**< Response Register 0 & 1 */
volatile uint16_t resp_2; /**< Response Register 2*/
volatile uint16_t resp_3; /**< Response Register 3 */
volatile uint16_t resp_4; /**< Response Register 4 */
volatile uint16_t resp_5; /**< Response Register 5 */
volatile uint16_t resp_6; /**< Response Register 6 */
volatile uint16_t resp_7; /**< Response Register 7 */
volatile uint32_t data_port; /**< Buffer Data Port */
volatile uint32_t present_state; /**< Present State */
volatile uint8_t host_ctrl1; /**< Host Control 1 */
volatile uint8_t power_ctrl; /**< Power Control */
volatile uint8_t block_gap_ctrl; /**< Block Gap Control */
volatile uint8_t wake_up_ctrl; /**< Wakeup Control */
volatile uint16_t clock_ctrl; /**< Clock Control */
volatile uint8_t timeout_ctrl; /**< Timeout Control */
volatile uint8_t sw_reset; /**< Software Reset */
volatile uint16_t normal_int_stat; /**< Normal Interrupt Status */
volatile uint16_t err_int_stat; /**< Error Interrupt Status */
volatile uint16_t normal_int_stat_en; /**< Normal Interrupt Status Enable */
volatile uint16_t err_int_stat_en; /**< Error Interrupt Status Enable */
volatile uint16_t normal_int_signal_en; /**< Normal Interrupt Signal Enable */
volatile uint16_t err_int_signal_en; /**< Error Interrupt Signal Enable */
volatile uint16_t auto_cmd_err_stat; /**< Auto CMD Error Status */
volatile uint16_t host_ctrl2; /**< Host Control 2 */
volatile uint64_t capabilities; /**< Capabilities */
volatile uint64_t max_current_cap; /**< Max Current Capabilities */
volatile uint16_t force_err_autocmd_stat; /**< Force Event for Auto CMD Error Status*/
volatile uint16_t force_err_int_stat; /**< Force Event for Error Interrupt Status */
volatile uint8_t adma_err_stat; /**< ADMA Error Status */
volatile uint8_t reserved[3];
volatile uint32_t adma_sys_addr1; /**< ADMA System Address1 */
volatile uint32_t adma_sys_addr2; /**< ADMA System Address2 */
volatile uint16_t preset_val_0; /**< Preset Value 0 */
volatile uint16_t preset_val_1; /**< Preset Value 1 */
volatile uint16_t preset_val_2; /**< Preset Value 2 */
volatile uint16_t preset_val_3; /**< Preset Value 3 */
volatile uint16_t preset_val_4; /**< Preset Value 4 */
volatile uint16_t preset_val_5; /**< Preset Value 5 */
volatile uint16_t preset_val_6; /**< Preset Value 6 */
volatile uint16_t preset_val_7; /**< Preset Value 7 */
volatile uint32_t boot_timeout; /**< Boot Timeout */
volatile uint16_t preset_val_8; /**< Preset Value 8 */
volatile uint16_t reserved3;
volatile uint16_t vendor_reg; /**< Vendor Enhanced strobe */
volatile uint16_t reserved4[56];
volatile uint32_t reserved5[4];
volatile uint16_t slot_intr_stat; /**< Slot Interrupt Status */
volatile uint16_t host_cntrl_version; /**< Host Controller Version */
volatile uint32_t reserved6[64];
volatile uint32_t cq_ver; /**< Command Queue Version */
volatile uint32_t cq_cap; /**< Command Queue Capabilities */
volatile uint32_t cq_cfg; /**< Command Queue Configuration */
volatile uint32_t cq_ctrl; /**< Command Queue Control */
volatile uint32_t cq_intr_stat; /**< Command Queue Interrupt Status */
volatile uint32_t cq_intr_stat_en; /**< Command Queue Interrupt Status Enable */
volatile uint32_t cq_intr_sig_en; /**< Command Queue Interrupt Signal Enable */
volatile uint32_t cq_intr_coalesc; /**< Command Queue Interrupt Coalescing */
volatile uint32_t cq_tdlba; /**< Command Queue Task Desc List Base Addr */
volatile uint32_t cq_tdlba_upr; /**< Command Queue Task Desc List Base Addr Upr */
volatile uint32_t cq_task_db; /**< Command Queue Task DoorBell */
volatile uint32_t cq_task_db_notify; /**< Command Queue Task DoorBell Notify */
volatile uint32_t cq_dev_qstat; /**< Command Queue Device queue status */
volatile uint32_t cq_dev_pend_task; /**< Command Queue Device pending tasks */
volatile uint32_t cq_task_clr; /**< Command Queue Task Clr */
volatile uint32_t reserved7;
volatile uint32_t cq_ssc1; /**< Command Queue Send Status Configuration 1 */
volatile uint32_t cq_ssc2; /**< Command Queue Send Status Configuration 2 */
volatile uint32_t cq_crdct; /**< Command response for direct command */
volatile uint32_t reserved8;
volatile uint32_t cq_rmem; /**< Command response mode error mask */
volatile uint32_t cq_terri; /**< Command Queue Task Error Information */
volatile uint32_t cq_cri; /**< Command Queue Command response index */
volatile uint32_t cq_cra; /**< Command Queue Command response argument */
volatile uint32_t reserved9[425];
};
enum emmc_sw_reset {
EMMC_HOST_SW_RESET_DATA_LINE = 0,
EMMC_HOST_SW_RESET_CMD_LINE,
EMMC_HOST_SW_RESET_ALL
};
enum emmc_cmd_type {
EMMC_HOST_CMD_NORMAL = 0,
EMMC_HOST_CMD_SUSPEND,
EMMC_HOST_CMD_RESUME,
EMMC_HOST_CMD_ABORT,
};
enum emmc_response_type {
EMMC_HOST_RESP_NONE = 0,
EMMC_HOST_RESP_LEN_136,
EMMC_HOST_RESP_LEN_48,
EMMC_HOST_RESP_LEN_48B,
EMMC_HOST_INVAL_HOST_RESP_LEN,
};
struct emmc_cmd_config {
struct sdhc_command *sdhc_cmd;
uint32_t cmd_idx;
enum emmc_cmd_type cmd_type;
bool data_present;
bool idx_check_en;
bool crc_check_en;
};
struct resp {
uint64_t resp_48bit;
};
#endif /* _EMMC_HOST_HC_H_ */

View file

@ -0,0 +1,8 @@
# Copyright (c) 2023 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
description: eMMC host controller
compatible: "intel,emmc-host"
include: [sdhc.yaml, pcie-device.yaml]