From d2e1446d81725c351dc73a03b397ce043fb18452 Mon Sep 17 00:00:00 2001 From: Meizu OpenSource Date: Mon, 15 Aug 2016 10:19:42 +0800 Subject: first commit --- include/linux/mmc/host.h | 575 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 575 insertions(+) create mode 100644 include/linux/mmc/host.h (limited to 'include/linux/mmc/host.h') diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h new file mode 100644 index 000000000..9be4a03c5 --- /dev/null +++ b/include/linux/mmc/host.h @@ -0,0 +1,575 @@ +/* + * linux/include/linux/mmc/host.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Host driver specific definitions. + */ +#ifndef LINUX_MMC_HOST_H +#define LINUX_MMC_HOST_H + +#include +#include +#include +#include +#include +#include + +#include +#include + +struct mmc_ios { + unsigned int clock; /* clock rate */ + unsigned short vdd; + +/* vdd stores the bit number of the selected voltage range from below. */ + + unsigned char bus_mode; /* command output mode */ + +#define MMC_BUSMODE_OPENDRAIN 1 +#define MMC_BUSMODE_PUSHPULL 2 + + unsigned char chip_select; /* SPI chip select */ + +#define MMC_CS_DONTCARE 0 +#define MMC_CS_HIGH 1 +#define MMC_CS_LOW 2 + + unsigned char power_mode; /* power supply mode */ + +#define MMC_POWER_OFF 0 +#define MMC_POWER_UP 1 +#define MMC_POWER_ON 2 + + unsigned char bus_width; /* data bus width */ + +#define MMC_BUS_WIDTH_1 0 +#define MMC_BUS_WIDTH_4 2 +#define MMC_BUS_WIDTH_8 3 + + unsigned char timing; /* timing specification used */ + +#define MMC_TIMING_LEGACY 0 +#define MMC_TIMING_MMC_HS 1 +#define MMC_TIMING_SD_HS 2 +#define MMC_TIMING_UHS_SDR12 3 +#define MMC_TIMING_UHS_SDR25 4 +#define MMC_TIMING_UHS_SDR50 5 +#define MMC_TIMING_UHS_SDR104 6 +#define MMC_TIMING_UHS_DDR50 7 +#define MMC_TIMING_MMC_HS200 8 +#ifdef CONFIG_EMMC_50_FEATURE +#define MMC_TIMING_MMC_HS400 9 +#endif + +#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 + + unsigned char signal_voltage; /* signalling voltage (1.8V or 3.3V) */ + +#define MMC_SIGNAL_VOLTAGE_330 0 +#define MMC_SIGNAL_VOLTAGE_180 1 +#define MMC_SIGNAL_VOLTAGE_120 2 + + unsigned char drv_type; /* driver type (A, B, C, D) */ + +#define MMC_SET_DRIVER_TYPE_B 0 +#define MMC_SET_DRIVER_TYPE_A 1 +#define MMC_SET_DRIVER_TYPE_C 2 +#define MMC_SET_DRIVER_TYPE_D 3 +}; + +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 + * request while another request is active). + * pre_req() must always be followed by a post_req(). + * To undo a call made to pre_req(), call post_req() with + * a nonzero err condition. + */ + void (*post_req)(struct mmc_host *host, struct mmc_request *req, + int err); + void (*pre_req)(struct mmc_host *host, struct mmc_request *req, + bool is_first_req); + void (*request)(struct mmc_host *host, struct mmc_request *req); +/*++add tuning for Mediatek MSDC host++*/ + void (*tuning)(struct mmc_host *host, struct mmc_request *req); +/*--add tuning for Mediatek MSDC host--*/ +/*++add send stop for Mediatek MSDC host++*/ + void (*send_stop)(struct mmc_host *host, struct mmc_request *req); +/*--add send stop for Mediatek MSDC host--*/ +/*++add dma error reset for Mediatek MSDC host++*/ + void (*dma_error_reset)(struct mmc_host *host); +/*--add dma error reset for Mediatek MSDC host--*/ +/*++add written data check for Mediatek MSDC host++*/ + bool (*check_written_data)(struct mmc_host *host, struct mmc_request *req); +/*--add written data check for Mediatek MSDC host--*/ + + + /* + * Avoid calling these three functions too often or in a "fast path", + * since underlaying controller might implement them in an expensive + * and/or slow way. + * + * Also note that these functions might sleep, so don't call them + * in the atomic contexts! + * + * Return values for the get_ro callback should be: + * 0 for a read/write card + * 1 for a read-only card + * -ENOSYS when not supported (equal to NULL callback) + * or a negative errno value when something bad happened + * + * Return values for the get_cd callback should be: + * 0 for a absent card + * 1 for a present card + * -ENOSYS when not supported (equal to NULL callback) + * or a negative errno value when something bad happened + */ + void (*set_ios)(struct mmc_host *host, struct mmc_ios *ios); + int (*get_ro)(struct mmc_host *host); + int (*get_cd)(struct mmc_host *host); + + void (*enable_sdio_irq)(struct mmc_host *host, int enable); + + /* optional callback for HC quirks */ + void (*init_card)(struct mmc_host *host, struct mmc_card *card); + + int (*start_signal_voltage_switch)(struct mmc_host *host, struct mmc_ios *ios); + + /* Check if the card is pulling dat[0:3] low */ + int (*card_busy)(struct mmc_host *host); + + /* 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); + void (*hw_reset)(struct mmc_host *host); + void (*card_event)(struct mmc_host *host); +}; + +struct mmc_card; +struct device; + +struct mmc_async_req { + /* active mmc request */ + struct mmc_request *mrq; + /* + * Check error status of completed mmc request. + * Returns 0 if success otherwise non zero. + */ + int (*err_check) (struct mmc_card *, 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 + * write-protect detection natively. However, a large number of controllers + * leave these functions to the CPU. This struct provides a hook to attach + * such slot-function drivers. + */ +struct mmc_slot { + int cd_irq; + struct mutex lock; + void *handler_priv; +}; + +#ifdef CONFIG_MTK_EMMC_CACHE +/** + * struct mmc_flush_ops_info - cache data + * @wq: workqueue + * @idle_time_dw: Idle time flush_ops delayed work + * @time_to_start_flush_ops_ms: The time to start the BKOPs + * delayed work once MMC thread is idle + * @cancel_delayed_work: A flag to indicate if the delayed work + * should be cancelled + */ +struct mmc_flush_info { + struct workqueue_struct *wq; + struct delayed_work idle_time_dw; + unsigned int time_to_start_flush_ms; + bool cancel_delayed_work; + bool work_start; +}; +#endif +/** + * mmc_context_info - synchronization details for mmc context + * @is_done_rcv wake up reason was done request + * @is_new_req wake up reason was new request + * @is_waiting_last_req mmc context waiting for single running request + * @wait wait queue + * @lock lock to protect data fields + */ +struct mmc_context_info { + bool is_done_rcv; + bool is_new_req; + bool is_waiting_last_req; + wait_queue_head_t wait; + spinlock_t lock; +}; + +struct regulator; + +struct mmc_supply { + struct regulator *vmmc; /* Card power supply */ + struct regulator *vqmmc; /* Optional Vccq supply */ +}; + +struct mmc_host { + struct device *parent; + struct device class_dev; + int index; + const struct mmc_host_ops *ops; + unsigned int f_min; + unsigned int f_max; + unsigned int f_init; + u32 ocr_avail; + u32 ocr_avail_sdio; /* SDIO-specific OCR */ + u32 ocr_avail_sd; /* SD-specific OCR */ + u32 ocr_avail_mmc; /* MMC-specific OCR */ + struct notifier_block pm_notify; + u32 max_current_330; + u32 max_current_300; + u32 max_current_180; + +#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */ +#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */ +#define MMC_VDD_21_22 0x00000200 /* VDD voltage 2.1 ~ 2.2 */ +#define MMC_VDD_22_23 0x00000400 /* VDD voltage 2.2 ~ 2.3 */ +#define MMC_VDD_23_24 0x00000800 /* VDD voltage 2.3 ~ 2.4 */ +#define MMC_VDD_24_25 0x00001000 /* VDD voltage 2.4 ~ 2.5 */ +#define MMC_VDD_25_26 0x00002000 /* VDD voltage 2.5 ~ 2.6 */ +#define MMC_VDD_26_27 0x00004000 /* VDD voltage 2.6 ~ 2.7 */ +#define MMC_VDD_27_28 0x00008000 /* VDD voltage 2.7 ~ 2.8 */ +#define MMC_VDD_28_29 0x00010000 /* VDD voltage 2.8 ~ 2.9 */ +#define MMC_VDD_29_30 0x00020000 /* VDD voltage 2.9 ~ 3.0 */ +#define MMC_VDD_30_31 0x00040000 /* VDD voltage 3.0 ~ 3.1 */ +#define MMC_VDD_31_32 0x00080000 /* VDD voltage 3.1 ~ 3.2 */ +#define MMC_VDD_32_33 0x00100000 /* VDD voltage 3.2 ~ 3.3 */ +#define MMC_VDD_33_34 0x00200000 /* VDD voltage 3.3 ~ 3.4 */ +#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */ +#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */ + + u32 caps; /* Host capabilities */ + +#define MMC_CAP_4_BIT_DATA (1 << 0) /* Can the host do 4 bit transfers */ +#define MMC_CAP_MMC_HIGHSPEED (1 << 1) /* Can do MMC high-speed timing */ +#define MMC_CAP_SD_HIGHSPEED (1 << 2) /* Can do SD high-speed timing */ +#define MMC_CAP_SDIO_IRQ (1 << 3) /* Can signal pending SDIO IRQs */ +#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_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 */ +#define MMC_CAP_1_8V_DDR (1 << 11) /* can support */ + /* DDR mode at 1.8V */ +#define MMC_CAP_1_2V_DDR (1 << 12) /* can support */ + /* DDR mode at 1.2V */ +#define MMC_CAP_POWER_OFF_CARD (1 << 13) /* Can power off after boot */ +#define MMC_CAP_BUS_WIDTH_TEST (1 << 14) /* CMD14/CMD19 bus width ok */ +#define MMC_CAP_UHS_SDR12 (1 << 15) /* Host supports UHS SDR12 mode */ +#define MMC_CAP_UHS_SDR25 (1 << 16) /* Host supports UHS SDR25 mode */ +#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_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 */ +#define MMC_CAP_CMD23 (1 << 30) /* CMD23 supported. */ +#define MMC_CAP_HW_RESET (1 << 31) /* Hardware reset */ + + 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_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 */ +#ifdef CONFIG_EMMC_50_FEATURE +#define MMC_CAP2_HS400_1_8V_DDR (1 << 12) /* can support */ +#define MMC_CAP2_HS400_1_2V_DDR (1 << 13) /* can support */ +#define MMC_CAP2_HS400 (MMC_CAP2_HS400_1_8V_DDR | \ + MMC_CAP2_HS400_1_2V_DDR) +#endif +#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_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */ + + 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 + + /* host specific block data */ + unsigned int max_seg_size; /* see blk_queue_max_segment_size */ + unsigned short max_segs; /* see blk_queue_max_segments */ + unsigned short unused; + 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 */ + + /* 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; + unsigned int claimed:1; /* host exclusively claimed */ + unsigned int bus_dead:1; /* bus has been released */ +#ifdef CONFIG_MMC_DEBUG + unsigned int removed:1; /* host is being removed */ +#endif + + int rescan_disable; /* disable card detection */ + int rescan_entered; /* used with nonremovable devices */ + + struct mmc_card *card; /* device attached to this host */ + + wait_queue_head_t wq; + struct task_struct *claimer; /* task that has host claimed */ + 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; + atomic_t sdio_irq_thread_abort; + + mmc_pm_flag_t pm_flags; /* requested pm features */ + + struct led_trigger *led; /* activity led */ + +#ifdef CONFIG_REGULATOR + bool regulator_enabled; /* regulator state */ +#endif + struct mmc_supply supply; + + struct dentry *debugfs_root; + + struct mmc_async_req *areq; /* active async req */ + struct mmc_context_info context_info; /* async synchronization info */ + +#ifdef CONFIG_FAIL_MMC_REQUEST + struct fault_attr fail_mmc_request; +#endif + + unsigned int actual_clock; /* Actual HC clock rate */ + + unsigned int slotno; /* used for sdio acpi binding */ + +#ifdef CONFIG_MMC_EMBEDDED_SDIO + struct { + struct sdio_cis *cis; + struct sdio_cccr *cccr; + struct sdio_embedded_func *funcs; + int num_funcs; + } embedded_sdio_data; +#endif + struct completion card_init_done; + void (*card_init_complete)(struct mmc_host*); + void (*card_init_wait)(struct mmc_host*); +#ifdef CONFIG_MTK_EMMC_CACHE + struct mmc_flush_info flush_info; +#endif + unsigned long private[0] ____cacheline_aligned; +}; + +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); + +#ifdef CONFIG_MMC_EMBEDDED_SDIO +extern void mmc_set_embedded_sdio_data(struct mmc_host *host, + struct sdio_cis *cis, + struct sdio_cccr *cccr, + struct sdio_embedded_func *funcs, + int num_funcs); +#endif + +static inline void *mmc_priv(struct mmc_host *host) +{ + return (void *)host->private; +} + +#define mmc_host_is_spi(host) ((host)->caps & MMC_CAP_SPI) + +#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); + +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); +} + +#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); +#else +static inline int mmc_regulator_get_ocrmask(struct regulator *supply) +{ + return 0; +} + +static inline int mmc_regulator_set_ocr(struct mmc_host *mmc, + struct regulator *supply, + unsigned short vdd_bit) +{ + return 0; +} + +static inline int mmc_regulator_get_supply(struct mmc_host *mmc) +{ + return 0; +} +#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_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; +} + +static inline int mmc_card_keep_power(struct mmc_host *host) +{ + return host->pm_flags & MMC_PM_KEEP_POWER; +} + +static inline int mmc_card_wake_sdio_irq(struct mmc_host *host) +{ + return host->pm_flags & MMC_PM_WAKE_SDIO_IRQ; +} + +static inline int mmc_host_cmd23(struct mmc_host *host) +{ + return host->caps & MMC_CAP_CMD23; +} + +static inline int mmc_boot_partition_access(struct mmc_host *host) +{ + return !(host->caps2 & MMC_CAP2_BOOTPART_NOACC); +} + +static inline int mmc_host_uhs(struct mmc_host *host) +{ + return host->caps & + (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | + MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | + MMC_CAP_UHS_DDR50); +} + +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); + +#else +static inline void mmc_host_clk_hold(struct mmc_host *host) +{ +} + +static inline void mmc_host_clk_release(struct mmc_host *host) +{ +} + +static inline unsigned int mmc_host_clk_rate(struct mmc_host *host) +{ + return host->ios.clock; +} +#endif +#endif /* LINUX_MMC_HOST_H */ -- cgit v1.2.3