162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Synopsys DesignWare Multimedia Card Interface driver 462306a36Sopenharmony_ci * (Based on NXP driver for lpc 31xx) 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2009 NXP Semiconductors 762306a36Sopenharmony_ci * Copyright (C) 2009, 2010 Imagination Technologies Ltd. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#ifndef _DW_MMC_H_ 1162306a36Sopenharmony_ci#define _DW_MMC_H_ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/scatterlist.h> 1462306a36Sopenharmony_ci#include <linux/mmc/core.h> 1562306a36Sopenharmony_ci#include <linux/dmaengine.h> 1662306a36Sopenharmony_ci#include <linux/reset.h> 1762306a36Sopenharmony_ci#include <linux/fault-inject.h> 1862306a36Sopenharmony_ci#include <linux/hrtimer.h> 1962306a36Sopenharmony_ci#include <linux/interrupt.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cienum dw_mci_state { 2262306a36Sopenharmony_ci STATE_IDLE = 0, 2362306a36Sopenharmony_ci STATE_SENDING_CMD, 2462306a36Sopenharmony_ci STATE_SENDING_DATA, 2562306a36Sopenharmony_ci STATE_DATA_BUSY, 2662306a36Sopenharmony_ci STATE_SENDING_STOP, 2762306a36Sopenharmony_ci STATE_DATA_ERROR, 2862306a36Sopenharmony_ci STATE_SENDING_CMD11, 2962306a36Sopenharmony_ci STATE_WAITING_CMD11_DONE, 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cienum { 3362306a36Sopenharmony_ci EVENT_CMD_COMPLETE = 0, 3462306a36Sopenharmony_ci EVENT_XFER_COMPLETE, 3562306a36Sopenharmony_ci EVENT_DATA_COMPLETE, 3662306a36Sopenharmony_ci EVENT_DATA_ERROR, 3762306a36Sopenharmony_ci}; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cienum dw_mci_cookie { 4062306a36Sopenharmony_ci COOKIE_UNMAPPED, 4162306a36Sopenharmony_ci COOKIE_PRE_MAPPED, /* mapped by pre_req() of dwmmc */ 4262306a36Sopenharmony_ci COOKIE_MAPPED, /* mapped by prepare_data() of dwmmc */ 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistruct mmc_data; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cienum { 4862306a36Sopenharmony_ci TRANS_MODE_PIO = 0, 4962306a36Sopenharmony_ci TRANS_MODE_IDMAC, 5062306a36Sopenharmony_ci TRANS_MODE_EDMAC 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistruct dw_mci_dma_slave { 5462306a36Sopenharmony_ci struct dma_chan *ch; 5562306a36Sopenharmony_ci enum dma_transfer_direction direction; 5662306a36Sopenharmony_ci}; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/** 5962306a36Sopenharmony_ci * struct dw_mci - MMC controller state shared between all slots 6062306a36Sopenharmony_ci * @lock: Spinlock protecting the queue and associated data. 6162306a36Sopenharmony_ci * @irq_lock: Spinlock protecting the INTMASK setting. 6262306a36Sopenharmony_ci * @regs: Pointer to MMIO registers. 6362306a36Sopenharmony_ci * @fifo_reg: Pointer to MMIO registers for data FIFO 6462306a36Sopenharmony_ci * @sg: Scatterlist entry currently being processed by PIO code, if any. 6562306a36Sopenharmony_ci * @sg_miter: PIO mapping scatterlist iterator. 6662306a36Sopenharmony_ci * @mrq: The request currently being processed on @slot, 6762306a36Sopenharmony_ci * or NULL if the controller is idle. 6862306a36Sopenharmony_ci * @cmd: The command currently being sent to the card, or NULL. 6962306a36Sopenharmony_ci * @data: The data currently being transferred, or NULL if no data 7062306a36Sopenharmony_ci * transfer is in progress. 7162306a36Sopenharmony_ci * @stop_abort: The command currently prepared for stoping transfer. 7262306a36Sopenharmony_ci * @prev_blksz: The former transfer blksz record. 7362306a36Sopenharmony_ci * @timing: Record of current ios timing. 7462306a36Sopenharmony_ci * @use_dma: Which DMA channel is in use for the current transfer, zero 7562306a36Sopenharmony_ci * denotes PIO mode. 7662306a36Sopenharmony_ci * @using_dma: Whether DMA is in use for the current transfer. 7762306a36Sopenharmony_ci * @dma_64bit_address: Whether DMA supports 64-bit address mode or not. 7862306a36Sopenharmony_ci * @sg_dma: Bus address of DMA buffer. 7962306a36Sopenharmony_ci * @sg_cpu: Virtual address of DMA buffer. 8062306a36Sopenharmony_ci * @dma_ops: Pointer to platform-specific DMA callbacks. 8162306a36Sopenharmony_ci * @cmd_status: Snapshot of SR taken upon completion of the current 8262306a36Sopenharmony_ci * @ring_size: Buffer size for idma descriptors. 8362306a36Sopenharmony_ci * command. Only valid when EVENT_CMD_COMPLETE is pending. 8462306a36Sopenharmony_ci * @dms: structure of slave-dma private data. 8562306a36Sopenharmony_ci * @phy_regs: physical address of controller's register map 8662306a36Sopenharmony_ci * @data_status: Snapshot of SR taken upon completion of the current 8762306a36Sopenharmony_ci * data transfer. Only valid when EVENT_DATA_COMPLETE or 8862306a36Sopenharmony_ci * EVENT_DATA_ERROR is pending. 8962306a36Sopenharmony_ci * @stop_cmdr: Value to be loaded into CMDR when the stop command is 9062306a36Sopenharmony_ci * to be sent. 9162306a36Sopenharmony_ci * @dir_status: Direction of current transfer. 9262306a36Sopenharmony_ci * @tasklet: Tasklet running the request state machine. 9362306a36Sopenharmony_ci * @pending_events: Bitmask of events flagged by the interrupt handler 9462306a36Sopenharmony_ci * to be processed by the tasklet. 9562306a36Sopenharmony_ci * @completed_events: Bitmask of events which the state machine has 9662306a36Sopenharmony_ci * processed. 9762306a36Sopenharmony_ci * @state: Tasklet state. 9862306a36Sopenharmony_ci * @queue: List of slots waiting for access to the controller. 9962306a36Sopenharmony_ci * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus 10062306a36Sopenharmony_ci * rate and timeout calculations. 10162306a36Sopenharmony_ci * @current_speed: Configured rate of the controller. 10262306a36Sopenharmony_ci * @minimum_speed: Stored minimum rate of the controller. 10362306a36Sopenharmony_ci * @fifoth_val: The value of FIFOTH register. 10462306a36Sopenharmony_ci * @verid: Denote Version ID. 10562306a36Sopenharmony_ci * @dev: Device associated with the MMC controller. 10662306a36Sopenharmony_ci * @pdata: Platform data associated with the MMC controller. 10762306a36Sopenharmony_ci * @drv_data: Driver specific data for identified variant of the controller 10862306a36Sopenharmony_ci * @priv: Implementation defined private data. 10962306a36Sopenharmony_ci * @biu_clk: Pointer to bus interface unit clock instance. 11062306a36Sopenharmony_ci * @ciu_clk: Pointer to card interface unit clock instance. 11162306a36Sopenharmony_ci * @slot: Slots sharing this MMC controller. 11262306a36Sopenharmony_ci * @fifo_depth: depth of FIFO. 11362306a36Sopenharmony_ci * @data_addr_override: override fifo reg offset with this value. 11462306a36Sopenharmony_ci * @wm_aligned: force fifo watermark equal with data length in PIO mode. 11562306a36Sopenharmony_ci * Set as true if alignment is needed. 11662306a36Sopenharmony_ci * @data_shift: log2 of FIFO item size. 11762306a36Sopenharmony_ci * @part_buf_start: Start index in part_buf. 11862306a36Sopenharmony_ci * @part_buf_count: Bytes of partial data in part_buf. 11962306a36Sopenharmony_ci * @part_buf: Simple buffer for partial fifo reads/writes. 12062306a36Sopenharmony_ci * @push_data: Pointer to FIFO push function. 12162306a36Sopenharmony_ci * @pull_data: Pointer to FIFO pull function. 12262306a36Sopenharmony_ci * @quirks: Set of quirks that apply to specific versions of the IP. 12362306a36Sopenharmony_ci * @vqmmc_enabled: Status of vqmmc, should be true or false. 12462306a36Sopenharmony_ci * @irq_flags: The flags to be passed to request_irq. 12562306a36Sopenharmony_ci * @irq: The irq value to be passed to request_irq. 12662306a36Sopenharmony_ci * @sdio_id0: Number of slot0 in the SDIO interrupt registers. 12762306a36Sopenharmony_ci * @cmd11_timer: Timer for SD3.0 voltage switch over scheme. 12862306a36Sopenharmony_ci * @cto_timer: Timer for broken command transfer over scheme. 12962306a36Sopenharmony_ci * @dto_timer: Timer for broken data transfer over scheme. 13062306a36Sopenharmony_ci * 13162306a36Sopenharmony_ci * Locking 13262306a36Sopenharmony_ci * ======= 13362306a36Sopenharmony_ci * 13462306a36Sopenharmony_ci * @lock is a softirq-safe spinlock protecting @queue as well as 13562306a36Sopenharmony_ci * @slot, @mrq and @state. These must always be updated 13662306a36Sopenharmony_ci * at the same time while holding @lock. 13762306a36Sopenharmony_ci * The @mrq field of struct dw_mci_slot is also protected by @lock, 13862306a36Sopenharmony_ci * and must always be written at the same time as the slot is added to 13962306a36Sopenharmony_ci * @queue. 14062306a36Sopenharmony_ci * 14162306a36Sopenharmony_ci * @irq_lock is an irq-safe spinlock protecting the INTMASK register 14262306a36Sopenharmony_ci * to allow the interrupt handler to modify it directly. Held for only long 14362306a36Sopenharmony_ci * enough to read-modify-write INTMASK and no other locks are grabbed when 14462306a36Sopenharmony_ci * holding this one. 14562306a36Sopenharmony_ci * 14662306a36Sopenharmony_ci * @pending_events and @completed_events are accessed using atomic bit 14762306a36Sopenharmony_ci * operations, so they don't need any locking. 14862306a36Sopenharmony_ci * 14962306a36Sopenharmony_ci * None of the fields touched by the interrupt handler need any 15062306a36Sopenharmony_ci * locking. However, ordering is important: Before EVENT_DATA_ERROR or 15162306a36Sopenharmony_ci * EVENT_DATA_COMPLETE is set in @pending_events, all data-related 15262306a36Sopenharmony_ci * interrupts must be disabled and @data_status updated with a 15362306a36Sopenharmony_ci * snapshot of SR. Similarly, before EVENT_CMD_COMPLETE is set, the 15462306a36Sopenharmony_ci * CMDRDY interrupt must be disabled and @cmd_status updated with a 15562306a36Sopenharmony_ci * snapshot of SR, and before EVENT_XFER_COMPLETE can be set, the 15662306a36Sopenharmony_ci * bytes_xfered field of @data must be written. This is ensured by 15762306a36Sopenharmony_ci * using barriers. 15862306a36Sopenharmony_ci */ 15962306a36Sopenharmony_cistruct dw_mci { 16062306a36Sopenharmony_ci spinlock_t lock; 16162306a36Sopenharmony_ci spinlock_t irq_lock; 16262306a36Sopenharmony_ci void __iomem *regs; 16362306a36Sopenharmony_ci void __iomem *fifo_reg; 16462306a36Sopenharmony_ci u32 data_addr_override; 16562306a36Sopenharmony_ci bool wm_aligned; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci struct scatterlist *sg; 16862306a36Sopenharmony_ci struct sg_mapping_iter sg_miter; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci struct mmc_request *mrq; 17162306a36Sopenharmony_ci struct mmc_command *cmd; 17262306a36Sopenharmony_ci struct mmc_data *data; 17362306a36Sopenharmony_ci struct mmc_command stop_abort; 17462306a36Sopenharmony_ci unsigned int prev_blksz; 17562306a36Sopenharmony_ci unsigned char timing; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci /* DMA interface members*/ 17862306a36Sopenharmony_ci int use_dma; 17962306a36Sopenharmony_ci int using_dma; 18062306a36Sopenharmony_ci int dma_64bit_address; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci dma_addr_t sg_dma; 18362306a36Sopenharmony_ci void *sg_cpu; 18462306a36Sopenharmony_ci const struct dw_mci_dma_ops *dma_ops; 18562306a36Sopenharmony_ci /* For idmac */ 18662306a36Sopenharmony_ci unsigned int ring_size; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci /* For edmac */ 18962306a36Sopenharmony_ci struct dw_mci_dma_slave *dms; 19062306a36Sopenharmony_ci /* Registers's physical base address */ 19162306a36Sopenharmony_ci resource_size_t phy_regs; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci u32 cmd_status; 19462306a36Sopenharmony_ci u32 data_status; 19562306a36Sopenharmony_ci u32 stop_cmdr; 19662306a36Sopenharmony_ci u32 dir_status; 19762306a36Sopenharmony_ci struct tasklet_struct tasklet; 19862306a36Sopenharmony_ci unsigned long pending_events; 19962306a36Sopenharmony_ci unsigned long completed_events; 20062306a36Sopenharmony_ci enum dw_mci_state state; 20162306a36Sopenharmony_ci struct list_head queue; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci u32 bus_hz; 20462306a36Sopenharmony_ci u32 current_speed; 20562306a36Sopenharmony_ci u32 minimum_speed; 20662306a36Sopenharmony_ci u32 fifoth_val; 20762306a36Sopenharmony_ci u16 verid; 20862306a36Sopenharmony_ci struct device *dev; 20962306a36Sopenharmony_ci struct dw_mci_board *pdata; 21062306a36Sopenharmony_ci const struct dw_mci_drv_data *drv_data; 21162306a36Sopenharmony_ci void *priv; 21262306a36Sopenharmony_ci struct clk *biu_clk; 21362306a36Sopenharmony_ci struct clk *ciu_clk; 21462306a36Sopenharmony_ci struct dw_mci_slot *slot; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci /* FIFO push and pull */ 21762306a36Sopenharmony_ci int fifo_depth; 21862306a36Sopenharmony_ci int data_shift; 21962306a36Sopenharmony_ci u8 part_buf_start; 22062306a36Sopenharmony_ci u8 part_buf_count; 22162306a36Sopenharmony_ci union { 22262306a36Sopenharmony_ci u16 part_buf16; 22362306a36Sopenharmony_ci u32 part_buf32; 22462306a36Sopenharmony_ci u64 part_buf; 22562306a36Sopenharmony_ci }; 22662306a36Sopenharmony_ci void (*push_data)(struct dw_mci *host, void *buf, int cnt); 22762306a36Sopenharmony_ci void (*pull_data)(struct dw_mci *host, void *buf, int cnt); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci u32 quirks; 23062306a36Sopenharmony_ci bool vqmmc_enabled; 23162306a36Sopenharmony_ci unsigned long irq_flags; /* IRQ flags */ 23262306a36Sopenharmony_ci int irq; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci int sdio_id0; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci struct timer_list cmd11_timer; 23762306a36Sopenharmony_ci struct timer_list cto_timer; 23862306a36Sopenharmony_ci struct timer_list dto_timer; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci#ifdef CONFIG_FAULT_INJECTION 24162306a36Sopenharmony_ci struct fault_attr fail_data_crc; 24262306a36Sopenharmony_ci struct hrtimer fault_timer; 24362306a36Sopenharmony_ci#endif 24462306a36Sopenharmony_ci}; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci/* DMA ops for Internal/External DMAC interface */ 24762306a36Sopenharmony_cistruct dw_mci_dma_ops { 24862306a36Sopenharmony_ci /* DMA Ops */ 24962306a36Sopenharmony_ci int (*init)(struct dw_mci *host); 25062306a36Sopenharmony_ci int (*start)(struct dw_mci *host, unsigned int sg_len); 25162306a36Sopenharmony_ci void (*complete)(void *host); 25262306a36Sopenharmony_ci void (*stop)(struct dw_mci *host); 25362306a36Sopenharmony_ci void (*cleanup)(struct dw_mci *host); 25462306a36Sopenharmony_ci void (*exit)(struct dw_mci *host); 25562306a36Sopenharmony_ci}; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cistruct dma_pdata; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci/* Board platform data */ 26062306a36Sopenharmony_cistruct dw_mci_board { 26162306a36Sopenharmony_ci unsigned int bus_hz; /* Clock speed at the cclk_in pad */ 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci u32 caps; /* Capabilities */ 26462306a36Sopenharmony_ci u32 caps2; /* More capabilities */ 26562306a36Sopenharmony_ci u32 pm_caps; /* PM capabilities */ 26662306a36Sopenharmony_ci /* 26762306a36Sopenharmony_ci * Override fifo depth. If 0, autodetect it from the FIFOTH register, 26862306a36Sopenharmony_ci * but note that this may not be reliable after a bootloader has used 26962306a36Sopenharmony_ci * it. 27062306a36Sopenharmony_ci */ 27162306a36Sopenharmony_ci unsigned int fifo_depth; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci /* delay in mS before detecting cards after interrupt */ 27462306a36Sopenharmony_ci u32 detect_delay_ms; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci struct reset_control *rstc; 27762306a36Sopenharmony_ci struct dw_mci_dma_ops *dma_ops; 27862306a36Sopenharmony_ci struct dma_pdata *data; 27962306a36Sopenharmony_ci}; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci/* Support for longer data read timeout */ 28262306a36Sopenharmony_ci#define DW_MMC_QUIRK_EXTENDED_TMOUT BIT(0) 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci#define DW_MMC_240A 0x240a 28562306a36Sopenharmony_ci#define DW_MMC_280A 0x280a 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci#define SDMMC_CTRL 0x000 28862306a36Sopenharmony_ci#define SDMMC_PWREN 0x004 28962306a36Sopenharmony_ci#define SDMMC_CLKDIV 0x008 29062306a36Sopenharmony_ci#define SDMMC_CLKSRC 0x00c 29162306a36Sopenharmony_ci#define SDMMC_CLKENA 0x010 29262306a36Sopenharmony_ci#define SDMMC_TMOUT 0x014 29362306a36Sopenharmony_ci#define SDMMC_CTYPE 0x018 29462306a36Sopenharmony_ci#define SDMMC_BLKSIZ 0x01c 29562306a36Sopenharmony_ci#define SDMMC_BYTCNT 0x020 29662306a36Sopenharmony_ci#define SDMMC_INTMASK 0x024 29762306a36Sopenharmony_ci#define SDMMC_CMDARG 0x028 29862306a36Sopenharmony_ci#define SDMMC_CMD 0x02c 29962306a36Sopenharmony_ci#define SDMMC_RESP0 0x030 30062306a36Sopenharmony_ci#define SDMMC_RESP1 0x034 30162306a36Sopenharmony_ci#define SDMMC_RESP2 0x038 30262306a36Sopenharmony_ci#define SDMMC_RESP3 0x03c 30362306a36Sopenharmony_ci#define SDMMC_MINTSTS 0x040 30462306a36Sopenharmony_ci#define SDMMC_RINTSTS 0x044 30562306a36Sopenharmony_ci#define SDMMC_STATUS 0x048 30662306a36Sopenharmony_ci#define SDMMC_FIFOTH 0x04c 30762306a36Sopenharmony_ci#define SDMMC_CDETECT 0x050 30862306a36Sopenharmony_ci#define SDMMC_WRTPRT 0x054 30962306a36Sopenharmony_ci#define SDMMC_GPIO 0x058 31062306a36Sopenharmony_ci#define SDMMC_TCBCNT 0x05c 31162306a36Sopenharmony_ci#define SDMMC_TBBCNT 0x060 31262306a36Sopenharmony_ci#define SDMMC_DEBNCE 0x064 31362306a36Sopenharmony_ci#define SDMMC_USRID 0x068 31462306a36Sopenharmony_ci#define SDMMC_VERID 0x06c 31562306a36Sopenharmony_ci#define SDMMC_HCON 0x070 31662306a36Sopenharmony_ci#define SDMMC_UHS_REG 0x074 31762306a36Sopenharmony_ci#define SDMMC_RST_N 0x078 31862306a36Sopenharmony_ci#define SDMMC_BMOD 0x080 31962306a36Sopenharmony_ci#define SDMMC_PLDMND 0x084 32062306a36Sopenharmony_ci#define SDMMC_DBADDR 0x088 32162306a36Sopenharmony_ci#define SDMMC_IDSTS 0x08c 32262306a36Sopenharmony_ci#define SDMMC_IDINTEN 0x090 32362306a36Sopenharmony_ci#define SDMMC_DSCADDR 0x094 32462306a36Sopenharmony_ci#define SDMMC_BUFADDR 0x098 32562306a36Sopenharmony_ci#define SDMMC_CDTHRCTL 0x100 32662306a36Sopenharmony_ci#define SDMMC_UHS_REG_EXT 0x108 32762306a36Sopenharmony_ci#define SDMMC_DDR_REG 0x10c 32862306a36Sopenharmony_ci#define SDMMC_ENABLE_SHIFT 0x110 32962306a36Sopenharmony_ci#define SDMMC_DATA(x) (x) 33062306a36Sopenharmony_ci/* 33162306a36Sopenharmony_ci * Registers to support idmac 64-bit address mode 33262306a36Sopenharmony_ci */ 33362306a36Sopenharmony_ci#define SDMMC_DBADDRL 0x088 33462306a36Sopenharmony_ci#define SDMMC_DBADDRU 0x08c 33562306a36Sopenharmony_ci#define SDMMC_IDSTS64 0x090 33662306a36Sopenharmony_ci#define SDMMC_IDINTEN64 0x094 33762306a36Sopenharmony_ci#define SDMMC_DSCADDRL 0x098 33862306a36Sopenharmony_ci#define SDMMC_DSCADDRU 0x09c 33962306a36Sopenharmony_ci#define SDMMC_BUFADDRL 0x0A0 34062306a36Sopenharmony_ci#define SDMMC_BUFADDRU 0x0A4 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci/* 34362306a36Sopenharmony_ci * Data offset is difference according to Version 34462306a36Sopenharmony_ci * Lower than 2.40a : data register offest is 0x100 34562306a36Sopenharmony_ci */ 34662306a36Sopenharmony_ci#define DATA_OFFSET 0x100 34762306a36Sopenharmony_ci#define DATA_240A_OFFSET 0x200 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci/* shift bit field */ 35062306a36Sopenharmony_ci#define _SBF(f, v) ((v) << (f)) 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci/* Control register defines */ 35362306a36Sopenharmony_ci#define SDMMC_CTRL_USE_IDMAC BIT(25) 35462306a36Sopenharmony_ci#define SDMMC_CTRL_CEATA_INT_EN BIT(11) 35562306a36Sopenharmony_ci#define SDMMC_CTRL_SEND_AS_CCSD BIT(10) 35662306a36Sopenharmony_ci#define SDMMC_CTRL_SEND_CCSD BIT(9) 35762306a36Sopenharmony_ci#define SDMMC_CTRL_ABRT_READ_DATA BIT(8) 35862306a36Sopenharmony_ci#define SDMMC_CTRL_SEND_IRQ_RESP BIT(7) 35962306a36Sopenharmony_ci#define SDMMC_CTRL_READ_WAIT BIT(6) 36062306a36Sopenharmony_ci#define SDMMC_CTRL_DMA_ENABLE BIT(5) 36162306a36Sopenharmony_ci#define SDMMC_CTRL_INT_ENABLE BIT(4) 36262306a36Sopenharmony_ci#define SDMMC_CTRL_DMA_RESET BIT(2) 36362306a36Sopenharmony_ci#define SDMMC_CTRL_FIFO_RESET BIT(1) 36462306a36Sopenharmony_ci#define SDMMC_CTRL_RESET BIT(0) 36562306a36Sopenharmony_ci/* Clock Enable register defines */ 36662306a36Sopenharmony_ci#define SDMMC_CLKEN_LOW_PWR BIT(16) 36762306a36Sopenharmony_ci#define SDMMC_CLKEN_ENABLE BIT(0) 36862306a36Sopenharmony_ci/* time-out register defines */ 36962306a36Sopenharmony_ci#define SDMMC_TMOUT_DATA(n) _SBF(8, (n)) 37062306a36Sopenharmony_ci#define SDMMC_TMOUT_DATA_MSK 0xFFFFFF00 37162306a36Sopenharmony_ci#define SDMMC_TMOUT_RESP(n) ((n) & 0xFF) 37262306a36Sopenharmony_ci#define SDMMC_TMOUT_RESP_MSK 0xFF 37362306a36Sopenharmony_ci/* card-type register defines */ 37462306a36Sopenharmony_ci#define SDMMC_CTYPE_8BIT BIT(16) 37562306a36Sopenharmony_ci#define SDMMC_CTYPE_4BIT BIT(0) 37662306a36Sopenharmony_ci#define SDMMC_CTYPE_1BIT 0 37762306a36Sopenharmony_ci/* Interrupt status & mask register defines */ 37862306a36Sopenharmony_ci#define SDMMC_INT_SDIO(n) BIT(16 + (n)) 37962306a36Sopenharmony_ci#define SDMMC_INT_EBE BIT(15) 38062306a36Sopenharmony_ci#define SDMMC_INT_ACD BIT(14) 38162306a36Sopenharmony_ci#define SDMMC_INT_SBE BIT(13) 38262306a36Sopenharmony_ci#define SDMMC_INT_HLE BIT(12) 38362306a36Sopenharmony_ci#define SDMMC_INT_FRUN BIT(11) 38462306a36Sopenharmony_ci#define SDMMC_INT_HTO BIT(10) 38562306a36Sopenharmony_ci#define SDMMC_INT_VOLT_SWITCH BIT(10) /* overloads bit 10! */ 38662306a36Sopenharmony_ci#define SDMMC_INT_DRTO BIT(9) 38762306a36Sopenharmony_ci#define SDMMC_INT_RTO BIT(8) 38862306a36Sopenharmony_ci#define SDMMC_INT_DCRC BIT(7) 38962306a36Sopenharmony_ci#define SDMMC_INT_RCRC BIT(6) 39062306a36Sopenharmony_ci#define SDMMC_INT_RXDR BIT(5) 39162306a36Sopenharmony_ci#define SDMMC_INT_TXDR BIT(4) 39262306a36Sopenharmony_ci#define SDMMC_INT_DATA_OVER BIT(3) 39362306a36Sopenharmony_ci#define SDMMC_INT_CMD_DONE BIT(2) 39462306a36Sopenharmony_ci#define SDMMC_INT_RESP_ERR BIT(1) 39562306a36Sopenharmony_ci#define SDMMC_INT_CD BIT(0) 39662306a36Sopenharmony_ci#define SDMMC_INT_ERROR 0xbfc2 39762306a36Sopenharmony_ci/* Command register defines */ 39862306a36Sopenharmony_ci#define SDMMC_CMD_START BIT(31) 39962306a36Sopenharmony_ci#define SDMMC_CMD_USE_HOLD_REG BIT(29) 40062306a36Sopenharmony_ci#define SDMMC_CMD_VOLT_SWITCH BIT(28) 40162306a36Sopenharmony_ci#define SDMMC_CMD_CCS_EXP BIT(23) 40262306a36Sopenharmony_ci#define SDMMC_CMD_CEATA_RD BIT(22) 40362306a36Sopenharmony_ci#define SDMMC_CMD_UPD_CLK BIT(21) 40462306a36Sopenharmony_ci#define SDMMC_CMD_INIT BIT(15) 40562306a36Sopenharmony_ci#define SDMMC_CMD_STOP BIT(14) 40662306a36Sopenharmony_ci#define SDMMC_CMD_PRV_DAT_WAIT BIT(13) 40762306a36Sopenharmony_ci#define SDMMC_CMD_SEND_STOP BIT(12) 40862306a36Sopenharmony_ci#define SDMMC_CMD_STRM_MODE BIT(11) 40962306a36Sopenharmony_ci#define SDMMC_CMD_DAT_WR BIT(10) 41062306a36Sopenharmony_ci#define SDMMC_CMD_DAT_EXP BIT(9) 41162306a36Sopenharmony_ci#define SDMMC_CMD_RESP_CRC BIT(8) 41262306a36Sopenharmony_ci#define SDMMC_CMD_RESP_LONG BIT(7) 41362306a36Sopenharmony_ci#define SDMMC_CMD_RESP_EXP BIT(6) 41462306a36Sopenharmony_ci#define SDMMC_CMD_INDX(n) ((n) & 0x1F) 41562306a36Sopenharmony_ci/* Status register defines */ 41662306a36Sopenharmony_ci#define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FFF) 41762306a36Sopenharmony_ci#define SDMMC_STATUS_DMA_REQ BIT(31) 41862306a36Sopenharmony_ci#define SDMMC_STATUS_BUSY BIT(9) 41962306a36Sopenharmony_ci/* FIFOTH register defines */ 42062306a36Sopenharmony_ci#define SDMMC_SET_FIFOTH(m, r, t) (((m) & 0x7) << 28 | \ 42162306a36Sopenharmony_ci ((r) & 0xFFF) << 16 | \ 42262306a36Sopenharmony_ci ((t) & 0xFFF)) 42362306a36Sopenharmony_ci/* HCON register defines */ 42462306a36Sopenharmony_ci#define DMA_INTERFACE_IDMA (0x0) 42562306a36Sopenharmony_ci#define DMA_INTERFACE_DWDMA (0x1) 42662306a36Sopenharmony_ci#define DMA_INTERFACE_GDMA (0x2) 42762306a36Sopenharmony_ci#define DMA_INTERFACE_NODMA (0x3) 42862306a36Sopenharmony_ci#define SDMMC_GET_TRANS_MODE(x) (((x)>>16) & 0x3) 42962306a36Sopenharmony_ci#define SDMMC_GET_SLOT_NUM(x) ((((x)>>1) & 0x1F) + 1) 43062306a36Sopenharmony_ci#define SDMMC_GET_HDATA_WIDTH(x) (((x)>>7) & 0x7) 43162306a36Sopenharmony_ci#define SDMMC_GET_ADDR_CONFIG(x) (((x)>>27) & 0x1) 43262306a36Sopenharmony_ci/* Internal DMAC interrupt defines */ 43362306a36Sopenharmony_ci#define SDMMC_IDMAC_INT_AI BIT(9) 43462306a36Sopenharmony_ci#define SDMMC_IDMAC_INT_NI BIT(8) 43562306a36Sopenharmony_ci#define SDMMC_IDMAC_INT_CES BIT(5) 43662306a36Sopenharmony_ci#define SDMMC_IDMAC_INT_DU BIT(4) 43762306a36Sopenharmony_ci#define SDMMC_IDMAC_INT_FBE BIT(2) 43862306a36Sopenharmony_ci#define SDMMC_IDMAC_INT_RI BIT(1) 43962306a36Sopenharmony_ci#define SDMMC_IDMAC_INT_TI BIT(0) 44062306a36Sopenharmony_ci/* Internal DMAC bus mode bits */ 44162306a36Sopenharmony_ci#define SDMMC_IDMAC_ENABLE BIT(7) 44262306a36Sopenharmony_ci#define SDMMC_IDMAC_FB BIT(1) 44362306a36Sopenharmony_ci#define SDMMC_IDMAC_SWRESET BIT(0) 44462306a36Sopenharmony_ci/* H/W reset */ 44562306a36Sopenharmony_ci#define SDMMC_RST_HWACTIVE 0x1 44662306a36Sopenharmony_ci/* Version ID register define */ 44762306a36Sopenharmony_ci#define SDMMC_GET_VERID(x) ((x) & 0xFFFF) 44862306a36Sopenharmony_ci/* Card read threshold */ 44962306a36Sopenharmony_ci#define SDMMC_SET_THLD(v, x) (((v) & 0xFFF) << 16 | (x)) 45062306a36Sopenharmony_ci#define SDMMC_CARD_WR_THR_EN BIT(2) 45162306a36Sopenharmony_ci#define SDMMC_CARD_RD_THR_EN BIT(0) 45262306a36Sopenharmony_ci/* UHS-1 register defines */ 45362306a36Sopenharmony_ci#define SDMMC_UHS_DDR BIT(16) 45462306a36Sopenharmony_ci#define SDMMC_UHS_18V BIT(0) 45562306a36Sopenharmony_ci/* DDR register defines */ 45662306a36Sopenharmony_ci#define SDMMC_DDR_HS400 BIT(31) 45762306a36Sopenharmony_ci/* Enable shift register defines */ 45862306a36Sopenharmony_ci#define SDMMC_ENABLE_PHASE BIT(0) 45962306a36Sopenharmony_ci/* All ctrl reset bits */ 46062306a36Sopenharmony_ci#define SDMMC_CTRL_ALL_RESET_FLAGS \ 46162306a36Sopenharmony_ci (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET) 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci/* FIFO register access macros. These should not change the data endian-ness 46462306a36Sopenharmony_ci * as they are written to memory to be dealt with by the upper layers 46562306a36Sopenharmony_ci */ 46662306a36Sopenharmony_ci#define mci_fifo_readw(__reg) __raw_readw(__reg) 46762306a36Sopenharmony_ci#define mci_fifo_readl(__reg) __raw_readl(__reg) 46862306a36Sopenharmony_ci#define mci_fifo_readq(__reg) __raw_readq(__reg) 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci#define mci_fifo_writew(__value, __reg) __raw_writew(__reg, __value) 47162306a36Sopenharmony_ci#define mci_fifo_writel(__value, __reg) __raw_writel(__reg, __value) 47262306a36Sopenharmony_ci#define mci_fifo_writeq(__value, __reg) __raw_writeq(__reg, __value) 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci/* Register access macros */ 47562306a36Sopenharmony_ci#define mci_readl(dev, reg) \ 47662306a36Sopenharmony_ci readl_relaxed((dev)->regs + SDMMC_##reg) 47762306a36Sopenharmony_ci#define mci_writel(dev, reg, value) \ 47862306a36Sopenharmony_ci writel_relaxed((value), (dev)->regs + SDMMC_##reg) 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci/* 16-bit FIFO access macros */ 48162306a36Sopenharmony_ci#define mci_readw(dev, reg) \ 48262306a36Sopenharmony_ci readw_relaxed((dev)->regs + SDMMC_##reg) 48362306a36Sopenharmony_ci#define mci_writew(dev, reg, value) \ 48462306a36Sopenharmony_ci writew_relaxed((value), (dev)->regs + SDMMC_##reg) 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci/* 64-bit FIFO access macros */ 48762306a36Sopenharmony_ci#ifdef readq 48862306a36Sopenharmony_ci#define mci_readq(dev, reg) \ 48962306a36Sopenharmony_ci readq_relaxed((dev)->regs + SDMMC_##reg) 49062306a36Sopenharmony_ci#define mci_writeq(dev, reg, value) \ 49162306a36Sopenharmony_ci writeq_relaxed((value), (dev)->regs + SDMMC_##reg) 49262306a36Sopenharmony_ci#else 49362306a36Sopenharmony_ci/* 49462306a36Sopenharmony_ci * Dummy readq implementation for architectures that don't define it. 49562306a36Sopenharmony_ci * 49662306a36Sopenharmony_ci * We would assume that none of these architectures would configure 49762306a36Sopenharmony_ci * the IP block with a 64bit FIFO width, so this code will never be 49862306a36Sopenharmony_ci * executed on those machines. Defining these macros here keeps the 49962306a36Sopenharmony_ci * rest of the code free from ifdefs. 50062306a36Sopenharmony_ci */ 50162306a36Sopenharmony_ci#define mci_readq(dev, reg) \ 50262306a36Sopenharmony_ci (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg)) 50362306a36Sopenharmony_ci#define mci_writeq(dev, reg, value) \ 50462306a36Sopenharmony_ci (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg) = (value)) 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci#define __raw_writeq(__value, __reg) \ 50762306a36Sopenharmony_ci (*(volatile u64 __force *)(__reg) = (__value)) 50862306a36Sopenharmony_ci#define __raw_readq(__reg) (*(volatile u64 __force *)(__reg)) 50962306a36Sopenharmony_ci#endif 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ciextern int dw_mci_probe(struct dw_mci *host); 51262306a36Sopenharmony_ciextern void dw_mci_remove(struct dw_mci *host); 51362306a36Sopenharmony_ci#ifdef CONFIG_PM 51462306a36Sopenharmony_ciextern int dw_mci_runtime_suspend(struct device *device); 51562306a36Sopenharmony_ciextern int dw_mci_runtime_resume(struct device *device); 51662306a36Sopenharmony_ci#endif 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci/** 51962306a36Sopenharmony_ci * struct dw_mci_slot - MMC slot state 52062306a36Sopenharmony_ci * @mmc: The mmc_host representing this slot. 52162306a36Sopenharmony_ci * @host: The MMC controller this slot is using. 52262306a36Sopenharmony_ci * @ctype: Card type for this slot. 52362306a36Sopenharmony_ci * @mrq: mmc_request currently being processed or waiting to be 52462306a36Sopenharmony_ci * processed, or NULL when the slot is idle. 52562306a36Sopenharmony_ci * @queue_node: List node for placing this node in the @queue list of 52662306a36Sopenharmony_ci * &struct dw_mci. 52762306a36Sopenharmony_ci * @clock: Clock rate configured by set_ios(). Protected by host->lock. 52862306a36Sopenharmony_ci * @__clk_old: The last clock value that was requested from core. 52962306a36Sopenharmony_ci * Keeping track of this helps us to avoid spamming the console. 53062306a36Sopenharmony_ci * @flags: Random state bits associated with the slot. 53162306a36Sopenharmony_ci * @id: Number of this slot. 53262306a36Sopenharmony_ci * @sdio_id: Number of this slot in the SDIO interrupt registers. 53362306a36Sopenharmony_ci */ 53462306a36Sopenharmony_cistruct dw_mci_slot { 53562306a36Sopenharmony_ci struct mmc_host *mmc; 53662306a36Sopenharmony_ci struct dw_mci *host; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci u32 ctype; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci struct mmc_request *mrq; 54162306a36Sopenharmony_ci struct list_head queue_node; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci unsigned int clock; 54462306a36Sopenharmony_ci unsigned int __clk_old; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci unsigned long flags; 54762306a36Sopenharmony_ci#define DW_MMC_CARD_PRESENT 0 54862306a36Sopenharmony_ci#define DW_MMC_CARD_NEED_INIT 1 54962306a36Sopenharmony_ci#define DW_MMC_CARD_NO_LOW_PWR 2 55062306a36Sopenharmony_ci#define DW_MMC_CARD_NO_USE_HOLD 3 55162306a36Sopenharmony_ci#define DW_MMC_CARD_NEEDS_POLL 4 55262306a36Sopenharmony_ci int id; 55362306a36Sopenharmony_ci int sdio_id; 55462306a36Sopenharmony_ci}; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci/** 55762306a36Sopenharmony_ci * dw_mci driver data - dw-mshc implementation specific driver data. 55862306a36Sopenharmony_ci * @caps: mmc subsystem specified capabilities of the controller(s). 55962306a36Sopenharmony_ci * @num_caps: number of capabilities specified by @caps. 56062306a36Sopenharmony_ci * @common_caps: mmc subsystem specified capabilities applicable to all of 56162306a36Sopenharmony_ci * the controllers 56262306a36Sopenharmony_ci * @init: early implementation specific initialization. 56362306a36Sopenharmony_ci * @set_ios: handle bus specific extensions. 56462306a36Sopenharmony_ci * @parse_dt: parse implementation specific device tree properties. 56562306a36Sopenharmony_ci * @execute_tuning: implementation specific tuning procedure. 56662306a36Sopenharmony_ci * @set_data_timeout: implementation specific timeout. 56762306a36Sopenharmony_ci * @get_drto_clks: implementation specific cycle count for data read timeout. 56862306a36Sopenharmony_ci * 56962306a36Sopenharmony_ci * Provide controller implementation specific extensions. The usage of this 57062306a36Sopenharmony_ci * data structure is fully optional and usage of each member in this structure 57162306a36Sopenharmony_ci * is optional as well. 57262306a36Sopenharmony_ci */ 57362306a36Sopenharmony_cistruct dw_mci_drv_data { 57462306a36Sopenharmony_ci unsigned long *caps; 57562306a36Sopenharmony_ci u32 num_caps; 57662306a36Sopenharmony_ci u32 common_caps; 57762306a36Sopenharmony_ci int (*init)(struct dw_mci *host); 57862306a36Sopenharmony_ci void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); 57962306a36Sopenharmony_ci int (*parse_dt)(struct dw_mci *host); 58062306a36Sopenharmony_ci int (*execute_tuning)(struct dw_mci_slot *slot, u32 opcode); 58162306a36Sopenharmony_ci int (*prepare_hs400_tuning)(struct dw_mci *host, 58262306a36Sopenharmony_ci struct mmc_ios *ios); 58362306a36Sopenharmony_ci int (*switch_voltage)(struct mmc_host *mmc, 58462306a36Sopenharmony_ci struct mmc_ios *ios); 58562306a36Sopenharmony_ci void (*set_data_timeout)(struct dw_mci *host, 58662306a36Sopenharmony_ci unsigned int timeout_ns); 58762306a36Sopenharmony_ci u32 (*get_drto_clks)(struct dw_mci *host); 58862306a36Sopenharmony_ci}; 58962306a36Sopenharmony_ci#endif /* _DW_MMC_H_ */ 590