kernel_samsung_a34x-permissive/drivers/mmc/host/mtk-msdc.h

263 lines
6.6 KiB
C
Raw Permalink Normal View History

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#ifndef __MT_MSDC_H__
#define __MT_MSDC_H__
#include <mt-plat/sync_write.h>
#if defined(CONFIG_MACH_MT6768) && defined(CONFIG_MTK_PMQOS)
#include <linux/soc/mediatek/mtk-pm-qos.h>
#endif
#define HOST_MAX_NUM (2)
#define TUNE_NONE (0) /* No need tune */
#define TUNE_CMD_CRC (0x1 << 0) /* transfer cmd crc */
#define TUNE_DATA_WRITE (0x1 << 1) /* transfer data crc */
#define TUNE_DATA_READ (0x1 << 2) /* transfer data crc */
#define TUNE_CMD_TMO (0x1 << 3) /* transfer cmd tmo */
#define TUNE_AUTOK_PASS (0x1 << 4) /* autok pass flag */
enum {
MODE_PIO = 0,
MODE_DMA = 1,
MODE_SIZE_DEP = 2,
MODE_NONE = 3,
};
static inline unsigned int uffs(unsigned int x)
{
unsigned int r = 1;
if (!x)
return 0;
if (!(x & 0xffff)) {
x >>= 16;
r += 16;
}
if (!(x & 0xff)) {
x >>= 8;
r += 8;
}
if (!(x & 0xf)) {
x >>= 4;
r += 4;
}
if (!(x & 3)) {
x >>= 2;
r += 2;
}
if (!(x & 1)) {
x >>= 1;
r += 1;
}
return r;
}
#define MSDC_READ8(reg) __raw_readb(reg)
#define MSDC_READ16(reg) __raw_readw(reg)
#define MSDC_READ32(reg) __raw_readl(reg)
#define MSDC_WRITE8(reg, val) mt_reg_sync_writeb(val, reg)
#define MSDC_WRITE16(reg, val) mt_reg_sync_writew(val, reg)
#define MSDC_WRITE32(reg, val) mt_reg_sync_writel(val, reg)
#define UNSTUFF_BITS(resp, start, size) \
({ \
const int __size = size; \
const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \
const int __off = 3 - ((start) / 32); \
const int __shft = (start) & 31; \
u32 __res; \
__res = resp[__off] >> __shft; \
if (__size + __shft > 32) \
__res |= resp[__off-1] << ((32 - __shft) % 32); \
__res & __mask; \
})
#define MSDC_SET_BIT32(reg, bs) \
do { \
unsigned int tv = MSDC_READ32(reg);\
tv |= (u32)(bs); \
MSDC_WRITE32(reg, tv); \
} while (0)
#define MSDC_CLR_BIT32(reg, bs) \
do { \
unsigned int tv = MSDC_READ32(reg);\
tv &= ~((u32)(bs)); \
MSDC_WRITE32(reg, tv); \
} while (0)
#define MSDC_SET_FIELD(reg, field, val) \
do { \
unsigned int tv = MSDC_READ32(reg); \
tv &= ~(field); \
tv |= ((val) << (uffs((unsigned int)field) - 1)); \
MSDC_WRITE32(reg, tv); \
} while (0)
#define MSDC_GET_FIELD(reg, field, val) \
do { \
unsigned int tv = MSDC_READ32(reg); \
val = ((tv & (field)) >> (uffs((unsigned int)field) - 1)); \
} while (0)
#define GET_FIELD(reg, field_shift, field_mask, val) \
(val = (reg >> field_shift) & field_mask)
struct mt_gpdma_desc {
u32 gpd_info;
#define GPDMA_DESC_HWO (0x1 << 0)
#define GPDMA_DESC_BDP (0x1 << 1)
#define GPDMA_DESC_CHECKSUM (0xff << 8) /* bit8 ~ bit15 */
#define GPDMA_DESC_INT (0x1 << 16)
#define GPDMA_DESC_NEXT_H4 (0xf << 24)
#define GPDMA_DESC_PTR_H4 (0xf << 28)
u32 next;
u32 ptr;
u32 gpd_data_len;
#define GPDMA_DESC_BUFLEN (0xffff) /* bit0 ~ bit15 */
#define GPDMA_DESC_EXTLEN (0xff << 16) /* bit16 ~ bit23 */
u32 arg;
u32 blknum;
u32 cmd;
};
struct mt_bdma_desc {
u32 bd_info;
#define BDMA_DESC_EOL (0x1 << 0)
#define BDMA_DESC_CHECKSUM (0xff << 8) /* bit8 ~ bit15 */
#define BDMA_DESC_BLKPAD (0x1 << 17)
#define BDMA_DESC_DWPAD (0x1 << 18)
#define BDMA_DESC_NEXT_H4 (0xf << 24)
#define BDMA_DESC_PTR_H4 (0xf << 28)
u32 next;
u32 ptr;
u32 bd_data_len;
#define BDMA_DESC_BUFLEN (0xffff) /* bit0 ~ bit15 */
#define BDMA_DESC_BUFLEN_EXT (0xffffff) /* bit0 ~ bit23 */
};
struct msdc_dma {
struct scatterlist *sg; /* I/O scatter list */
struct mt_gpdma_desc *gpd; /* pointer to gpd array */
struct mt_bdma_desc *bd; /* pointer to bd array */
dma_addr_t gpd_addr; /* the physical address of gpd array */
dma_addr_t bd_addr; /* the physical address of bd array */
};
struct msdc_save_para {
u32 msdc_cfg;
u32 iocon;
u32 sdc_cfg;
u32 pad_tune;
u32 patch_bit0;
u32 patch_bit1;
u32 patch_bit2;
u32 pad_ds_tune;
u32 pad_cmd_tune;
u32 emmc50_cfg0;
u32 emmc50_cfg3;
u32 sdc_fifo_cfg;
u32 emmc_top_control;
u32 emmc_top_cmd;
u32 emmc50_pad_ds_tune;
};
struct msdc_tune_para {
u32 iocon;
u32 pad_tune;
u32 pad_cmd_tune;
u32 emmc_top_control;
u32 emmc_top_cmd;
};
struct msdc_host {
struct device *dev;
const struct mtk_mmc_compatible *dev_comp;
struct mmc_host *mmc; /* mmc structure */
int cmd_rsp;
spinlock_t lock;
struct mmc_request *mrq;
struct mmc_command *cmd;
struct mmc_data *data;
int error;
void __iomem *base; /* host base address */
void __iomem *top_base; /* host top register base address */
struct msdc_dma dma; /* dma channel */
u64 dma_mask;
u32 timeout_ns; /* data timeout ns */
u32 timeout_clks; /* data timeout clks */
struct pinctrl *pinctrl;
struct pinctrl_state *pins_default;
struct pinctrl_state *pins_uhs;
struct pinctrl_state *pins_pull_down;
struct delayed_work req_timeout;
int irq; /* host interrupt */
struct clk *src_clk; /* msdc source clock */
struct clk *h_clk; /* msdc h_clk */
struct clk *bus_clk; /* bus clock which used to access register */
struct clk *src_clk_cg; /* msdc source clock control gate */
struct clk *crypto_clk; /* msdc crypto clock */
void __iomem *crypto_clk_base; /*dbg use: for dump aes clk cg*/
u32 mclk; /* mmc subsystem clock frequency */
u32 src_clk_freq; /* source clock frequency */
#ifdef CONFIG_MACH_MT8173
u32 sclk; /* SD/MS bus clock frequency */
#endif
unsigned char timing;
bool vqmmc_enabled;
#ifdef CONFIG_MACH_MT8173
u32 host_id;
#endif
u32 latch_ck;
u32 hs400_ds_delay;
u32 hs400_ds_dly3;
u32 hs200_cmd_int_delay; /* cmd internal delay for HS200/SDR104 */
u32 hs400_cmd_int_delay; /* cmd internal delay for HS400 */
#ifdef CONFIG_MACH_MT8173
u32 hs200_cmd_resp_sel; /* cmd response sample selection */
/* valid after tune response && final delay != 0xffffffff */
bool tune_response_valid;
u8 tune_response_delay; /* saved tune response value */
#endif
bool hs400_cmd_resp_sel_rising;
/* cmd response sample selection for HS400 */
bool hs400_mode; /* current eMMC will run at hs400 mode */
bool hs400_tuning; /* hs400 mode online tuning */
bool cqhci; /* support eMMC hw cmdq */
bool is_autok_done;
bool internal_cd; /* Use internal card-detect logic */
bool block_bad_card;
u8 card_inserted; /* the status of card inserted */
int retune_times;
u32 need_tune;
int power_cycle_cnt;
u32 data_timeout_cont; /* data continuous timeout */
struct msdc_save_para save_para; /* used when gate HCLK */
struct msdc_tune_para def_tune_para; /* default tune setting */
struct msdc_tune_para saved_tune_para; /* tune result of CMD21/CMD19 */
struct cqhci_host *cq_host;
#if defined(CONFIG_MACH_MT6768) && defined(CONFIG_MTK_PMQOS)
struct mtk_pm_qos_request pm_qos;
#endif
};
#endif