提交 bb21deda 编写于 作者: Z zhangguijiang 提交者: Yang Yingliang

EMMC: ascend customized emmc host

ascend inclusion
category: feature
feature: Ascend emmc adaption
bugzilla: https://gitee.com/openeuler/kernel/issues/I4F4LL
CVE: NA

--------------------

To identify Ascend HiSilicon emmc chip, we add a customized property
to dts. In this patch we add an interface to read this property. At
the same time, we provided a switch, which is CONFIG_ASCEND_HISI_MMC,
for you to get rid of our modifications.
Signed-off-by: Nzhangguijiang <zhangguijiang@huawei.com>
Reviewed-by: NDing Tianhong <dingtianhong@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 fd3d7378
...@@ -12,6 +12,16 @@ menuconfig MMC ...@@ -12,6 +12,16 @@ menuconfig MMC
If you want MMC/SD/SDIO support, you should say Y here and If you want MMC/SD/SDIO support, you should say Y here and
also to your specific host controller driver. also to your specific host controller driver.
config ASCEND_HISI_MMC
bool "Ascend HiSilicon MMC card support"
depends on MMC
default n
help
This selects for Hisilicon SoC specific extensions to the
Synopsys DesignWare Memory Card Interface driver.
You should select this option if you want mmc support on
Ascend platform.
if MMC if MMC
source "drivers/mmc/core/Kconfig" source "drivers/mmc/core/Kconfig"
......
...@@ -348,6 +348,11 @@ int mmc_of_parse(struct mmc_host *host) ...@@ -348,6 +348,11 @@ int mmc_of_parse(struct mmc_host *host)
EXPORT_SYMBOL(mmc_of_parse); EXPORT_SYMBOL(mmc_of_parse);
static inline int mmc_is_ascend_hi_mci_1(struct device *dev)
{
return !strncmp(dev_name(dev), "hi_mci.1", strlen("hi_mci.1"));
}
/** /**
* mmc_alloc_host - initialise the per-host structure. * mmc_alloc_host - initialise the per-host structure.
* @extra: sizeof private data structure * @extra: sizeof private data structure
...@@ -374,7 +379,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) ...@@ -374,7 +379,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
} }
host->index = err; host->index = err;
if (mmc_is_ascend_customized(dev)) {
if (mmc_is_ascend_hi_mci_1(dev))
host->index = 1;
}
dev_set_name(&host->class_dev, "mmc%d", host->index); dev_set_name(&host->class_dev, "mmc%d", host->index);
host->parent = dev; host->parent = dev;
...@@ -383,12 +391,13 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) ...@@ -383,12 +391,13 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
device_initialize(&host->class_dev); device_initialize(&host->class_dev);
device_enable_async_suspend(&host->class_dev); device_enable_async_suspend(&host->class_dev);
if (mmc_gpio_alloc(host)) { if (!mmc_is_ascend_customized(host->parent))
put_device(&host->class_dev); if (mmc_gpio_alloc(host)) {
ida_simple_remove(&mmc_host_ida, host->index); put_device(&host->class_dev);
kfree(host); ida_simple_remove(&mmc_host_ida, host->index);
return NULL; kfree(host);
} return NULL;
}
spin_lock_init(&host->lock); spin_lock_init(&host->lock);
init_waitqueue_head(&host->wq); init_waitqueue_head(&host->wq);
...@@ -441,7 +450,9 @@ int mmc_add_host(struct mmc_host *host) ...@@ -441,7 +450,9 @@ int mmc_add_host(struct mmc_host *host)
#endif #endif
mmc_start_host(host); mmc_start_host(host);
mmc_register_pm_notifier(host); if (!mmc_is_ascend_customized(host->parent) ||
!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY))
mmc_register_pm_notifier(host);
return 0; return 0;
} }
...@@ -458,7 +469,9 @@ EXPORT_SYMBOL(mmc_add_host); ...@@ -458,7 +469,9 @@ EXPORT_SYMBOL(mmc_add_host);
*/ */
void mmc_remove_host(struct mmc_host *host) void mmc_remove_host(struct mmc_host *host)
{ {
mmc_unregister_pm_notifier(host); if (!mmc_is_ascend_customized(host->parent) ||
!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY))
mmc_unregister_pm_notifier(host);
mmc_stop_host(host); mmc_stop_host(host);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
...@@ -485,3 +498,19 @@ void mmc_free_host(struct mmc_host *host) ...@@ -485,3 +498,19 @@ void mmc_free_host(struct mmc_host *host)
} }
EXPORT_SYMBOL(mmc_free_host); EXPORT_SYMBOL(mmc_free_host);
int mmc_is_ascend_customized(struct device *dev)
{
#ifdef CONFIG_ASCEND_HISI_MMC
static int is_ascend_customized = -1;
if (is_ascend_customized == -1)
is_ascend_customized = ((dev == NULL) ? 0 :
of_find_property(dev->of_node, "customized", NULL) != NULL);
return is_ascend_customized;
#else
return 0;
#endif
}
EXPORT_SYMBOL(mmc_is_ascend_customized);
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
#include <linux/mmc/pm.h> #include <linux/mmc/pm.h>
#include <linux/dma-direction.h> #include <linux/dma-direction.h>
#include <linux/jiffies.h>
#include <linux/version.h>
struct mmc_ios { struct mmc_ios {
unsigned int clock; /* clock rate */ unsigned int clock; /* clock rate */
unsigned short vdd; unsigned short vdd;
...@@ -63,6 +66,7 @@ struct mmc_ios { ...@@ -63,6 +66,7 @@ struct mmc_ios {
#define MMC_TIMING_MMC_DDR52 8 #define MMC_TIMING_MMC_DDR52 8
#define MMC_TIMING_MMC_HS200 9 #define MMC_TIMING_MMC_HS200 9
#define MMC_TIMING_MMC_HS400 10 #define MMC_TIMING_MMC_HS400 10
#define MMC_TIMING_NEW_SD MMC_TIMING_UHS_SDR12
unsigned char signal_voltage; /* signalling voltage (1.8V or 3.3V) */ unsigned char signal_voltage; /* signalling voltage (1.8V or 3.3V) */
...@@ -78,7 +82,25 @@ struct mmc_ios { ...@@ -78,7 +82,25 @@ struct mmc_ios {
#define MMC_SET_DRIVER_TYPE_D 3 #define MMC_SET_DRIVER_TYPE_D 3
bool enhanced_strobe; /* hs400es selection */ bool enhanced_strobe; /* hs400es selection */
#ifdef CONFIG_ASCEND_HISI_MMC
unsigned int clock_store; /*store the clock before power off*/
#endif
};
#ifdef CONFIG_ASCEND_HISI_MMC
struct mmc_cmdq_host_ops {
int (*enable)(struct mmc_host *mmc);
int (*disable)(struct mmc_host *mmc, bool soft);
int (*restore_irqs)(struct mmc_host *mmc);
int (*request)(struct mmc_host *mmc, struct mmc_request *mrq);
int (*halt)(struct mmc_host *mmc, bool halt);
void (*post_req)(struct mmc_host *mmc, struct mmc_request *mrq,
int err);
void (*disable_immediately)(struct mmc_host *mmc);
int (*clear_and_halt)(struct mmc_host *mmc);
}; };
#endif
struct mmc_host; struct mmc_host;
...@@ -168,6 +190,12 @@ struct mmc_host_ops { ...@@ -168,6 +190,12 @@ struct mmc_host_ops {
*/ */
int (*multi_io_quirk)(struct mmc_card *card, int (*multi_io_quirk)(struct mmc_card *card,
unsigned int direction, int blk_size); unsigned int direction, int blk_size);
#ifdef CONFIG_ASCEND_HISI_MMC
/* Slow down clk for ascend chip SD cards */
void (*slowdown_clk)(struct mmc_host *host, int timing);
int (*enable_enhanced_strobe)(struct mmc_host *host);
int (*send_cmd_direct)(struct mmc_host *host, struct mmc_request *mrq);
#endif
}; };
struct mmc_cqe_ops { struct mmc_cqe_ops {
...@@ -255,6 +283,30 @@ struct mmc_context_info { ...@@ -255,6 +283,30 @@ struct mmc_context_info {
wait_queue_head_t wait; wait_queue_head_t wait;
}; };
#ifdef CONFIG_ASCEND_HISI_MMC
/**
* mmc_cmdq_context_info - describes the contexts of cmdq
* @active_reqs requests being processed
* @active_dcmd dcmd in progress, don't issue any
* more dcmd requests
* @rpmb_in_wait do not pull any more reqs till rpmb is handled
* @cmdq_state state of cmdq engine
* @req_starved completion should invoke the request_fn since
* no tags were available
* @cmdq_ctx_lock acquire this before accessing this structure
*/
struct mmc_cmdq_context_info {
unsigned long active_reqs; /* in-flight requests */
bool active_dcmd;
bool rpmb_in_wait;
unsigned long curr_state;
/* no free tag available */
unsigned long req_starved;
spinlock_t cmdq_ctx_lock;
};
#endif
struct regulator; struct regulator;
struct mmc_pwrseq; struct mmc_pwrseq;
...@@ -328,6 +380,9 @@ struct mmc_host { ...@@ -328,6 +380,9 @@ struct mmc_host {
#define MMC_CAP_UHS_SDR50 (1 << 18) /* Host supports UHS SDR50 mode */ #define MMC_CAP_UHS_SDR50 (1 << 18) /* Host supports UHS SDR50 mode */
#define MMC_CAP_UHS_SDR104 (1 << 19) /* Host supports UHS SDR104 mode */ #define MMC_CAP_UHS_SDR104 (1 << 19) /* Host supports UHS SDR104 mode */
#define MMC_CAP_UHS_DDR50 (1 << 20) /* Host supports UHS DDR50 mode */ #define MMC_CAP_UHS_DDR50 (1 << 20) /* Host supports UHS DDR50 mode */
#ifdef CONFIG_ASCEND_HISI_MMC
#define MMC_CAP_RUNTIME_RESUME (1 << 20) /* Resume at runtime_resume. */
#endif
#define MMC_CAP_UHS (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | \ #define MMC_CAP_UHS (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | \
MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | \ MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | \
MMC_CAP_UHS_DDR50) MMC_CAP_UHS_DDR50)
...@@ -367,6 +422,34 @@ struct mmc_host { ...@@ -367,6 +422,34 @@ struct mmc_host {
#define MMC_CAP2_CQE (1 << 23) /* Has eMMC command queue engine */ #define MMC_CAP2_CQE (1 << 23) /* Has eMMC command queue engine */
#define MMC_CAP2_CQE_DCMD (1 << 24) /* CQE can issue a direct command */ #define MMC_CAP2_CQE_DCMD (1 << 24) /* CQE can issue a direct command */
#define MMC_CAP2_AVOID_3_3V (1 << 25) /* Host must negotiate down from 3.3V */ #define MMC_CAP2_AVOID_3_3V (1 << 25) /* Host must negotiate down from 3.3V */
#ifdef CONFIG_ASCEND_HISI_MMC
#define MMC_CAP2_CACHE_CTRL (1 << 1) /* Allow cache control */
#define MMC_CAP2_NO_MULTI_READ (1 << 3) /* Multiblock read don't work */
#define MMC_CAP2_NO_SLEEP_CMD (1 << 4) /* Don't allow sleep command */
#define MMC_CAP2_BROKEN_VOLTAGE (1 << 7) /* Use the broken voltage */
#define MMC_CAP2_DETECT_ON_ERR (1 << 8) /* I/O err check card removal */
#define MMC_CAP2_HC_ERASE_SZ (1 << 9) /* High-capacity erase size */
#define MMC_CAP2_PACKED_RD (1 << 12) /* Allow packed read */
#define MMC_CAP2_PACKED_WR (1 << 13) /* Allow packed write */
#define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \
MMC_CAP2_PACKED_WR)
#define MMC_CAP2_CMD_QUEUE (1 << 18) /* support eMMC command queue */
#define MMC_CAP2_ENHANCED_STROBE (1 << 19)
#define MMC_CAP2_CACHE_FLUSH_BARRIER (1 << 20)
/* Allow background operations auto enable control */
#define MMC_CAP2_BKOPS_AUTO_CTRL (1 << 21)
/* Allow background operations manual enable control */
#define MMC_CAP2_BKOPS_MANUAL_CTRL (1 << 22)
/* host is connected by via modem through sdio */
#define MMC_CAP2_SUPPORT_VIA_MODEM (1 << 26)
/* host is connected by wifi through sdio */
#define MMC_CAP2_SUPPORT_WIFI (1 << 27)
/* host is connected to 1102 wifi */
#define MMC_CAP2_SUPPORT_WIFI_CMD11 (1 << 28)
/* host do not support low power for wifi*/
#define MMC_CAP2_WIFI_NO_LOWPWR (1 << 29)
#endif
int fixed_drv_type; /* fixed driver type for non-removable media */ int fixed_drv_type; /* fixed driver type for non-removable media */
...@@ -460,6 +543,12 @@ struct mmc_host { ...@@ -460,6 +543,12 @@ struct mmc_host {
bool cqe_on; bool cqe_on;
unsigned long private[0] ____cacheline_aligned; unsigned long private[0] ____cacheline_aligned;
#ifdef CONFIG_ASCEND_HISI_MMC
const struct mmc_cmdq_host_ops *cmdq_ops;
int sdio_present;
unsigned int cmdq_slots;
struct mmc_cmdq_context_info cmdq_ctx;
#endif
}; };
struct device_node; struct device_node;
...@@ -587,4 +676,30 @@ static inline enum dma_data_direction mmc_get_dma_dir(struct mmc_data *data) ...@@ -587,4 +676,30 @@ static inline enum dma_data_direction mmc_get_dma_dir(struct mmc_data *data)
int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error); int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error);
int mmc_abort_tuning(struct mmc_host *host, u32 opcode); int mmc_abort_tuning(struct mmc_host *host, u32 opcode);
#ifdef CONFIG_ASCEND_HISI_MMC
int mmc_cache_ctrl(struct mmc_host *host, u8 enable);
int mmc_card_awake(struct mmc_host *host);
int mmc_card_sleep(struct mmc_host *host);
int mmc_card_can_sleep(struct mmc_host *host);
#else
static inline int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
{
return 0;
}
static inline int mmc_card_awake(struct mmc_host *host)
{
return 0;
}
static inline int mmc_card_sleep(struct mmc_host *host)
{
return 0;
}
static inline int mmc_card_can_sleep(struct mmc_host *host)
{
return 0;
}
#endif
int mmc_is_ascend_customized(struct device *dev);
#endif /* LINUX_MMC_HOST_H */ #endif /* LINUX_MMC_HOST_H */
...@@ -26,5 +26,6 @@ typedef unsigned int mmc_pm_flag_t; ...@@ -26,5 +26,6 @@ typedef unsigned int mmc_pm_flag_t;
#define MMC_PM_KEEP_POWER (1 << 0) /* preserve card power during suspend */ #define MMC_PM_KEEP_POWER (1 << 0) /* preserve card power during suspend */
#define MMC_PM_WAKE_SDIO_IRQ (1 << 1) /* wake up host system on SDIO IRQ assertion */ #define MMC_PM_WAKE_SDIO_IRQ (1 << 1) /* wake up host system on SDIO IRQ assertion */
#define MMC_PM_IGNORE_PM_NOTIFY (1 << 2) /* ignore mmc pm notify */
#endif /* LINUX_MMC_PM_H */ #endif /* LINUX_MMC_PM_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册