diff options
Diffstat (limited to 'drivers/mmc/host/dw_mmc.h')
| -rw-r--r-- | drivers/mmc/host/dw_mmc.h | 63 |
1 files changed, 59 insertions, 4 deletions
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index da5923a92e60..648b4a5641bf 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -14,7 +14,10 @@ #include <linux/mmc/core.h> #include <linux/dmaengine.h> #include <linux/reset.h> +#include <linux/fault-inject.h> +#include <linux/hrtimer.h> #include <linux/interrupt.h> +#include <linux/workqueue.h> enum dw_mci_state { STATE_IDLE = 0, @@ -87,16 +90,17 @@ struct dw_mci_dma_slave { * @stop_cmdr: Value to be loaded into CMDR when the stop command is * to be sent. * @dir_status: Direction of current transfer. - * @tasklet: Tasklet running the request state machine. + * @bh_work: Work running the request state machine. * @pending_events: Bitmask of events flagged by the interrupt handler - * to be processed by the tasklet. + * to be processed by bh work. * @completed_events: Bitmask of events which the state machine has * processed. - * @state: Tasklet state. + * @state: BH work state. * @queue: List of slots waiting for access to the controller. * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus * rate and timeout calculations. * @current_speed: Configured rate of the controller. + * @minimum_speed: Stored minimum rate of the controller. * @fifoth_val: The value of FIFOTH register. * @verid: Denote Version ID. * @dev: Device associated with the MMC controller. @@ -116,6 +120,7 @@ struct dw_mci_dma_slave { * @part_buf: Simple buffer for partial fifo reads/writes. * @push_data: Pointer to FIFO push function. * @pull_data: Pointer to FIFO pull function. + * @quirks: Set of quirks that apply to specific versions of the IP. * @vqmmc_enabled: Status of vqmmc, should be true or false. * @irq_flags: The flags to be passed to request_irq. * @irq: The irq value to be passed to request_irq. @@ -190,7 +195,7 @@ struct dw_mci { u32 data_status; u32 stop_cmdr; u32 dir_status; - struct tasklet_struct tasklet; + struct work_struct bh_work; unsigned long pending_events; unsigned long completed_events; enum dw_mci_state state; @@ -198,6 +203,7 @@ struct dw_mci { u32 bus_hz; u32 current_speed; + u32 minimum_speed; u32 fifoth_val; u16 verid; struct device *dev; @@ -221,6 +227,7 @@ struct dw_mci { void (*push_data)(struct dw_mci *host, void *buf, int cnt); void (*pull_data)(struct dw_mci *host, void *buf, int cnt); + u32 quirks; bool vqmmc_enabled; unsigned long irq_flags; /* IRQ flags */ int irq; @@ -230,6 +237,11 @@ struct dw_mci { struct timer_list cmd11_timer; struct timer_list cto_timer; struct timer_list dto_timer; + +#ifdef CONFIG_FAULT_INJECTION + struct fault_attr fail_data_crc; + struct hrtimer fault_timer; +#endif }; /* DMA ops for Internal/External DMAC interface */ @@ -267,6 +279,11 @@ struct dw_mci_board { struct dma_pdata *data; }; +/* Support for longer data read timeout */ +#define DW_MMC_QUIRK_EXTENDED_TMOUT BIT(0) +/* Force 32-bit access to the FIFO */ +#define DW_MMC_QUIRK_FIFO64_32 BIT(1) + #define DW_MMC_240A 0x240a #define DW_MMC_280A 0x280a @@ -457,6 +474,31 @@ struct dw_mci_board { #define mci_fifo_writel(__value, __reg) __raw_writel(__reg, __value) #define mci_fifo_writeq(__value, __reg) __raw_writeq(__reg, __value) +/* + * Some dw_mmc devices have 64-bit FIFOs, but expect them to be + * accessed using two 32-bit accesses. If such controller is used + * with a 64-bit kernel, this has to be done explicitly. + */ +static inline u64 mci_fifo_l_readq(void __iomem *addr) +{ + u64 ans; + u32 proxy[2]; + + proxy[0] = mci_fifo_readl(addr); + proxy[1] = mci_fifo_readl(addr + 4); + memcpy(&ans, proxy, 8); + return ans; +} + +static inline void mci_fifo_l_writeq(void __iomem *addr, u64 value) +{ + u32 proxy[2]; + + memcpy(proxy, &value, 8); + mci_fifo_writel(addr, proxy[0]); + mci_fifo_writel(addr + 4, proxy[1]); +} + /* Register access macros */ #define mci_readl(dev, reg) \ readl_relaxed((dev)->regs + SDMMC_##reg) @@ -499,6 +541,9 @@ extern void dw_mci_remove(struct dw_mci *host); #ifdef CONFIG_PM extern int dw_mci_runtime_suspend(struct device *device); extern int dw_mci_runtime_resume(struct device *device); +#else +static inline int dw_mci_runtime_suspend(struct device *device) { return -EOPNOTSUPP; } +static inline int dw_mci_runtime_resume(struct device *device) { return -EOPNOTSUPP; } #endif /** @@ -543,10 +588,15 @@ struct dw_mci_slot { * dw_mci driver data - dw-mshc implementation specific driver data. * @caps: mmc subsystem specified capabilities of the controller(s). * @num_caps: number of capabilities specified by @caps. + * @common_caps: mmc subsystem specified capabilities applicable to all of + * the controllers * @init: early implementation specific initialization. * @set_ios: handle bus specific extensions. * @parse_dt: parse implementation specific device tree properties. * @execute_tuning: implementation specific tuning procedure. + * @set_data_timeout: implementation specific timeout. + * @get_drto_clks: implementation specific cycle count for data read timeout. + * @hw_reset: implementation specific HW reset. * * Provide controller implementation specific extensions. The usage of this * data structure is fully optional and usage of each member in this structure @@ -555,6 +605,7 @@ struct dw_mci_slot { struct dw_mci_drv_data { unsigned long *caps; u32 num_caps; + u32 common_caps; int (*init)(struct dw_mci *host); void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); int (*parse_dt)(struct dw_mci *host); @@ -563,5 +614,9 @@ struct dw_mci_drv_data { struct mmc_ios *ios); int (*switch_voltage)(struct mmc_host *mmc, struct mmc_ios *ios); + void (*set_data_timeout)(struct dw_mci *host, + unsigned int timeout_ns); + u32 (*get_drto_clks)(struct dw_mci *host); + void (*hw_reset)(struct dw_mci *host); }; #endif /* _DW_MMC_H_ */ |
