+/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2011, Marvell Semiconductor Inc.
*
- * SPDX-License-Identifier: GPL-2.0+
- *
* Back ported to the 8xx platform (from the 8260 platform) by
*/
#define SDHCI_ARGUMENT 0x08
#define SDHCI_TRANSFER_MODE 0x0C
-#define SDHCI_TRNS_DMA 0x01
-#define SDHCI_TRNS_BLK_CNT_EN 0x02
-#define SDHCI_TRNS_ACMD12 0x04
-#define SDHCI_TRNS_READ 0x10
-#define SDHCI_TRNS_MULTI 0x20
+#define SDHCI_TRNS_DMA BIT(0)
+#define SDHCI_TRNS_BLK_CNT_EN BIT(1)
+#define SDHCI_TRNS_ACMD12 BIT(2)
+#define SDHCI_TRNS_READ BIT(4)
+#define SDHCI_TRNS_MULTI BIT(5)
#define SDHCI_COMMAND 0x0E
#define SDHCI_CMD_RESP_MASK 0x03
#define SDHCI_BUFFER 0x20
#define SDHCI_PRESENT_STATE 0x24
-#define SDHCI_CMD_INHIBIT 0x00000001
-#define SDHCI_DATA_INHIBIT 0x00000002
-#define SDHCI_DOING_WRITE 0x00000100
-#define SDHCI_DOING_READ 0x00000200
-#define SDHCI_SPACE_AVAILABLE 0x00000400
-#define SDHCI_DATA_AVAILABLE 0x00000800
-#define SDHCI_CARD_PRESENT 0x00010000
-#define SDHCI_CARD_STATE_STABLE 0x00020000
-#define SDHCI_CARD_DETECT_PIN_LEVEL 0x00040000
-#define SDHCI_WRITE_PROTECT 0x00080000
+#define SDHCI_CMD_INHIBIT BIT(0)
+#define SDHCI_DATA_INHIBIT BIT(1)
+#define SDHCI_DOING_WRITE BIT(8)
+#define SDHCI_DOING_READ BIT(9)
+#define SDHCI_SPACE_AVAILABLE BIT(10)
+#define SDHCI_DATA_AVAILABLE BIT(11)
+#define SDHCI_CARD_PRESENT BIT(16)
+#define SDHCI_CARD_STATE_STABLE BIT(17)
+#define SDHCI_CARD_DETECT_PIN_LEVEL BIT(18)
+#define SDHCI_WRITE_PROTECT BIT(19)
#define SDHCI_HOST_CONTROL 0x28
-#define SDHCI_CTRL_LED 0x01
-#define SDHCI_CTRL_4BITBUS 0x02
-#define SDHCI_CTRL_HISPD 0x04
+#define SDHCI_CTRL_LED BIT(0)
+#define SDHCI_CTRL_4BITBUS BIT(1)
+#define SDHCI_CTRL_HISPD BIT(2)
#define SDHCI_CTRL_DMA_MASK 0x18
#define SDHCI_CTRL_SDMA 0x00
#define SDHCI_CTRL_ADMA1 0x08
#define SDHCI_CTRL_ADMA32 0x10
#define SDHCI_CTRL_ADMA64 0x18
-#define SDHCI_CTRL_8BITBUS 0x20
-#define SDHCI_CTRL_CD_TEST_INS 0x40
-#define SDHCI_CTRL_CD_TEST 0x80
+#define SDHCI_CTRL_8BITBUS BIT(5)
+#define SDHCI_CTRL_CD_TEST_INS BIT(6)
+#define SDHCI_CTRL_CD_TEST BIT(7)
#define SDHCI_POWER_CONTROL 0x29
#define SDHCI_POWER_ON 0x01
#define SDHCI_BLOCK_GAP_CONTROL 0x2A
#define SDHCI_WAKE_UP_CONTROL 0x2B
-#define SDHCI_WAKE_ON_INT 0x01
-#define SDHCI_WAKE_ON_INSERT 0x02
-#define SDHCI_WAKE_ON_REMOVE 0x04
+#define SDHCI_WAKE_ON_INT BIT(0)
+#define SDHCI_WAKE_ON_INSERT BIT(1)
+#define SDHCI_WAKE_ON_REMOVE BIT(2)
#define SDHCI_CLOCK_CONTROL 0x2C
#define SDHCI_DIVIDER_SHIFT 8
#define SDHCI_DIV_MASK 0xFF
#define SDHCI_DIV_MASK_LEN 8
#define SDHCI_DIV_HI_MASK 0x300
-#define SDHCI_CLOCK_CARD_EN 0x0004
-#define SDHCI_CLOCK_INT_STABLE 0x0002
-#define SDHCI_CLOCK_INT_EN 0x0001
+#define SDHCI_PROG_CLOCK_MODE BIT(5)
+#define SDHCI_CLOCK_CARD_EN BIT(2)
+#define SDHCI_CLOCK_INT_STABLE BIT(1)
+#define SDHCI_CLOCK_INT_EN BIT(0)
#define SDHCI_TIMEOUT_CONTROL 0x2E
#define SDHCI_INT_STATUS 0x30
#define SDHCI_INT_ENABLE 0x34
#define SDHCI_SIGNAL_ENABLE 0x38
-#define SDHCI_INT_RESPONSE 0x00000001
-#define SDHCI_INT_DATA_END 0x00000002
-#define SDHCI_INT_DMA_END 0x00000008
-#define SDHCI_INT_SPACE_AVAIL 0x00000010
-#define SDHCI_INT_DATA_AVAIL 0x00000020
-#define SDHCI_INT_CARD_INSERT 0x00000040
-#define SDHCI_INT_CARD_REMOVE 0x00000080
-#define SDHCI_INT_CARD_INT 0x00000100
-#define SDHCI_INT_ERROR 0x00008000
-#define SDHCI_INT_TIMEOUT 0x00010000
-#define SDHCI_INT_CRC 0x00020000
-#define SDHCI_INT_END_BIT 0x00040000
-#define SDHCI_INT_INDEX 0x00080000
-#define SDHCI_INT_DATA_TIMEOUT 0x00100000
-#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_ADMA_ERROR 0x02000000
+#define SDHCI_INT_RESPONSE BIT(0)
+#define SDHCI_INT_DATA_END BIT(1)
+#define SDHCI_INT_DMA_END BIT(3)
+#define SDHCI_INT_SPACE_AVAIL BIT(4)
+#define SDHCI_INT_DATA_AVAIL BIT(5)
+#define SDHCI_INT_CARD_INSERT BIT(6)
+#define SDHCI_INT_CARD_REMOVE BIT(7)
+#define SDHCI_INT_CARD_INT BIT(8)
+#define SDHCI_INT_ERROR BIT(15)
+#define SDHCI_INT_TIMEOUT BIT(16)
+#define SDHCI_INT_CRC BIT(17)
+#define SDHCI_INT_END_BIT BIT(18)
+#define SDHCI_INT_INDEX BIT(19)
+#define SDHCI_INT_DATA_TIMEOUT BIT(20)
+#define SDHCI_INT_DATA_CRC BIT(21)
+#define SDHCI_INT_DATA_END_BIT BIT(22)
+#define SDHCI_INT_BUS_POWER BIT(23)
+#define SDHCI_INT_ACMD12ERR BIT(24)
+#define SDHCI_INT_ADMA_ERROR BIT(25)
#define SDHCI_INT_NORMAL_MASK 0x00007FFF
#define SDHCI_INT_ERROR_MASK 0xFFFF8000
#define SDHCI_ACMD12_ERR 0x3C
-/* 3E-3F reserved */
+#define SDHCI_HOST_CONTROL2 0x3E
+#define SDHCI_CTRL_UHS_MASK 0x0007
+#define SDHCI_CTRL_UHS_SDR12 0x0000
+#define SDHCI_CTRL_UHS_SDR25 0x0001
+#define SDHCI_CTRL_UHS_SDR50 0x0002
+#define SDHCI_CTRL_UHS_SDR104 0x0003
+#define SDHCI_CTRL_UHS_DDR50 0x0004
+#define SDHCI_CTRL_HS400 0x0005 /* Non-standard */
+#define SDHCI_CTRL_VDD_180 0x0008
+#define SDHCI_CTRL_DRV_TYPE_MASK 0x0030
+#define SDHCI_CTRL_DRV_TYPE_B 0x0000
+#define SDHCI_CTRL_DRV_TYPE_A 0x0010
+#define SDHCI_CTRL_DRV_TYPE_C 0x0020
+#define SDHCI_CTRL_DRV_TYPE_D 0x0030
+#define SDHCI_CTRL_EXEC_TUNING 0x0040
+#define SDHCI_CTRL_TUNED_CLK 0x0080
+#define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000
#define SDHCI_CAPABILITIES 0x40
#define SDHCI_TIMEOUT_CLK_MASK 0x0000003F
#define SDHCI_CLOCK_BASE_SHIFT 8
#define SDHCI_MAX_BLOCK_MASK 0x00030000
#define SDHCI_MAX_BLOCK_SHIFT 16
-#define SDHCI_CAN_DO_8BIT 0x00040000
-#define SDHCI_CAN_DO_ADMA2 0x00080000
-#define SDHCI_CAN_DO_ADMA1 0x00100000
-#define SDHCI_CAN_DO_HISPD 0x00200000
-#define SDHCI_CAN_DO_SDMA 0x00400000
-#define SDHCI_CAN_VDD_330 0x01000000
-#define SDHCI_CAN_VDD_300 0x02000000
-#define SDHCI_CAN_VDD_180 0x04000000
-#define SDHCI_CAN_64BIT 0x10000000
+#define SDHCI_CAN_DO_8BIT BIT(18)
+#define SDHCI_CAN_DO_ADMA2 BIT(19)
+#define SDHCI_CAN_DO_ADMA1 BIT(20)
+#define SDHCI_CAN_DO_HISPD BIT(21)
+#define SDHCI_CAN_DO_SDMA BIT(22)
+#define SDHCI_CAN_VDD_330 BIT(24)
+#define SDHCI_CAN_VDD_300 BIT(25)
+#define SDHCI_CAN_VDD_180 BIT(26)
+#define SDHCI_CAN_64BIT BIT(28)
#define SDHCI_CAPABILITIES_1 0x44
+#define SDHCI_SUPPORT_SDR50 0x00000001
+#define SDHCI_SUPPORT_SDR104 0x00000002
+#define SDHCI_SUPPORT_DDR50 0x00000004
+#define SDHCI_USE_SDR50_TUNING 0x00002000
+
+#define SDHCI_CLOCK_MUL_MASK 0x00FF0000
+#define SDHCI_CLOCK_MUL_SHIFT 16
#define SDHCI_MAX_CURRENT 0x48
/* 55-57 reserved */
#define SDHCI_ADMA_ADDRESS 0x58
+#define SDHCI_ADMA_ADDRESS_HI 0x5c
/* 60-FB reserved */
#define SDHCI_QUIRK_BROKEN_R1B (1 << 2)
#define SDHCI_QUIRK_NO_HISPD_BIT (1 << 3)
#define SDHCI_QUIRK_BROKEN_VOLTAGE (1 << 4)
-#define SDHCI_QUIRK_NO_CD (1 << 5)
+/*
+ * SDHCI_QUIRK_BROKEN_HISPD_MODE
+ * the hardware cannot operate correctly in high-speed mode,
+ * this quirk forces the sdhci host-controller to non high-speed mode
+ */
+#define SDHCI_QUIRK_BROKEN_HISPD_MODE BIT(5)
#define SDHCI_QUIRK_WAIT_SEND_CMD (1 << 6)
-#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1 << 7)
#define SDHCI_QUIRK_USE_WIDE8 (1 << 8)
+#define SDHCI_QUIRK_NO_1_8_V (1 << 9)
/* to make gcc happy */
struct sdhci_host;
#define SDHCI_DEFAULT_BOUNDARY_ARG (7)
struct sdhci_ops {
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
- u32 (*read_l)(struct sdhci_host *host, int reg);
- u16 (*read_w)(struct sdhci_host *host, int reg);
- u8 (*read_b)(struct sdhci_host *host, int reg);
- void (*write_l)(struct sdhci_host *host, u32 val, int reg);
- void (*write_w)(struct sdhci_host *host, u16 val, int reg);
- void (*write_b)(struct sdhci_host *host, u8 val, int reg);
+ u32 (*read_l)(struct sdhci_host *host, int reg);
+ u16 (*read_w)(struct sdhci_host *host, int reg);
+ u8 (*read_b)(struct sdhci_host *host, int reg);
+ void (*write_l)(struct sdhci_host *host, u32 val, int reg);
+ void (*write_w)(struct sdhci_host *host, u16 val, int reg);
+ void (*write_b)(struct sdhci_host *host, u8 val, int reg);
#endif
+ int (*get_cd)(struct sdhci_host *host);
+ void (*set_control_reg)(struct sdhci_host *host);
+ int (*set_ios_post)(struct sdhci_host *host);
+ void (*set_clock)(struct sdhci_host *host, u32 div);
+ int (*platform_execute_tuning)(struct mmc *host, u8 opcode);
+ void (*set_delay)(struct sdhci_host *host);
};
+#if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
+#define ADMA_MAX_LEN 65532
+#ifdef CONFIG_DMA_ADDR_T_64BIT
+#define ADMA_DESC_LEN 16
+#else
+#define ADMA_DESC_LEN 8
+#endif
+#define ADMA_TABLE_NO_ENTRIES (CONFIG_SYS_MMC_MAX_BLK_COUNT * \
+ MMC_MAX_BLOCK_LEN) / ADMA_MAX_LEN
+
+#define ADMA_TABLE_SZ (ADMA_TABLE_NO_ENTRIES * ADMA_DESC_LEN)
+
+/* Decriptor table defines */
+#define ADMA_DESC_ATTR_VALID BIT(0)
+#define ADMA_DESC_ATTR_END BIT(1)
+#define ADMA_DESC_ATTR_INT BIT(2)
+#define ADMA_DESC_ATTR_ACT1 BIT(4)
+#define ADMA_DESC_ATTR_ACT2 BIT(5)
+
+#define ADMA_DESC_TRANSFER_DATA ADMA_DESC_ATTR_ACT2
+#define ADMA_DESC_LINK_DESC (ADMA_DESC_ATTR_ACT1 | ADMA_DESC_ATTR_ACT2)
+
+struct sdhci_adma_desc {
+ u8 attr;
+ u8 reserved;
+ u16 len;
+ u32 addr_lo;
+#ifdef CONFIG_DMA_ADDR_T_64BIT
+ u32 addr_hi;
+#endif
+} __packed;
+#endif
struct sdhci_host {
- char *name;
+ const char *name;
void *ioaddr;
unsigned int quirks;
unsigned int host_caps;
unsigned int version;
+ unsigned int max_clk; /* Maximum Base Clock frequency */
+ unsigned int clk_mul; /* Clock Multiplier value */
unsigned int clock;
struct mmc *mmc;
const struct sdhci_ops *ops;
struct gpio_desc pwr_gpio; /* Power GPIO */
struct gpio_desc cd_gpio; /* Card Detect GPIO */
- void (*set_control_reg)(struct sdhci_host *host);
- void (*set_clock)(int dev_index, unsigned int div);
uint voltages;
struct mmc_config cfg;
+ dma_addr_t start_addr;
+ int flags;
+#define USE_SDMA (0x1 << 0)
+#define USE_ADMA (0x1 << 1)
+#define USE_ADMA64 (0x1 << 2)
+#define USE_DMA (USE_SDMA | USE_ADMA | USE_ADMA64)
+ dma_addr_t adma_addr;
+#if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
+ struct sdhci_adma_desc *adma_desc_table;
+ uint desc_slot;
+#endif
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
}
#endif
-int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk);
+#ifdef CONFIG_BLK
+/**
+ * sdhci_setup_cfg() - Set up the configuration for DWMMC
+ *
+ * This is used to set up an SDHCI device when you are using CONFIG_BLK.
+ *
+ * This should be called from your MMC driver's probe() method once you have
+ * the information required.
+ *
+ * Generally your driver will have a platform data structure which holds both
+ * the configuration (struct mmc_config) and the MMC device info (struct mmc).
+ * For example:
+ *
+ * struct msm_sdhc_plat {
+ * struct mmc_config cfg;
+ * struct mmc mmc;
+ * };
+ *
+ * ...
+ *
+ * Inside U_BOOT_DRIVER():
+ * .platdata_auto_alloc_size = sizeof(struct msm_sdhc_plat),
+ *
+ * To access platform data:
+ * struct msm_sdhc_plat *plat = dev_get_platdata(dev);
+ *
+ * See msm_sdhci.c for an example.
+ *
+ * @cfg: Configuration structure to fill in (generally &plat->mmc)
+ * @host: SDHCI host structure
+ * @f_max: Maximum supported clock frequency in HZ (0 for default)
+ * @f_min: Minimum supported clock frequency in HZ (0 for default)
+ */
+int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
+ u32 f_max, u32 f_min);
+
+/**
+ * sdhci_bind() - Set up a new MMC block device
+ *
+ * This is used to set up an SDHCI block device when you are using CONFIG_BLK.
+ * It should be called from your driver's bind() method.
+ *
+ * See msm_sdhci.c for an example.
+ *
+ * @dev: Device to set up
+ * @mmc: Pointer to mmc structure (normally &plat->mmc)
+ * @cfg: Empty configuration structure (generally &plat->cfg). This is
+ * normally all zeroes at this point. The only purpose of passing
+ * this in is to set mmc->cfg to it.
+ * @return 0 if OK, -ve if the block device could not be created
+ */
+int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg);
+#else
+
+/**
+ * add_sdhci() - Add a new SDHCI interface
+ *
+ * This is used when you are not using CONFIG_BLK. Convert your driver over!
+ *
+ * @host: SDHCI host structure
+ * @f_max: Maximum supported clock frequency in HZ (0 for default)
+ * @f_min: Minimum supported clock frequency in HZ (0 for default)
+ * @return 0 if OK, -ve on error
+ */
+int add_sdhci(struct sdhci_host *host, u32 f_max, u32 f_min);
+#endif /* !CONFIG_BLK */
+
+void sdhci_set_uhs_timing(struct sdhci_host *host);
+#ifdef CONFIG_DM_MMC
+/* Export the operations to drivers */
+int sdhci_probe(struct udevice *dev);
+int sdhci_set_clock(struct mmc *mmc, unsigned int clock);
+extern const struct dm_mmc_ops sdhci_ops;
+#else
+#endif
+
#endif /* __SDHCI_HW_H */