/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Efinix eMMC Host Controller Driver Header with DMA Support * * Copyright (C) 2025 Efinix, Inc. * Author: Teoh Choon Zone */ #ifndef __EFX_EMMC_H__ #define __EFX_EMMC_H__ #include #include #include #include #include #include #ifndef min3 #define min3(x, y, z) min(min(x, y), z) #endif #define EFX_ADMA_DESC_VALID BIT(0) #define EFX_ADMA_DESC_END BIT(1) #define EFX_ADMA_DESC_INT BIT(2) #define EFX_ADMA_DESC_NOP (0 << 4) #define EFX_ADMA_DESC_TRAN (2 << 4) #define EFX_ADMA_DESC_LINK (3 << 4) #define EFX_ADMA_MAX_LEN 65536 #define EFX_ADMA_DESC_ALIGN 8 #define EFX_ADMA_TABLE_SZ (512 * 8) #define EFX_DMA_BOUNDARY_4K 0 #define EFX_DMA_BOUNDARY_8K 1 #define EFX_DMA_BOUNDARY_16K 2 #define EFX_DMA_BOUNDARY_32K 3 #define EFX_DMA_BOUNDARY_64K 4 #define EFX_DMA_BOUNDARY_128K 5 #define EFX_DMA_BOUNDARY_256K 6 #define EFX_DMA_BOUNDARY_512K 7 #define EFX_EMMC_VERSION 0x000 #define EFX_EMMC_BASE_REG0 0x004 #define EFX_EMMC_BASE_STATUS_REG0 0x008 #define EFX_EMMC_BASE_REG1 0x00C #define EFX_EMMC_ARG2 0x100 #define EFX_EMMC_BLOCK_SIZE 0x104 #define EFX_EMMC_ARG1 0x108 #define EFX_EMMC_TRANSFER_MODE 0x10C #define EFX_EMMC_RESPONSE0 0x110 #define EFX_EMMC_RESPONSE1 0x114 #define EFX_EMMC_RESPONSE2 0x118 #define EFX_EMMC_RESPONSE3 0x11C #define EFX_EMMC_BUFFER_DATA_PORT 0x120 #define EFX_EMMC_PRESENT_STATE 0x124 #define EFX_EMMC_HOST_CONTROL 0x128 #define EFX_EMMC_INT_STATUS 0x130 #define EFX_EMMC_INT_STATUS_EN 0x134 #define EFX_EMMC_INT_SIGNAL_EN 0x138 #define EFX_EMMC_HOST_CAPABILITIES 0x140 #define EFX_EMMC_ADMA_SYS_ADDR_LOW 0x158 #define EFX_EMMC_ADMA_SYS_ADDR_HIGH 0x15C #define EFX_SYS_DATE_REG 0x000 #define EFX_SYS_TEST_REG 0x004 #define EFX_SYS_RESET_REG 0x008 #define EFX_EMMC_BASE_REG0_CLK_EN BIT(16) #define EFX_EMMC_BASE_REG0_CLK_DIV_MASK 0xFFFF #define EFX_EMMC_BASE_STATUS_DAT_BUSY BIT(1) #define EFX_EMMC_BASE_STATUS_CMD_BUSY BIT(0) #define EFX_EMMC_BASE_REG1_SAMPLE_CNT_SHIFT 16 #define EFX_EMMC_BASE_REG1_SAMPLE_CNT_MASK (0xFFFF << 16) #define EFX_EMMC_BASE_REG1_PHASE_SHIFT 6 #define EFX_EMMC_BASE_REG1_PHASE_MASK (0x7 << 6) #define EFX_EMMC_BASE_REG1_PHASE_PULSE BIT(0) #define EFX_EMMC_BLOCK_COUNT_SHIFT 16 #define EFX_EMMC_BLOCK_COUNT_MASK (0xFFFF << 16) #define EFX_EMMC_BLOCK_SIZE_MASK 0xFFF #define EFX_EMMC_DMA_BOUNDARY_SHIFT 12 #define EFX_EMMC_DMA_BOUNDARY_MASK (0x7 << 12) #define EFX_EMMC_CMD_INDEX_SHIFT 24 #define EFX_EMMC_CMD_INDEX_MASK (0x3F << 24) #define EFX_EMMC_DATA_PRESENT BIT(21) #define EFX_EMMC_CMD_INDEX_CHECK_EN BIT(20) #define EFX_EMMC_CMD_CRC_CHECK_EN BIT(19) #define EFX_EMMC_RESP_TYPE_SHIFT 16 #define EFX_EMMC_RESP_TYPE_MASK (0x3 << 16) #define EFX_EMMC_RESP_TYPE_NONE 0 #define EFX_EMMC_RESP_TYPE_136 1 #define EFX_EMMC_RESP_TYPE_48 2 #define EFX_EMMC_RESP_TYPE_48_BUSY 3 #define EFX_EMMC_MULTI_BLOCK_SEL BIT(5) #define EFX_EMMC_DATA_XFER_DIR BIT(4) #define EFX_EMMC_AUTO_CMD_EN_SHIFT 2 #define EFX_EMMC_AUTO_CMD_EN_MASK (0x3 << 2) #define EFX_EMMC_BLOCK_COUNT_EN BIT(1) #define EFX_EMMC_DMA_EN BIT(0) #define EFX_EMMC_BUFFER_READ_EN BIT(11) #define EFX_EMMC_BUFFER_WRITE_EN BIT(10) #define EFX_EMMC_READ_XFER_ACTIVE BIT(9) #define EFX_EMMC_WRITE_XFER_ACTIVE BIT(8) #define EFX_EMMC_DAT_LINE_ACTIVE BIT(2) #define EFX_EMMC_CMD_INHIBIT_DAT BIT(1) #define EFX_EMMC_CMD_INHIBIT_CMD BIT(0) #define EFX_EMMC_DATA_SAMPLING_MODE BIT(3) #define EFX_EMMC_DATA_WIDTH_SHIFT 1 #define EFX_EMMC_DATA_WIDTH_MASK (0x3 << 1) #define EFX_EMMC_DATA_WIDTH_1BIT 0 #define EFX_EMMC_DATA_WIDTH_4BIT 1 #define EFX_EMMC_DATA_WIDTH_8BIT 2 #define EFX_EMMC_INT_ADMA_ERROR BIT(25) #define EFX_EMMC_INT_DATA_TIMEOUT_ERR BIT(22) #define EFX_EMMC_INT_DATA_CRC_ERR BIT(21) #define EFX_EMMC_INT_DATA_END_BIT_ERR BIT(20) #define EFX_EMMC_INT_CMD_INDEX_ERR BIT(19) #define EFX_EMMC_INT_CMD_END_BIT_ERR BIT(18) #define EFX_EMMC_INT_CMD_CRC_ERR BIT(17) #define EFX_EMMC_INT_CMD_TIMEOUT_ERR BIT(16) #define EFX_EMMC_INT_BUFFER_READ_RDY BIT(5) #define EFX_EMMC_INT_BUFFER_WRITE_RDY BIT(4) #define EFX_EMMC_INT_BLOCK_GAP_EVENT BIT(2) #define EFX_EMMC_INT_XFER_COMPLETE BIT(1) #define EFX_EMMC_INT_CMD_COMPLETE BIT(0) #define EFX_EMMC_INT_ERROR_MASK (EFX_EMMC_INT_ADMA_ERROR | \ EFX_EMMC_INT_DATA_TIMEOUT_ERR | \ EFX_EMMC_INT_DATA_CRC_ERR | \ EFX_EMMC_INT_DATA_END_BIT_ERR | \ EFX_EMMC_INT_CMD_INDEX_ERR | \ EFX_EMMC_INT_CMD_END_BIT_ERR | \ EFX_EMMC_INT_CMD_CRC_ERR | \ EFX_EMMC_INT_CMD_TIMEOUT_ERR) #define EFX_EMMC_INT_ALL_MASK (EFX_EMMC_INT_ERROR_MASK | \ EFX_EMMC_INT_BUFFER_READ_RDY | \ EFX_EMMC_INT_BUFFER_WRITE_RDY | \ EFX_EMMC_INT_BLOCK_GAP_EVENT | \ EFX_EMMC_INT_XFER_COMPLETE | \ EFX_EMMC_INT_CMD_COMPLETE) #define EFX_SYS_RESET_EMMC_DEV BIT(1) #define EFX_SYS_RESET_EMMC_IP BIT(0) #define EFX_EMMC_BASE_CLK_FREQ_MHZ 200 #define EFX_EMMC_MAX_BLOCK_LENGTH 512 #define EFX_EMMC_TIMEOUT_CLK_FREQ 200000000 #define EFX_EMMC_MIN_FREQ 400000 #define EFX_EMMC_MAX_FREQ 200000000 #define EFX_EMMC_PIO_TIMEOUT_MS 1000 #define EFX_EMMC_CLOCK_STABILIZE_DELAY 1000 #define EFX_EMMC_RESET_PULSE_WIDTH 1 #define EFX_EMMC_POST_RESET_DELAY 200 #define EFX_EMMC_CMD_RETRY_COUNT 3 #define EFX_EMMC_MAX_PLL_SHIFT 8 #define EFX_EMMC_PLL_SETTLING_TIME 50 #define EFX_EMMC_TUNING_TIMEOUT_MS 50 #define EFX_EMMC_TUNING_POLL_INTERVAL 200 #define EFX_EMMC_TUNING_BLOCK_SIZE_4BIT 64 #define EFX_EMMC_TUNING_BLOCK_SIZE_8BIT 128 #define EFX_EMMC_MIN_TIMING_MARGIN 1 struct efx_adma_desc { u16 attr; u16 len; u32 addr; } __packed __aligned(8); struct efx_emmc_host { struct mmc_host *mmc; void __iomem *ioaddr; void __iomem *sys_ioaddr; struct clk *clk; int irq; struct mmc_request *mrq; struct mmc_request *mrq_done; struct mmc_command *cmd; struct mmc_data *data; u32 base_clk; u32 current_clk; int bytes_to_transfer; int blocks_done; unsigned int sg_offset; struct efx_adma_desc *adma_desc; dma_addr_t adma_desc_dma; size_t adma_desc_sz; void *bounce_buffer; dma_addr_t bounce_dma; unsigned int bounce_buffer_size; unsigned int bounce_used; bool bounce_active; bool use_dma; bool dma_64bit; u32 clk_div; u32 hs200_sample_count; u32 hs200_pll_shift; u32 hs200_margin; u32 hs400_sample_count; u32 hs400_pll_shift; u32 hs400_margin; u32 hs400_default_sample; u32 hs400_default_pll; bool tuning_done; bool tuning_in_progress; unsigned int prev_timing; bool hs400_retune_pending; struct delayed_work hs400_retune_work; unsigned long tuned_timing_modes; spinlock_t lock; struct platform_device *pdev; }; #define efx_emmc_dbg_irq(host, fmt, ...) \ dev_dbg(&(host)->pdev->dev, fmt, ##__VA_ARGS__) #define efx_emmc_dbg_pio(host, fmt, ...) \ dev_dbg(&(host)->pdev->dev, fmt, ##__VA_ARGS__) #define efx_emmc_dbg_cmd(host, fmt, ...) \ dev_dbg(&(host)->pdev->dev, fmt, ##__VA_ARGS__) int efx_emmc_probe(struct platform_device *pdev); int efx_emmc_remove(struct platform_device *pdev); int efx_emmc_init_hw(struct efx_emmc_host *host); void efx_emmc_reset_hw(struct efx_emmc_host *host); void efx_emmc_hs400_retune_work(struct work_struct *work); void efx_emmc_request(struct mmc_host *mmc, struct mmc_request *mrq); void efx_emmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); int efx_emmc_get_cd(struct mmc_host *mmc); int efx_emmc_card_busy_wrapper(struct mmc_host *mmc); int efx_emmc_get_ro(struct mmc_host *mmc); irqreturn_t efx_emmc_irq(int irq, void *dev_id); void efx_emmc_send_command(struct efx_emmc_host *host, struct mmc_command *cmd); void efx_emmc_finish_request(struct efx_emmc_host *host, struct mmc_request *mrq); void efx_emmc_finish_command(struct efx_emmc_host *host); void efx_emmc_finish_data(struct efx_emmc_host *host); void efx_emmc_transfer_pio(struct efx_emmc_host *host); void efx_emmc_set_clock(struct efx_emmc_host *host, unsigned int clock); void efx_emmc_set_bus_width(struct efx_emmc_host *host, int width); void efx_emmc_set_timing(struct efx_emmc_host *host, unsigned int timing); bool efx_emmc_card_busy(struct efx_emmc_host *host); int efx_emmc_adma_table_pre(struct efx_emmc_host *host, struct mmc_data *data); void efx_emmc_adma_table_post(struct efx_emmc_host *host, struct mmc_data *data); void efx_emmc_prepare_dma(struct efx_emmc_host *host, struct mmc_data *data); void efx_emmc_cleanup_dma(struct efx_emmc_host *host, struct mmc_data *data); void efx_emmc_set_adma_addr(struct efx_emmc_host *host, dma_addr_t addr); int efx_emmc_execute_tuning(struct mmc_host *mmc, u32 opcode); int efx_emmc_execute_tuning_command(struct efx_emmc_host *host, int bus_width); void efx_emmc_set_timing_config(struct efx_emmc_host *host, u32 sample_count, u32 pll_shift); int efx_emmc_find_optimal_timing(struct efx_emmc_host *host, u8 result_map[][EFX_EMMC_MAX_PLL_SHIFT], u32 max_sample_count); static inline u32 efx_emmc_readl(struct efx_emmc_host *host, u32 reg) { return readl(host->ioaddr + reg); } static inline void efx_emmc_writel(struct efx_emmc_host *host, u32 val, u32 reg) { writel(val, host->ioaddr + reg); } static inline u32 efx_emmc_sys_readl(struct efx_emmc_host *host, u32 reg) { return readl(host->sys_ioaddr + reg); } static inline void efx_emmc_sys_writel(struct efx_emmc_host *host, u32 val, u32 reg) { writel(val, host->sys_ioaddr + reg); } #endif