summaryrefslogtreecommitdiff
path: root/drivers/mmc/host/cavium.h
diff options
context:
space:
mode:
authorJan Glauber <jglauber@cavium.com>2017-03-30 17:31:24 +0200
committerUlf Hansson <ulf.hansson@linaro.org>2017-04-24 21:42:09 +0200
commitba3869ff32e4a671b0f9baa73900f9e2bfeb0414 (patch)
tree7e0ff1b8aca3adae07e09c5b24d4017dd32d663c /drivers/mmc/host/cavium.h
parentdc5aee3f9f454c35d4e092873b103dc791119e0e (diff)
mmc: cavium: Add core MMC driver for Cavium SOCs
This core driver will be used by a MIPS platform driver or by an ARM64 PCI driver. The core driver implements the mmc_host_ops and slot probe & remove functions. Callbacks are provided to allow platform specific interrupt enable and bus locking. The host controller supports: - up to 4 slots that can contain sd-cards or eMMC chips - 1, 4 and 8 bit bus width - SDR and DDR - transfers up to 52 Mhz (might be less when multiple slots are used) - DMA read/write - multi-block read/write (but not stream mode) Voltage is limited to 3.3v and shared for all slots (vmmc and vmmcq). A global lock for all MMC devices is required because the host controller is shared. Signed-off-by: Jan Glauber <jglauber@cavium.com> Signed-off-by: David Daney <david.daney@cavium.com> Signed-off-by: Steven J. Hill <steven.hill@cavium.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc/host/cavium.h')
-rw-r--r--drivers/mmc/host/cavium.h192
1 files changed, 192 insertions, 0 deletions
diff --git a/drivers/mmc/host/cavium.h b/drivers/mmc/host/cavium.h
new file mode 100644
index 000000000000..f5d2b6156005
--- /dev/null
+++ b/drivers/mmc/host/cavium.h
@@ -0,0 +1,192 @@
+/*
+ * Driver for MMC and SSD cards for Cavium OCTEON and ThunderX SOCs.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012-2017 Cavium Inc.
+ */
+
+#ifndef _CAVIUM_MMC_H_
+#define _CAVIUM_MMC_H_
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/io.h>
+#include <linux/mmc/host.h>
+#include <linux/of.h>
+#include <linux/scatterlist.h>
+#include <linux/semaphore.h>
+
+#define CAVIUM_MAX_MMC 4
+
+/* DMA register addresses */
+#define MIO_EMM_DMA_CFG(x) (0x00 + x->reg_off_dma)
+
+/* register addresses */
+#define MIO_EMM_CFG(x) (0x00 + 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)
+#define MIO_EMM_RSP_STS(x) (0x60 + x->reg_off)
+#define MIO_EMM_RSP_LO(x) (0x68 + x->reg_off)
+#define MIO_EMM_RSP_HI(x) (0x70 + x->reg_off)
+#define MIO_EMM_INT(x) (0x78 + x->reg_off)
+#define MIO_EMM_INT_EN(x) (0x80 + x->reg_off)
+#define MIO_EMM_WDOG(x) (0x88 + x->reg_off)
+#define MIO_EMM_SAMPLE(x) (0x90 + x->reg_off)
+#define MIO_EMM_STS_MASK(x) (0x98 + x->reg_off)
+#define MIO_EMM_RCA(x) (0xa0 + x->reg_off)
+#define MIO_EMM_BUF_IDX(x) (0xe0 + x->reg_off)
+#define MIO_EMM_BUF_DAT(x) (0xe8 + x->reg_off)
+
+struct cvm_mmc_host {
+ struct device *dev;
+ void __iomem *base;
+ void __iomem *dma_base;
+ int reg_off;
+ int reg_off_dma;
+ u64 emm_cfg;
+ u64 n_minus_one; /* OCTEON II workaround location */
+ int last_slot;
+ struct clk *clk;
+ int sys_freq;
+
+ struct mmc_request *current_req;
+ struct sg_mapping_iter smi;
+ bool dma_active;
+
+ bool has_ciu3;
+ bool big_dma_addr;
+ bool need_irq_handler_lock;
+ spinlock_t irq_handler_lock;
+ struct semaphore mmc_serializer;
+
+ 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];
+
+ void (*set_shared_power)(struct cvm_mmc_host *, int);
+ void (*acquire_bus)(struct cvm_mmc_host *);
+ void (*release_bus)(struct cvm_mmc_host *);
+ void (*int_enable)(struct cvm_mmc_host *, u64);
+ /* required on some MIPS models */
+ void (*dmar_fixup)(struct cvm_mmc_host *, struct mmc_command *,
+ struct mmc_data *, u64);
+ void (*dmar_fixup_done)(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 */
+
+ u64 clock;
+
+ u64 cached_switch;
+ u64 cached_rca;
+
+ unsigned int cmd_cnt; /* sample delay */
+ unsigned int dat_cnt; /* sample delay */
+
+ int bus_id;
+};
+
+struct cvm_mmc_cr_type {
+ u8 ctype;
+ u8 rtype;
+};
+
+struct cvm_mmc_cr_mods {
+ u8 ctype_xor;
+ u8 rtype_xor;
+};
+
+/* Bitfield definitions */
+#define MIO_EMM_CMD_SKIP_BUSY BIT_ULL(62)
+#define MIO_EMM_CMD_BUS_ID GENMASK_ULL(61, 60)
+#define MIO_EMM_CMD_VAL BIT_ULL(59)
+#define MIO_EMM_CMD_DBUF BIT_ULL(55)
+#define MIO_EMM_CMD_OFFSET GENMASK_ULL(54, 49)
+#define MIO_EMM_CMD_CTYPE_XOR GENMASK_ULL(42, 41)
+#define MIO_EMM_CMD_RTYPE_XOR GENMASK_ULL(40, 38)
+#define MIO_EMM_CMD_IDX GENMASK_ULL(37, 32)
+#define MIO_EMM_CMD_ARG GENMASK_ULL(31, 0)
+
+#define MIO_EMM_DMA_SKIP_BUSY BIT_ULL(62)
+#define MIO_EMM_DMA_BUS_ID GENMASK_ULL(61, 60)
+#define MIO_EMM_DMA_VAL BIT_ULL(59)
+#define MIO_EMM_DMA_SECTOR BIT_ULL(58)
+#define MIO_EMM_DMA_DAT_NULL BIT_ULL(57)
+#define MIO_EMM_DMA_THRES GENMASK_ULL(56, 51)
+#define MIO_EMM_DMA_REL_WR BIT_ULL(50)
+#define MIO_EMM_DMA_RW BIT_ULL(49)
+#define MIO_EMM_DMA_MULTI BIT_ULL(48)
+#define MIO_EMM_DMA_BLOCK_CNT GENMASK_ULL(47, 32)
+#define MIO_EMM_DMA_CARD_ADDR GENMASK_ULL(31, 0)
+
+#define MIO_EMM_DMA_CFG_EN BIT_ULL(63)
+#define MIO_EMM_DMA_CFG_RW BIT_ULL(62)
+#define MIO_EMM_DMA_CFG_CLR BIT_ULL(61)
+#define MIO_EMM_DMA_CFG_SWAP32 BIT_ULL(59)
+#define MIO_EMM_DMA_CFG_SWAP16 BIT_ULL(58)
+#define MIO_EMM_DMA_CFG_SWAP8 BIT_ULL(57)
+#define MIO_EMM_DMA_CFG_ENDIAN BIT_ULL(56)
+#define MIO_EMM_DMA_CFG_SIZE GENMASK_ULL(55, 36)
+#define MIO_EMM_DMA_CFG_ADR GENMASK_ULL(35, 0)
+
+#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)
+#define MIO_EMM_INT_CMD_ERR BIT_ULL(3)
+#define MIO_EMM_INT_DMA_DONE BIT_ULL(2)
+#define MIO_EMM_INT_CMD_DONE BIT_ULL(1)
+#define MIO_EMM_INT_BUF_DONE 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)
+#define MIO_EMM_RSP_STS_DMA_VAL BIT_ULL(57)
+#define MIO_EMM_RSP_STS_DMA_PEND BIT_ULL(56)
+#define MIO_EMM_RSP_STS_DBUF_ERR BIT_ULL(28)
+#define MIO_EMM_RSP_STS_DBUF BIT_ULL(23)
+#define MIO_EMM_RSP_STS_BLK_TIMEOUT BIT_ULL(22)
+#define MIO_EMM_RSP_STS_BLK_CRC_ERR BIT_ULL(21)
+#define MIO_EMM_RSP_STS_RSP_BUSYBIT BIT_ULL(20)
+#define MIO_EMM_RSP_STS_STP_TIMEOUT BIT_ULL(19)
+#define MIO_EMM_RSP_STS_STP_CRC_ERR BIT_ULL(18)
+#define MIO_EMM_RSP_STS_STP_BAD_STS BIT_ULL(17)
+#define MIO_EMM_RSP_STS_STP_VAL BIT_ULL(16)
+#define MIO_EMM_RSP_STS_RSP_TIMEOUT BIT_ULL(15)
+#define MIO_EMM_RSP_STS_RSP_CRC_ERR BIT_ULL(14)
+#define MIO_EMM_RSP_STS_RSP_BAD_STS BIT_ULL(13)
+#define MIO_EMM_RSP_STS_RSP_VAL BIT_ULL(12)
+#define MIO_EMM_RSP_STS_RSP_TYPE GENMASK_ULL(11, 9)
+#define MIO_EMM_RSP_STS_CMD_TYPE GENMASK_ULL(8, 7)
+#define MIO_EMM_RSP_STS_CMD_IDX GENMASK_ULL(6, 1)
+#define MIO_EMM_RSP_STS_CMD_DONE BIT_ULL(0)
+
+#define MIO_EMM_SAMPLE_CMD_CNT GENMASK_ULL(25, 16)
+#define MIO_EMM_SAMPLE_DAT_CNT GENMASK_ULL(9, 0)
+
+#define MIO_EMM_SWITCH_BUS_ID GENMASK_ULL(61, 60)
+#define MIO_EMM_SWITCH_EXE BIT_ULL(59)
+#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_HS_TIMING BIT_ULL(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_HI GENMASK_ULL(31, 16)
+#define MIO_EMM_SWITCH_CLK_LO GENMASK_ULL(15, 0)
+
+/* 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[];
+
+#endif