X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Flinux%2Fmmc%2Fhost.h;h=ec55e25115d191afe5d89ea6cac5b4002e28a197;hb=87145991406facd537f57c9e6bf0809ceddda851;hp=66b4659276026e3769d859573007c2d1f06ac294;hpb=240e7f3ebf06fc651deeb75ea4721796f701b9af;p=firefly-linux-kernel-4.4.55.git diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 66b465927602..ec55e25115d1 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -12,12 +12,14 @@ #include #include +#include #include #include #include -#include #include +#include +#include #include struct mmc_ios { @@ -42,6 +44,7 @@ struct mmc_ios { #define MMC_POWER_OFF 0 #define MMC_POWER_UP 1 #define MMC_POWER_ON 2 +#define MMC_POWER_UNDEFINED 3 unsigned char bus_width; /* data bus width */ @@ -59,13 +62,9 @@ struct mmc_ios { #define MMC_TIMING_UHS_SDR50 5 #define MMC_TIMING_UHS_SDR104 6 #define MMC_TIMING_UHS_DDR50 7 -#define MMC_TIMING_MMC_HS200 8 - -#define MMC_SDR_MODE 0 -#define MMC_1_2V_DDR_MODE 1 -#define MMC_1_8V_DDR_MODE 2 -#define MMC_1_2V_SDR_MODE 3 -#define MMC_1_8V_SDR_MODE 4 +#define MMC_TIMING_MMC_DDR52 8 +#define MMC_TIMING_MMC_HS200 9 +#define MMC_TIMING_MMC_HS400 10 unsigned char signal_voltage; /* signalling voltage (1.8V or 3.3V) */ @@ -82,12 +81,6 @@ struct mmc_ios { }; struct mmc_host_ops { - /* - * 'enable' is called when the host is claimed and 'disable' is called - * when the host is released. 'enable' and 'disable' are deprecated. - */ - int (*enable)(struct mmc_host *host); - int (*disable)(struct mmc_host *host); /* * It is optional for the host to implement pre_req and post_req in * order to support double buffering of requests (prepare one @@ -134,12 +127,27 @@ struct mmc_host_ops { /* Check if the card is pulling dat[0:3] low */ int (*card_busy)(struct mmc_host *host); + int (*set_sdio_status)(struct mmc_host *host, int val); /* The tuning command opcode value is different for SD and eMMC cards */ int (*execute_tuning)(struct mmc_host *host, u32 opcode); - int (*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv); + + /* Prepare HS400 target operating frequency depending host driver */ + int (*prepare_hs400_tuning)(struct mmc_host *host, struct mmc_ios *ios); + /* Prepare enhanced strobe depending host driver */ + int (*prepare_enhanced_strobe)(struct mmc_host *host, bool enable); + int (*select_drive_strength)(struct mmc_card *card, + unsigned int max_dtr, int host_drv, + int card_drv, int *drv_type); void (*hw_reset)(struct mmc_host *host); void (*card_event)(struct mmc_host *host); + + /* + * Optional callback to support controllers with HW issues for multiple + * I/O. Returns the number of supported blocks for the request. + */ + int (*multi_io_quirk)(struct mmc_card *card, + unsigned int direction, int blk_size); }; struct mmc_card; @@ -159,7 +167,6 @@ struct mmc_async_req { * struct mmc_slot - MMC slot functions * * @cd_irq: MMC/SD-card slot hotplug detection IRQ or -EINVAL - * @lock: protect the @handler_priv pointer * @handler_priv: MMC/SD-card slot context * * Some MMC/SD host controllers implement slot-functions like card and @@ -169,7 +176,6 @@ struct mmc_async_req { */ struct mmc_slot { int cd_irq; - struct mutex lock; void *handler_priv; }; @@ -190,6 +196,7 @@ struct mmc_context_info { }; struct regulator; +struct mmc_pwrseq; struct mmc_supply { struct regulator *vmmc; /* Card power supply */ @@ -201,6 +208,7 @@ struct mmc_host { struct device class_dev; int index; const struct mmc_host_ops *ops; + struct mmc_pwrseq *pwrseq; unsigned int f_min; unsigned int f_max; unsigned int f_init; @@ -240,7 +248,7 @@ struct mmc_host { #define MMC_CAP_SPI (1 << 4) /* Talks only SPI protocols */ #define MMC_CAP_NEEDS_POLL (1 << 5) /* Needs polling for card-detection */ #define MMC_CAP_8_BIT_DATA (1 << 6) /* Can the host do 8 bit transfers */ - +#define MMC_CAP_AGGRESSIVE_PM (1 << 7) /* Suspend (e)MMC/SD at idle */ #define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */ #define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */ #define MMC_CAP_ERASE (1 << 10) /* Allow erase/trim commands */ @@ -255,6 +263,7 @@ struct mmc_host { #define MMC_CAP_UHS_SDR50 (1 << 17) /* Host supports UHS SDR50 mode */ #define MMC_CAP_UHS_SDR104 (1 << 18) /* Host supports UHS SDR104 mode */ #define MMC_CAP_UHS_DDR50 (1 << 19) /* Host supports UHS DDR50 mode */ +#define MMC_CAP_RUNTIME_RESUME (1 << 20) /* Resume at runtime_resume. */ #define MMC_CAP_DRIVER_TYPE_A (1 << 23) /* Host supports Driver Type A */ #define MMC_CAP_DRIVER_TYPE_C (1 << 24) /* Host supports Driver Type C */ #define MMC_CAP_DRIVER_TYPE_D (1 << 25) /* Host supports Driver Type D */ @@ -264,16 +273,11 @@ struct mmc_host { u32 caps2; /* More host capabilities */ #define MMC_CAP2_BOOTPART_NOACC (1 << 0) /* Boot partition no access */ -#define MMC_CAP2_CACHE_CTRL (1 << 1) /* Allow cache control */ -#define MMC_CAP2_POWEROFF_NOTIFY (1 << 2) /* Notify poweroff supported */ -#define MMC_CAP2_NO_MULTI_READ (1 << 3) /* Multiblock reads don't work */ -#define MMC_CAP2_NO_SLEEP_CMD (1 << 4) /* Don't allow sleep command */ +#define MMC_CAP2_FULL_PWR_CYCLE (1 << 2) /* Can do full power cycle */ #define MMC_CAP2_HS200_1_8V_SDR (1 << 5) /* can support */ #define MMC_CAP2_HS200_1_2V_SDR (1 << 6) /* can support */ #define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \ MMC_CAP2_HS200_1_2V_SDR) -#define MMC_CAP2_BROKEN_VOLTAGE (1 << 7) /* Use the broken voltage */ -#define MMC_CAP2_DETECT_ON_ERR (1 << 8) /* On I/O err check card removal */ #define MMC_CAP2_HC_ERASE_SZ (1 << 9) /* High-capacity erase size */ #define MMC_CAP2_CD_ACTIVE_HIGH (1 << 10) /* Card-detect signal active high */ #define MMC_CAP2_RO_ACTIVE_HIGH (1 << 11) /* Write-protect signal active high */ @@ -282,20 +286,21 @@ struct mmc_host { #define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ MMC_CAP2_PACKED_WR) #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */ +#define MMC_CAP2_HS400_1_8V (1 << 15) /* Can support HS400 1.8V */ +#define MMC_CAP2_HS400_1_2V (1 << 16) /* Can support HS400 1.2V */ +#define MMC_CAP2_HS400 (MMC_CAP2_HS400_1_8V | \ + MMC_CAP2_HS400_1_2V) +#define MMC_CAP2_HSX00_1_2V (MMC_CAP2_HS200_1_2V_SDR | MMC_CAP2_HS400_1_2V) +#define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17) +#define MMC_CAP2_NO_WRITE_PROTECT (1 << 18) /* No physical write protect pin, assume that card is always read-write */ +#define MMC_CAP2_HS400_ENHANCED_STROBE (1 << 20) /* Host supports enhanced strobe */ mmc_pm_flag_t pm_caps; /* supported pm features */ -#ifdef CONFIG_MMC_CLKGATE - int clk_requests; /* internal reference counter */ - unsigned int clk_delay; /* number of MCI clk hold cycles */ - bool clk_gated; /* clock gated */ - struct delayed_work clk_gate_work; /* delayed clock gate */ - unsigned int clk_old; /* old clock value cache */ - spinlock_t clk_lock; /* lock for clk fields */ - struct mutex clk_gate_mutex; /* mutex for clock gating */ - struct device_attribute clkgate_delay_attr; - unsigned long clkgate_delay; -#endif + u32 restrict_caps; /* Indicate slot specific card type */ +#define RESTRICT_CARD_TYPE_SD (1 << 0) /* Can support Secure-Digital Card */ +#define RESTRICT_CARD_TYPE_SDIO (1 << 1) /* Can support Secure-Digital I/O Card or Combo-Mem */ +#define RESTRICT_CARD_TYPE_EMMC (1 << 2) /* Can support embedded Multi-Media Card */ /* host specific block data */ unsigned int max_seg_size; /* see blk_queue_max_segment_size */ @@ -304,13 +309,12 @@ struct mmc_host { unsigned int max_req_size; /* maximum number of bytes in one req */ unsigned int max_blk_size; /* maximum size of one mmc block */ unsigned int max_blk_count; /* maximum number of blocks in one req */ - unsigned int max_discard_to; /* max. discard timeout in ms */ + unsigned int max_busy_timeout; /* max busy timeout in ms */ /* private data */ spinlock_t lock; /* lock for claim and bus ops */ struct mmc_ios ios; /* current io bus settings */ - u32 ocr; /* the current OCR setting */ /* group bitfields together to minimize padding */ unsigned int use_spi_crc:1; @@ -319,10 +323,20 @@ struct mmc_host { #ifdef CONFIG_MMC_DEBUG unsigned int removed:1; /* host is being removed */ #endif + unsigned int can_retune:1; /* re-tuning can be used */ + unsigned int doing_retune:1; /* re-tuning in progress */ + unsigned int retune_now:1; /* do re-tuning at next req */ int rescan_disable; /* disable card detection */ int rescan_entered; /* used with nonremovable devices */ + int need_retune; /* re-tuning is needed */ + int hold_retune; /* hold off re-tuning */ + unsigned int retune_period; /* re-tuning period in secs */ + struct timer_list retune_timer; /* for periodic re-tuning */ + + bool trigger_card_event; /* card_event necessary */ + struct mmc_card *card; /* device attached to this host */ wait_queue_head_t wq; @@ -330,17 +344,12 @@ struct mmc_host { int claim_cnt; /* "claim" nesting count */ struct delayed_work detect; - struct wake_lock detect_wake_lock; int detect_change; /* card detect flag */ struct mmc_slot slot; const struct mmc_bus_ops *bus_ops; /* current bus driver */ unsigned int bus_refs; /* reference counter */ - unsigned int bus_resume_flags; -#define MMC_BUSRESUME_MANUAL_RESUME (1 << 0) -#define MMC_BUSRESUME_NEEDS_RESUME (1 << 1) - unsigned int sdio_irqs; struct task_struct *sdio_irq_thread; bool sdio_irq_pending; @@ -368,6 +377,9 @@ struct mmc_host { unsigned int slotno; /* used for sdio acpi binding */ + int dsr_req; /* DSR value is valid */ + u32 dsr; /* optional driver stage (DSR) value */ + #ifdef CONFIG_MMC_EMBEDDED_SDIO struct { struct sdio_cis *cis; @@ -384,7 +396,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *); int mmc_add_host(struct mmc_host *); void mmc_remove_host(struct mmc_host *); void mmc_free_host(struct mmc_host *); -void mmc_of_parse(struct mmc_host *host); +int mmc_of_parse(struct mmc_host *host); #ifdef CONFIG_MMC_EMBEDDED_SDIO extern void mmc_set_embedded_sdio_data(struct mmc_host *host, @@ -404,21 +416,6 @@ static inline void *mmc_priv(struct mmc_host *host) #define mmc_dev(x) ((x)->parent) #define mmc_classdev(x) (&(x)->class_dev) #define mmc_hostname(x) (dev_name(&(x)->class_dev)) -#define mmc_bus_needs_resume(host) ((host)->bus_resume_flags & MMC_BUSRESUME_NEEDS_RESUME) -#define mmc_bus_manual_resume(host) ((host)->bus_resume_flags & MMC_BUSRESUME_MANUAL_RESUME) - -static inline void mmc_set_bus_resume_policy(struct mmc_host *host, int manual) -{ - if (manual) - host->bus_resume_flags |= MMC_BUSRESUME_MANUAL_RESUME; - else - host->bus_resume_flags &= ~MMC_BUSRESUME_MANUAL_RESUME; -} - -extern int mmc_resume_bus(struct mmc_host *host); - -int mmc_suspend_host(struct mmc_host *); -int mmc_resume_host(struct mmc_host *); int mmc_power_save_host(struct mmc_host *host); int mmc_power_restore_host(struct mmc_host *host); @@ -426,21 +423,22 @@ int mmc_power_restore_host(struct mmc_host *host); void mmc_detect_change(struct mmc_host *, unsigned long delay); void mmc_request_done(struct mmc_host *, struct mmc_request *); -int mmc_cache_ctrl(struct mmc_host *, u8); - static inline void mmc_signal_sdio_irq(struct mmc_host *host) { host->ops->enable_sdio_irq(host, 0); host->sdio_irq_pending = true; - wake_up_process(host->sdio_irq_thread); + if (host->sdio_irq_thread) + wake_up_process(host->sdio_irq_thread); } +void sdio_run_irqs(struct mmc_host *host); + #ifdef CONFIG_REGULATOR int mmc_regulator_get_ocrmask(struct regulator *supply); int mmc_regulator_set_ocr(struct mmc_host *mmc, struct regulator *supply, unsigned short vdd_bit); -int mmc_regulator_get_supply(struct mmc_host *mmc); +int mmc_regulator_set_vqmmc(struct mmc_host *mmc, struct mmc_ios *ios); #else static inline int mmc_regulator_get_ocrmask(struct regulator *supply) { @@ -454,24 +452,20 @@ static inline int mmc_regulator_set_ocr(struct mmc_host *mmc, return 0; } -static inline int mmc_regulator_get_supply(struct mmc_host *mmc) +static inline int mmc_regulator_set_vqmmc(struct mmc_host *mmc, + struct mmc_ios *ios) { - return 0; + return -EINVAL; } #endif -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); +int mmc_regulator_get_supply(struct mmc_host *mmc); int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *); -/* Module parameter */ -extern bool mmc_assume_removable; - static inline int mmc_card_is_removable(struct mmc_host *host) { - return !(host->caps & MMC_CAP_NONREMOVABLE) && mmc_assume_removable; + return !(host->caps & MMC_CAP_NONREMOVABLE); } static inline int mmc_card_keep_power(struct mmc_host *host) @@ -502,28 +496,64 @@ static inline int mmc_host_uhs(struct mmc_host *host) MMC_CAP_UHS_DDR50); } +static inline int mmc_host_hs400_enhanced_strobe(struct mmc_host *host) +{ + return host->caps2 & MMC_CAP2_HS400_ENHANCED_STROBE; +} + static inline int mmc_host_packed_wr(struct mmc_host *host) { return host->caps2 & MMC_CAP2_PACKED_WR; } -#ifdef CONFIG_MMC_CLKGATE -void mmc_host_clk_hold(struct mmc_host *host); -void mmc_host_clk_release(struct mmc_host *host); -unsigned int mmc_host_clk_rate(struct mmc_host *host); +static inline int mmc_card_hs(struct mmc_card *card) +{ + return card->host->ios.timing == MMC_TIMING_SD_HS || + card->host->ios.timing == MMC_TIMING_MMC_HS; +} -#else -static inline void mmc_host_clk_hold(struct mmc_host *host) +static inline int mmc_card_uhs(struct mmc_card *card) { + return card->host->ios.timing >= MMC_TIMING_UHS_SDR12 && + card->host->ios.timing <= MMC_TIMING_UHS_DDR50; } -static inline void mmc_host_clk_release(struct mmc_host *host) +static inline bool mmc_card_hs200(struct mmc_card *card) { + return card->host->ios.timing == MMC_TIMING_MMC_HS200; } -static inline unsigned int mmc_host_clk_rate(struct mmc_host *host) +static inline bool mmc_card_ddr52(struct mmc_card *card) { - return host->ios.clock; + return card->host->ios.timing == MMC_TIMING_MMC_DDR52; } -#endif + +static inline bool mmc_card_hs400(struct mmc_card *card) +{ + return card->host->ios.timing == MMC_TIMING_MMC_HS400; +} + +static inline bool mmc_card_hs400es(struct mmc_card *card) +{ + if (mmc_card_hs400(card) && + (card->mmc_avail_type & EXT_CSD_CARD_TYPE_HS400ES)) + return 1; + + return 0; +} + +void mmc_retune_timer_stop(struct mmc_host *host); + +static inline void mmc_retune_needed(struct mmc_host *host) +{ + if (host->can_retune) + host->need_retune = 1; +} + +static inline void mmc_retune_recheck(struct mmc_host *host) +{ + if (host->hold_retune <= 1) + host->retune_now = 1; +} + #endif /* LINUX_MMC_HOST_H */