diff options
Diffstat (limited to 'drivers/mmc/host/sdhci.h')
-rw-r--r-- | drivers/mmc/host/sdhci.h | 152 |
1 files changed, 148 insertions, 4 deletions
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 0115e9907bf8..300be7fd0f24 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -17,7 +17,7 @@ #include <linux/compiler.h> #include <linux/types.h> #include <linux/io.h> - +#include <linux/ratelimit.h> #include <linux/mmc/host.h> /* @@ -137,22 +137,32 @@ #define SDHCI_INT_DATA_CRC 0x00200000 #define SDHCI_INT_DATA_END_BIT 0x00400000 #define SDHCI_INT_BUS_POWER 0x00800000 -#define SDHCI_INT_ACMD12ERR 0x01000000 +#define SDHCI_INT_AUTO_CMD_ERR 0x01000000 #define SDHCI_INT_ADMA_ERROR 0x02000000 #define SDHCI_INT_NORMAL_MASK 0x00007FFF #define SDHCI_INT_ERROR_MASK 0xFFFF8000 #define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \ - SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX) + SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX | \ + SDHCI_INT_AUTO_CMD_ERR) + #define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | \ SDHCI_INT_BLK_GAP) + +#define SDHCI_INT_CMDQ_EN (0x1 << 14) #define SDHCI_INT_ALL_MASK ((unsigned int)-1) -#define SDHCI_ACMD12_ERR 0x3C +#define SDHCI_AUTO_CMD_ERR 0x3C +#define SDHCI_AUTO_CMD12_NOT_EXEC 0x0001 +#define SDHCI_AUTO_CMD_TIMEOUT_ERR 0x0002 +#define SDHCI_AUTO_CMD_CRC_ERR 0x0004 +#define SDHCI_AUTO_CMD_ENDBIT_ERR 0x0008 +#define SDHCI_AUTO_CMD_INDEX_ERR 0x0010 +#define SDHCI_AUTO_CMD12_NOT_ISSUED 0x0080 #define SDHCI_HOST_CONTROL2 0x3E #define SDHCI_CTRL_UHS_MASK 0x0007 @@ -170,6 +180,7 @@ #define SDHCI_CTRL_DRV_TYPE_D 0x0030 #define SDHCI_CTRL_EXEC_TUNING 0x0040 #define SDHCI_CTRL_TUNED_CLK 0x0080 +#define SDHCI_CTRL_ASYNC_INT_ENABLE 0x4000 #define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000 #define SDHCI_CAPABILITIES 0x40 @@ -190,6 +201,7 @@ #define SDHCI_CAN_VDD_300 0x02000000 #define SDHCI_CAN_VDD_180 0x04000000 #define SDHCI_CAN_64BIT 0x10000000 +#define SDHCI_CAN_ASYNC_INT 0x20000000 #define SDHCI_SUPPORT_SDR50 0x00000001 #define SDHCI_SUPPORT_SDR104 0x00000002 @@ -320,6 +332,12 @@ enum sdhci_cookie { COOKIE_GIVEN, }; +enum sdhci_power_policy { + SDHCI_PERFORMANCE_MODE, + SDHCI_POWER_SAVE_MODE, + SDHCI_POWER_POLICY_NUM /* Always keep this one last */ +}; + struct sdhci_host { /* Data set by hardware interface driver */ const char *hw_name; /* Hardware bus name */ @@ -423,6 +441,84 @@ struct sdhci_host { */ #define SDHCI_QUIRK2_NEED_DELAY_AFTER_INT_CLK_RST (1<<16) +/* + * Read Transfer Active/ Write Transfer Active may be not + * de-asserted after end of transaction. Issue reset for DAT line. + */ +#define SDHCI_QUIRK2_RDWR_TX_ACTIVE_EOT (1<<17) +/* + * Slow interrupt clearance at 400KHz may cause + * host controller driver interrupt handler to + * be called twice. + */ +#define SDHCI_QUIRK2_SLOW_INT_CLR (1<<18) + +/* + * If the base clock can be scalable, then there should be no further + * clock dividing as the input clock itself will be scaled down to + * required frequency. + */ +#define SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK (1<<19) + +/* + * Ignore data timeout error for R1B commands as there will be no + * data associated and the busy timeout value for these commands + * could be lager than the maximum timeout value that controller + * can handle. + */ +#define SDHCI_QUIRK2_IGNORE_DATATOUT_FOR_R1BCMD (1<<20) + +/* + * The preset value registers are not properly initialized by + * some hardware and hence preset value must not be enabled for + * such controllers. + */ +#define SDHCI_QUIRK2_BROKEN_PRESET_VALUE (1<<21) +/* + * Some controllers define the usage of 0xF in data timeout counter + * register (0x2E) which is actually a reserved bit as per + * specification. + */ +#define SDHCI_QUIRK2_USE_RESERVED_MAX_TIMEOUT (1<<22) +/* + * This is applicable for controllers that advertize timeout clock + * value in capabilities register (bit 5-0) as just 50MHz whereas the + * base clock frequency is 200MHz. So, the controller internally + * multiplies the value in timeout control register by 4 with the + * assumption that driver always uses fixed timeout clock value from + * capabilities register to calculate the timeout. But when the driver + * uses SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK base clock frequency is directly + * controller by driver and it's rate varies upto max. 200MHz. This new quirk + * will be used in such cases to avoid controller mulplication when timeout is + * calculated based on the base clock. + */ +#define SDHCI_QUIRK2_DIVIDE_TOUT_BY_4 (1 << 23) + +/* + * Some SDHC controllers are unable to handle data-end bit error in + * 1-bit mode of SDIO. + */ +#define SDHCI_QUIRK2_IGN_DATA_END_BIT_ERROR (1<<24) + +/* Controller has nonstandard clock management */ +#define SDHCI_QUIRK_NONSTANDARD_CLOCK (1<<25) +/* Use reset workaround in case sdhci reset timeouts */ +#define SDHCI_QUIRK2_USE_RESET_WORKAROUND (1<<26) +/* Some controllers doesn't have have any LED control */ +#define SDHCI_QUIRK2_BROKEN_LED_CONTROL (1<<27) +/* + * Some controllers doesn't follow the tuning procedure as defined in spec. + * The tuning data has to be compared from SW driver to validate the correct + * phase. + */ +#define SDHCI_QUIRK2_NON_STANDARD_TUNING (1 << 28) +/* + * Some controllers may use PIO mode to workaround HW issues in ADMA for + * eMMC tuning commands. + */ +#define SDHCI_QUIRK2_USE_PIO_FOR_EMMC_TUNING (1 << 23) + + int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ @@ -432,6 +528,7 @@ struct sdhci_host { struct mmc_host *mmc; /* MMC structure */ struct mmc_host_ops mmc_host_ops; /* MMC host ops */ u64 dma_mask; /* custom DMA mask */ + u64 coherent_dma_mask; #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) struct led_classdev led; /* LED control */ @@ -453,6 +550,7 @@ struct sdhci_host { #define SDHCI_SDR104_NEEDS_TUNING (1<<10) /* SDR104/HS200 needs tuning */ #define SDHCI_USE_64_BIT_DMA (1<<12) /* Use 64-bit DMA */ #define SDHCI_HS400_TUNING (1<<13) /* Tuning for HS400 */ +#define SDHCI_HOST_IRQ_STATUS (1<<14) /* host->irq status */ unsigned int version; /* SDHCI spec. version */ @@ -466,6 +564,7 @@ struct sdhci_host { bool runtime_suspended; /* Host is runtime suspended */ bool bus_on; /* Bus power prevents runtime suspend */ bool preset_enabled; /* Preset is enabled */ + bool cdr_support; struct mmc_request *mrq; /* Current request */ struct mmc_command *cmd; /* Current command */ @@ -514,6 +613,20 @@ struct sdhci_host { unsigned int tuning_count; /* Timer count for re-tuning */ unsigned int tuning_mode; /* Re-tuning mode supported by host */ #define SDHCI_TUNING_MODE_1 0 + ktime_t data_start_time; + + enum sdhci_power_policy power_policy; + + bool is_crypto_en; + bool crypto_reset_reqd; + bool sdio_irq_async_status; + + u32 auto_cmd_err_sts; + struct ratelimit_state dbg_dump_rs; + struct cmdq_host *cq_host; + int reset_wa_applied; /* reset workaround status */ + ktime_t reset_wa_t; /* time when the reset workaround is applied */ + int reset_wa_cnt; /* total number of times workaround is used */ unsigned long private[0] ____cacheline_aligned; }; @@ -543,16 +656,46 @@ struct sdhci_ops { unsigned int (*get_ro)(struct sdhci_host *host); void (*reset)(struct sdhci_host *host, u8 mask); int (*platform_execute_tuning)(struct sdhci_host *host, u32 opcode); + int (*crypto_engine_cfg)(struct sdhci_host *host, + struct mmc_request *mrq, u32 slot); + int (*crypto_engine_cmdq_cfg)(struct sdhci_host *host, + struct mmc_request *mrq, u32 slot, u64 *ice_ctx); + int (*crypto_engine_cfg_end)(struct sdhci_host *host, + struct mmc_request *mrq); + int (*crypto_engine_reset)(struct sdhci_host *host); + void (*crypto_cfg_reset)(struct sdhci_host *host, unsigned int slot); void (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs); void (*hw_reset)(struct sdhci_host *host); void (*adma_workaround)(struct sdhci_host *host, u32 intmask); + unsigned int (*get_max_segments)(void); void (*platform_init)(struct sdhci_host *host); +#define REQ_BUS_OFF (1 << 0) +#define REQ_BUS_ON (1 << 1) +#define REQ_IO_LOW (1 << 2) +#define REQ_IO_HIGH (1 << 3) void (*card_event)(struct sdhci_host *host); + int (*enhanced_strobe)(struct sdhci_host *host); + void (*platform_bus_voting)(struct sdhci_host *host, u32 enable); + void (*check_power_status)(struct sdhci_host *host, u32 req_type); + int (*config_auto_tuning_cmd)(struct sdhci_host *host, + bool enable, + u32 type); + int (*enable_controller_clock)(struct sdhci_host *host); + void (*clear_set_dumpregs)(struct sdhci_host *host, bool set); + void (*enhanced_strobe_mask)(struct sdhci_host *host, bool set); + void (*dump_vendor_regs)(struct sdhci_host *host); + void (*toggle_cdr)(struct sdhci_host *host, bool enable); void (*voltage_switch)(struct sdhci_host *host); int (*select_drive_strength)(struct sdhci_host *host, struct mmc_card *card, unsigned int max_dtr, int host_drv, int card_drv, int *drv_type); + int (*notify_load)(struct sdhci_host *host, enum mmc_load state); + void (*reset_workaround)(struct sdhci_host *host, u32 enable); + void (*init)(struct sdhci_host *host); + void (*pre_req)(struct sdhci_host *host, struct mmc_request *req); + void (*post_req)(struct sdhci_host *host, struct mmc_request *req); + unsigned int (*get_current_limit)(struct sdhci_host *host); }; #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS @@ -672,4 +815,5 @@ extern int sdhci_runtime_suspend_host(struct sdhci_host *host); extern int sdhci_runtime_resume_host(struct sdhci_host *host); #endif +void sdhci_cfg_irq(struct sdhci_host *host, bool enable, bool sync); #endif /* __SDHCI_HW_H */ |