aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/cavium.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/cavium.h')
-rw-r--r--drivers/mmc/host/cavium.h158
1 files changed, 151 insertions, 7 deletions
diff --git a/drivers/mmc/host/cavium.h b/drivers/mmc/host/cavium.h
index f3eea5eaa678..4725804d72bb 100644
--- a/drivers/mmc/host/cavium.h
+++ b/drivers/mmc/host/cavium.h
@@ -19,8 +19,59 @@
#include <linux/of.h>
#include <linux/scatterlist.h>
#include <linux/semaphore.h>
+#include <linux/pci.h>
#define CAVIUM_MAX_MMC 4
+#define BLKSZ_EXT_CSD 512
+#define MRVL_OCTEONTX2_96XX_PARTNUM 0xB2
+
+/* Subsystem Device ID */
+#define PCI_SUBSYS_DEVID_8XXX 0xA
+#define PCI_SUBSYS_DEVID_9XXX 0xB
+#define PCI_SUBSYS_DEVID_98XX 0xB1
+#define PCI_SUBSYS_DEVID_96XX 0xB2
+#define PCI_SUBSYS_DEVID_95XX 0xB3
+#define PCI_SUBSYS_DEVID_LOKI 0xB4
+#define PCI_SUBSYS_DEVID_95XXMM 0xB5
+
+/* Chip revision Id */
+#define REV_ID_0 0
+#define REV_ID_1 1
+#define REV_ID_2 2
+
+#define KHZ_400 (400000)
+#define MHZ_26 (26000000)
+#define MHZ_52 (52000000)
+#define MHZ_100 (100000000)
+#define MHZ_112_5 (112500000)
+#define MHZ_150 (150000000)
+#define MHZ_167 (167000000)
+#define MHZ_200 (200000000)
+
+/* octtx2: emmc interface io current drive strength */
+#define MILLI_AMP_2 (0x0)
+#define MILLI_AMP_4 (0x1)
+#define MILLI_AMP_8 (0x2)
+#define MILLI_AMP_16 (0x3)
+
+/* octtx2: emmc interface io clk skew */
+#define LOW_SLEW_RATE (0x0)
+#define HIGH_SLEW_RATE (0x1)
+
+/* octtx2: emmc interface calibration */
+#define START_CALIBRATION (0x1)
+#define TOTAL_NO_OF_TAPS (512)
+#define PS_10000 (10 * 1000)
+#define PS_5000 (5000)
+#define PS_2500 (2500)
+#define PS_800 (800)
+#define PS_400 (400)
+#define MAX_NO_OF_TAPS 64
+
+/* Macros to enable/disable clks */
+#define CLK_ON 0
+#define CLK_OFF 1
+
/* DMA register addresses */
#define MIO_EMM_DMA_FIFO_CFG(x) (0x00 + x->reg_off_dma)
@@ -33,8 +84,17 @@
#define MIO_EMM_DMA_INT_ENA_W1S(x) (0x40 + x->reg_off_dma)
#define MIO_EMM_DMA_INT_ENA_W1C(x) (0x48 + x->reg_off_dma)
+/* octtx2 specific registers */
+#define MIO_EMM_CALB(x) (0xC0 + x->reg_off)
+#define MIO_EMM_TAP(x) (0xC8 + x->reg_off)
+#define MIO_EMM_TIMING(x) (0xD0 + x->reg_off)
+#define MIO_EMM_DEBUG(x) (0xF8 + x->reg_off)
+
/* register addresses */
#define MIO_EMM_CFG(x) (0x00 + x->reg_off)
+#define MIO_EMM_MODE(x, s) (0x08 + 8*(s) + (x)->reg_off)
+/* octtx2 specific register */
+#define MIO_EMM_IO_CTL(x) (0x40 + x->reg_off)
#define MIO_EMM_SWITCH(x) (0x48 + x->reg_off)
#define MIO_EMM_DMA(x) (0x50 + x->reg_off)
#define MIO_EMM_CMD(x) (0x58 + x->reg_off)
@@ -56,6 +116,7 @@ struct cvm_mmc_host {
struct device *dev;
void __iomem *base;
void __iomem *dma_base;
+ struct pci_dev *pdev;
int reg_off;
int reg_off_dma;
u64 emm_cfg;
@@ -63,23 +124,30 @@ struct cvm_mmc_host {
int last_slot;
struct clk *clk;
int sys_freq;
-
- struct mmc_request *current_req;
- struct sg_mapping_iter smi;
- bool dma_active;
+ int max_freq;
bool use_sg;
-
bool has_ciu3;
+ bool powered;
+ bool use_vqmmc; /* must disable slots over switch */
bool big_dma_addr;
bool need_irq_handler_lock;
+ bool tap_requires_noclk;
+ bool calibrate_glitch;
+ bool cond_clock_glitch;
spinlock_t irq_handler_lock;
struct semaphore mmc_serializer;
+#if IS_ENABLED(CONFIG_MMC_PSTORE)
+ bool pstore;
+#endif
struct gpio_desc *global_pwr_gpiod;
atomic_t shared_power_users;
struct cvm_mmc_slot *slot[CAVIUM_MAX_MMC];
struct platform_device *slot_pdev[CAVIUM_MAX_MMC];
+ /* octtx2 specific */
+ unsigned int per_tap_delay; /* per tap delay in pico second */
+ unsigned long delay_logged; /* per-ios.timing bitmask */
void (*set_shared_power)(struct cvm_mmc_host *, int);
void (*acquire_bus)(struct cvm_mmc_host *);
@@ -94,16 +162,42 @@ struct cvm_mmc_host {
struct cvm_mmc_slot {
struct mmc_host *mmc; /* slot-level mmc_core object */
struct cvm_mmc_host *host; /* common hw for all slots */
+ struct mmc_request *current_req;
u64 clock;
+ u32 ecount, gcount;
u64 cached_switch;
u64 cached_rca;
- unsigned int cmd_cnt; /* sample delay */
- unsigned int dat_cnt; /* sample delay */
+ struct sg_mapping_iter smi;
+ bool dma_active;
+
+ u64 taps; /* otx2: MIO_EMM_TIMING */
+ unsigned int cmd_cnt; /* otx: sample cmd in delay */
+ unsigned int data_cnt; /* otx: sample data in delay */
+
+ int drive; /* Current drive */
+ int slew; /* clock skew */
int bus_id;
+ bool cmd6_pending;
+ u64 want_switch;
+ u32 hs400_tuning_block; /* Block number used for tuning */
+ bool hs400_tuning_block_present;
+
+#define MMC_TIMINGS_COUNT ((MMC_TIMING_MMC_HS400) + 1)
+ u32 data_out_taps_dly[MMC_TIMINGS_COUNT];
+ u32 cmd_out_taps_dly[MMC_TIMINGS_COUNT];
+ u32 cmd_in_taps_dly[MMC_TIMINGS_COUNT];
+ u32 data_in_taps_dly[MMC_TIMINGS_COUNT];
+ /*
+ * Flags indicate input timings modified by user.
+ * Flag is set when cmd-in-XXX or data-in-XXX value is set for given
+ * mode in DT. They can be used to control behavior of the timings
+ * tuning alorithm.
+ */
+ u32 in_timings_ctl;
};
struct cvm_mmc_cr_type {
@@ -161,6 +255,21 @@ struct cvm_mmc_cr_mods {
#define MIO_EMM_DMA_CFG_SIZE GENMASK_ULL(55, 36)
#define MIO_EMM_DMA_CFG_ADR GENMASK_ULL(35, 0)
+#define MIO_EMM_CFG_BUS_ENA GENMASK_ULL(3, 0)
+
+#define MIO_EMM_IO_CTL_DRIVE GENMASK_ULL(3, 2)
+#define MIO_EMM_IO_CTL_SLEW BIT_ULL(0)
+
+#define MIO_EMM_CALB_START BIT_ULL(0)
+#define MIO_EMM_TAP_DELAY GENMASK_ULL(7, 0)
+
+#define MIO_EMM_TIMING_CMD_IN GENMASK_ULL(53, 48)
+#define MIO_EMM_TIMING_CMD_OUT GENMASK_ULL(37, 32)
+#define MIO_EMM_TIMING_DATA_IN GENMASK_ULL(21, 16)
+#define MIO_EMM_TIMING_DATA_OUT GENMASK_ULL(5, 0)
+
+#define MIO_EMM_INT_NCB_RAS BIT_ULL(8)
+#define MIO_EMM_INT_NCB_FLT BIT_ULL(7)
#define MIO_EMM_INT_SWITCH_ERR BIT_ULL(6)
#define MIO_EMM_INT_SWITCH_DONE BIT_ULL(5)
#define MIO_EMM_INT_DMA_ERR BIT_ULL(4)
@@ -169,6 +278,9 @@ struct cvm_mmc_cr_mods {
#define MIO_EMM_INT_CMD_DONE BIT_ULL(1)
#define MIO_EMM_INT_BUF_DONE BIT_ULL(0)
+#define MIO_EMM_DMA_INT_FIFO BIT_ULL(1)
+#define MIO_EMM_DMA_INT_DMA BIT_ULL(0)
+
#define MIO_EMM_RSP_STS_BUS_ID GENMASK_ULL(61, 60)
#define MIO_EMM_RSP_STS_CMD_VAL BIT_ULL(59)
#define MIO_EMM_RSP_STS_SWITCH_VAL BIT_ULL(58)
@@ -200,16 +312,48 @@ struct cvm_mmc_cr_mods {
#define MIO_EMM_SWITCH_ERR0 BIT_ULL(58)
#define MIO_EMM_SWITCH_ERR1 BIT_ULL(57)
#define MIO_EMM_SWITCH_ERR2 BIT_ULL(56)
+#define MIO_EMM_SWITCH_ERRS GENMASK_ULL(58, 56)
+#define MIO_EMM_SWITCH_HS400_TIMING BIT_ULL(50)
+#define MIO_EMM_SWITCH_HS200_TIMING BIT_ULL(49)
#define MIO_EMM_SWITCH_HS_TIMING BIT_ULL(48)
+#define MIO_EMM_SWITCH_TIMING GENMASK_ULL(50, 48)
#define MIO_EMM_SWITCH_BUS_WIDTH GENMASK_ULL(42, 40)
#define MIO_EMM_SWITCH_POWER_CLASS GENMASK_ULL(35, 32)
+#define MIO_EMM_SWITCH_CLK GENMASK_ULL(31, 0)
#define MIO_EMM_SWITCH_CLK_HI GENMASK_ULL(31, 16)
#define MIO_EMM_SWITCH_CLK_LO GENMASK_ULL(15, 0)
+#define MIO_EMM_DEBUG_CLK_DIS BIT_ULL(20)
+#define MIO_EMM_DEBUG_RDSYNC BIT_ULL(21)
/* Protoypes */
irqreturn_t cvm_mmc_interrupt(int irq, void *dev_id);
int cvm_mmc_of_slot_probe(struct device *dev, struct cvm_mmc_host *host);
int cvm_mmc_of_slot_remove(struct cvm_mmc_slot *slot);
+
extern const char *cvm_mmc_irq_names[];
+static inline bool is_mmc_8xxx(struct cvm_mmc_host *host)
+{
+#ifdef CONFIG_ARM64
+ struct pci_dev *pdev = host->pdev;
+ u32 chip_id = (pdev->subsystem_device >> 12) & 0xF;
+
+ return (chip_id == PCI_SUBSYS_DEVID_8XXX);
+#else
+ return false;
+#endif
+}
+
+static inline bool is_mmc_otx2(struct cvm_mmc_host *host)
+{
+#ifdef CONFIG_ARM64
+ struct pci_dev *pdev = host->pdev;
+ u32 chip_id = (pdev->subsystem_device >> 12) & 0xF;
+
+ return (chip_id == PCI_SUBSYS_DEVID_9XXX);
+#else
+ return false;
+#endif
+}
+
#endif