diff options
| author | GUI <[email protected]> | 2025-12-26 21:04:42 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-12-26 21:04:42 +0800 |
| commit | c6498b5f65bc5f1cf7ad70f214fda56079890848 (patch) | |
| tree | 448189b2f0f75ff376e35252ee7699e207821cfd /components/drivers/include | |
| parent | 71d802c415262862734ce3c70573e512903083a6 (diff) | |
[sdio][dm] update for DM (#11078)
* [sdio][dm] import Kconfig for DM
Signed-off-by: GuEe-GUI <[email protected]>
* [sdio] fixup IRQ and mmcsd threads' stack size default
Signed-off-by: GuEe-GUI <[email protected]>
* [sdio][dm] Support DM mode
1. Support features read by DM.
2. Support regulator API in drivers.
3. Support send tuning option CMD.
4. Replace `switch_uhs_voltage` by `signal_voltage_switch`.
Signed-off-by: GuEe-GUI <[email protected]>
* [dm][sdhci] Cleanup the SDHCI
Signed-off-by: GuEe-GUI <[email protected]>
* [sdio][dm] add new SDIO/SDHCI drivers
1. SDHCI support on PCI bus
2. Synopsys DesignWare MMC Family(MMIO/PCI)
Signed-off-by: GuEe-GUI <[email protected]>
---------
Signed-off-by: GuEe-GUI <[email protected]>
Diffstat (limited to 'components/drivers/include')
| -rw-r--r-- | components/drivers/include/drivers/dev_mmcsd_core.h | 6 | ||||
| -rwxr-xr-x | components/drivers/include/drivers/dev_sdhci.h | 668 | ||||
| -rwxr-xr-x | components/drivers/include/drivers/dev_sdhci_host.h | 310 | ||||
| -rw-r--r-- | components/drivers/include/drivers/mmcsd_host.h | 25 | ||||
| -rw-r--r-- | components/drivers/include/rtdevice.h | 4 |
5 files changed, 1012 insertions, 1 deletions
diff --git a/components/drivers/include/drivers/dev_mmcsd_core.h b/components/drivers/include/drivers/dev_mmcsd_core.h index c86e9dde48..a541bc2e2d 100644 --- a/components/drivers/include/drivers/dev_mmcsd_core.h +++ b/components/drivers/include/drivers/dev_mmcsd_core.h @@ -242,6 +242,12 @@ void mmcsd_set_bus_width(struct rt_mmcsd_host *host, rt_uint32_t width); void mmcsd_set_timing(struct rt_mmcsd_host *host, rt_uint32_t timing); void mmcsd_set_data_timeout(struct rt_mmcsd_data *data, const struct rt_mmcsd_card *card); rt_uint32_t mmcsd_select_voltage(struct rt_mmcsd_host *host, rt_uint32_t ocr); +rt_err_t mmcsd_set_signal_voltage(struct rt_mmcsd_host *host, unsigned char signal_voltage); +void mmcsd_set_initial_signal_voltage(struct rt_mmcsd_host *host); +rt_err_t mmcsd_host_set_uhs_voltage(struct rt_mmcsd_host *host); +rt_err_t mmcsd_set_uhs_voltage(struct rt_mmcsd_host *host, rt_uint32_t ocr); +rt_err_t mmcsd_send_tuning(struct rt_mmcsd_host *host, rt_uint32_t opcode, rt_err_t *cmd_error); +rt_err_t mmcsd_send_abort_tuning(struct rt_mmcsd_host *host, rt_uint32_t opcode); void mmcsd_change(struct rt_mmcsd_host *host); void mmcsd_detect(void *param); void mmcsd_host_init(struct rt_mmcsd_host *host); diff --git a/components/drivers/include/drivers/dev_sdhci.h b/components/drivers/include/drivers/dev_sdhci.h new file mode 100755 index 0000000000..be6e427907 --- /dev/null +++ b/components/drivers/include/drivers/dev_sdhci.h @@ -0,0 +1,668 @@ +/* + * Copyright (c) 2006-2024 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-08-16 zhujiale first version + */ + +#ifndef __DEV_SDHCI_H__ +#define __DEV_SDHCI_H__ + +#include <drivers/misc.h> +#include <drivers/mmcsd_cmd.h> +#include <drivers/mmcsd_host.h> +#include <drivers/dev_sdhci_host.h> +#include <drivers/dev_mmcsd_core.h> + +#define RT_SDHCI_MAX_TUNING_LOOP 40 +/* + * Controller registers + */ +#define RT_SDHCI_DMA_ADDRESS 0x00 +#define RT_SDHCI_ARGUMENT2 RT_SDHCI_DMA_ADDRESS +#define RT_SDHCI_32BIT_BLK_CNT RT_SDHCI_DMA_ADDRESS + +#define RT_SDHCI_BLOCK_SIZE 0x04 +#define RT_SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF)) + +#define RT_SDHCI_BLOCK_COUNT 0x06 + +#define RT_SDHCI_ARGUMENT 0x08 + +#define RT_SDHCI_TRANSFER_MODE 0x0c +#define RT_SDHCI_TRNS_DMA 0x01 +#define RT_SDHCI_TRNS_BLK_CNT_EN 0x02 +#define RT_SDHCI_TRNS_AUTO_CMD12 0x04 +#define RT_SDHCI_TRNS_AUTO_CMD23 0x08 +#define RT_SDHCI_TRNS_AUTO_SEL 0x0c +#define RT_SDHCI_TRNS_READ 0x10 +#define RT_SDHCI_TRNS_MULTI 0x20 + +#define RT_SDHCI_COMMAND 0x0e +#define RT_SDHCI_CMD_RESP_MASK 0x03 +#define RT_SDHCI_CMD_CRC 0x08 +#define RT_SDHCI_CMD_INDEX 0x10 +#define RT_SDHCI_CMD_DATA 0x20 +#define RT_SDHCI_CMD_ABORTCMD 0xc0 + +#define RT_SDHCI_CMD_RESP_NONE 0x00 +#define RT_SDHCI_CMD_RESP_LONG 0x01 +#define RT_SDHCI_CMD_RESP_SHORT 0x02 +#define RT_SDHCI_CMD_RESP_SHORT_BUSY 0x03 + +#define RT_SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff)) +#define RT_SDHCI_GET_CMD(c) ((c >> 8) & 0x3f) + +#define RT_SDHCI_RESPONSE 0x10 + +#define RT_SDHCI_BUFFER 0x20 + +#define RT_SDHCI_PRESENT_STATE 0x24 +#define RT_SDHCI_CMD_INHIBIT 0x00000001 +#define RT_SDHCI_DATA_INHIBIT 0x00000002 +#define RT_SDHCI_DOING_WRITE 0x00000100 +#define RT_SDHCI_DOING_READ 0x00000200 +#define RT_SDHCI_SPACE_AVAILABLE 0x00000400 +#define RT_SDHCI_DATA_AVAILABLE 0x00000800 +#define RT_SDHCI_CARD_PRESENT 0x00010000 +#define RT_SDHCI_CARD_PRES_SHIFT 16 +#define RT_SDHCI_CD_STABLE 0x00020000 +#define RT_SDHCI_CD_LVL 0x00040000 +#define RT_SDHCI_CD_LVL_SHIFT 18 +#define RT_SDHCI_WRITE_PROTECT 0x00080000 +#define RT_SDHCI_DATA_LVL_MASK 0x00f00000 +#define RT_SDHCI_DATA_LVL_SHIFT 20 +#define RT_SDHCI_DATA_0_LVL_MASK 0x00100000 +#define RT_SDHCI_CMD_LVL 0x01000000 + +#define RT_SDHCI_HOST_CONTROL 0x28 +#define RT_SDHCI_CTRL_LED 0x01 +#define RT_SDHCI_CTRL_4BITBUS 0x02 +#define RT_SDHCI_CTRL_HISPD 0x04 +#define RT_SDHCI_CTRL_DMA_MASK 0x18 +#define RT_SDHCI_CTRL_SDMA 0x00 +#define RT_SDHCI_CTRL_ADMA1 0x08 +#define RT_SDHCI_CTRL_ADMA32 0x10 +#define RT_SDHCI_CTRL_ADMA64 0x18 +#define RT_SDHCI_CTRL_ADMA3 0x18 +#define RT_SDHCI_CTRL_8BITBUS 0x20 +#define RT_SDHCI_CTRL_CDTEST_INS 0x40 +#define RT_SDHCI_CTRL_CDTEST_EN 0x80 + +#define RT_SDHCI_POWER_CONTROL 0x29 +#define RT_SDHCI_POWER_ON 0x01 +#define RT_SDHCI_POWER_180 0x0a +#define RT_SDHCI_POWER_300 0x0c +#define RT_SDHCI_POWER_330 0x0e +/* + * VDD2 - UHS2 or PCIe/NVMe + * VDD2 power on/off and voltage select + */ +#define RT_SDHCI_VDD2_POWER_ON 0x10 +#define RT_SDHCI_VDD2_POWER_120 0x80 +#define RT_SDHCI_VDD2_POWER_180 0xa0 + +#define RT_SDHCI_BLOCK_GAP_CONTROL 0x2a + +#define RT_SDHCI_WAKE_UP_CONTROL 0x2b +#define RT_SDHCI_WAKE_ON_INT 0x01 +#define RT_SDHCI_WAKE_ON_INSERT 0x02 +#define RT_SDHCI_WAKE_ON_REMOVE 0x04 + +#define RT_SDHCI_CLOCK_CONTROL 0x2c +#define RT_SDHCI_DIVIDER_SHIFT 8 +#define RT_SDHCI_DIVIDER_HI_SHIFT 6 +#define RT_SDHCI_DIV_MASK 0xff +#define RT_SDHCI_DIV_MASK_LEN 8 +#define RT_SDHCI_DIV_HI_MASK 0x300 +#define RT_SDHCI_PROG_CLOCK_MODE 0x0020 +#define RT_SDHCI_CLOCK_CARD_EN 0x0004 +#define RT_SDHCI_CLOCK_PLL_EN 0x0008 +#define RT_SDHCI_CLOCK_INT_STABLE 0x0002 +#define RT_SDHCI_CLOCK_INT_EN 0x0001 + +#define RT_SDHCI_TIMEOUT_CONTROL 0x2e + +#define RT_SDHCI_SOFTWARE_RESET 0x2f +#define RT_SDHCI_RESET_ALL 0x01 +#define RT_SDHCI_RESET_CMD 0x02 +#define RT_SDHCI_RESET_DATA 0x04 + +#define RT_SDHCI_INT_STATUS 0x30 +#define RT_SDHCI_INT_ENABLE 0x34 +#define RT_SDHCI_SIGNAL_ENABLE 0x38 +#define RT_SDHCI_INT_RESPONSE 0x00000001 +#define RT_SDHCI_INT_DATA_END 0x00000002 +#define RT_SDHCI_INT_BLK_GAP 0x00000004 +#define RT_SDHCI_INT_DMA_END 0x00000008 +#define RT_SDHCI_INT_SPACE_AVAIL 0x00000010 +#define RT_SDHCI_INT_DATA_AVAIL 0x00000020 +#define RT_SDHCI_INT_CARD_INSERT 0x00000040 +#define RT_SDHCI_INT_CARD_REMOVE 0x00000080 +#define RT_SDHCI_INT_CARD_INT 0x00000100 +#define RT_SDHCI_INT_RETUNE 0x00001000 +#define RT_SDHCI_INT_CQE 0x00004000 +#define RT_SDHCI_INT_ERROR 0x00008000 +#define RT_SDHCI_INT_TIMEOUT 0x00010000 +#define RT_SDHCI_INT_CRC 0x00020000 +#define RT_SDHCI_INT_END_BIT 0x00040000 +#define RT_SDHCI_INT_INDEX 0x00080000 +#define RT_SDHCI_INT_DATA_TIMEOUT 0x00100000 +#define RT_SDHCI_INT_DATA_CRC 0x00200000 +#define RT_SDHCI_INT_DATA_END_BIT 0x00400000 +#define RT_SDHCI_INT_BUS_POWER 0x00800000 +#define RT_SDHCI_INT_AUTO_CMD_ERR 0x01000000 +#define RT_SDHCI_INT_ADMA_ERROR 0x02000000 + +#define RT_SDHCI_INT_NORMAL_MASK 0x00007fff +#define RT_SDHCI_INT_ERROR_MASK 0xffff8000 + +#define RT_SDHCI_INT_CMD_MASK (RT_SDHCI_INT_RESPONSE | RT_SDHCI_INT_TIMEOUT | \ + RT_SDHCI_INT_CRC | RT_SDHCI_INT_END_BIT | \ + RT_SDHCI_INT_INDEX | RT_SDHCI_INT_AUTO_CMD_ERR) +#define RT_SDHCI_INT_DATA_MASK (RT_SDHCI_INT_DATA_END | RT_SDHCI_INT_DMA_END | \ + RT_SDHCI_INT_DATA_AVAIL | RT_SDHCI_INT_SPACE_AVAIL | \ + RT_SDHCI_INT_DATA_TIMEOUT | RT_SDHCI_INT_DATA_CRC | \ + RT_SDHCI_INT_DATA_END_BIT | RT_SDHCI_INT_ADMA_ERROR | \ + RT_SDHCI_INT_BLK_GAP) +#define RT_SDHCI_INT_ALL_MASK ((rt_uint32_t)-1) + +#define RT_SDHCI_CQE_INT_ERR_MASK (RT_SDHCI_INT_ADMA_ERROR | RT_SDHCI_INT_BUS_POWER | \ + RT_SDHCI_INT_DATA_END_BIT | RT_SDHCI_INT_DATA_CRC | \ + RT_SDHCI_INT_DATA_TIMEOUT | RT_SDHCI_INT_INDEX | \ + RT_SDHCI_INT_END_BIT | RT_SDHCI_INT_CRC | RT_SDHCI_INT_TIMEOUT) + +#define RT_SDHCI_CQE_INT_MASK (RT_SDHCI_CQE_INT_ERR_MASK | RT_SDHCI_INT_CQE) + +#define RT_SDHCI_AUTO_CMD_STATUS 0x3c +#define RT_SDHCI_AUTO_CMD_TIMEOUT 0x00000002 +#define RT_SDHCI_AUTO_CMD_CRC 0x00000004 +#define RT_SDHCI_AUTO_CMD_END_BIT 0x00000008 +#define RT_SDHCI_AUTO_CMD_INDEX 0x00000010 + +#define RT_SDHCI_HOST_CONTROL2 0x3e +#define RT_SDHCI_CTRL_UHS_MASK 0x0007 +#define RT_SDHCI_CTRL_UHS_SDR12 0x0000 +#define RT_SDHCI_CTRL_UHS_SDR25 0x0001 +#define RT_SDHCI_CTRL_UHS_SDR50 0x0002 +#define RT_SDHCI_CTRL_UHS_SDR104 0x0003 +#define RT_SDHCI_CTRL_UHS_DDR50 0x0004 +#define RT_SDHCI_CTRL_HS400 0x0005 /* Non-standard */ +#define RT_SDHCI_CTRL_VDD_180 0x0008 +#define RT_SDHCI_CTRL_DRV_TYPE_MASK 0x0030 +#define RT_SDHCI_CTRL_DRV_TYPE_B 0x0000 +#define RT_SDHCI_CTRL_DRV_TYPE_A 0x0010 +#define RT_SDHCI_CTRL_DRV_TYPE_C 0x0020 +#define RT_SDHCI_CTRL_DRV_TYPE_D 0x0030 +#define RT_SDHCI_CTRL_EXEC_TUNING 0x0040 +#define RT_SDHCI_CTRL_TUNED_CLK 0x0080 +#define RT_SDHCI_CMD23_ENABLE 0x0800 +#define RT_SDHCI_CTRL_V4_MODE 0x1000 +#define RT_SDHCI_CTRL_64BIT_ADDR 0x2000 +#define RT_SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000 + +#define RT_SDHCI_CAPABILITIES 0x40 +#define RT_SDHCI_TIMEOUT_CLK_MASK RT_GENMASK(5, 0) +#define RT_SDHCI_TIMEOUT_CLK_SHIFT 0 +#define RT_SDHCI_TIMEOUT_CLK_UNIT 0x00000080 +#define RT_SDHCI_CLOCK_BASE_MASK RT_GENMASK(13, 8) +#define RT_SDHCI_CLOCK_BASE_SHIFT 8 +#define RT_SDHCI_CLOCK_V3_BASE_MASK RT_GENMASK(15, 8) +#define RT_SDHCI_MAX_BLOCK_MASK 0x00030000 +#define RT_SDHCI_MAX_BLOCK_SHIFT 16 +#define RT_SDHCI_CAN_DO_8BIT 0x00040000 +#define RT_SDHCI_CAN_DO_ADMA2 0x00080000 +#define RT_SDHCI_CAN_DO_ADMA1 0x00100000 +#define RT_SDHCI_CAN_DO_HISPD 0x00200000 +#define RT_SDHCI_CAN_DO_SDMA 0x00400000 +#define RT_SDHCI_CAN_DO_SUSPEND 0x00800000 +#define RT_SDHCI_CAN_VDD_330 0x01000000 +#define RT_SDHCI_CAN_VDD_300 0x02000000 +#define RT_SDHCI_CAN_VDD_180 0x04000000 +#define RT_SDHCI_CAN_64BIT_V4 0x08000000 +#define RT_SDHCI_CAN_64BIT 0x10000000 + +#define RT_SDHCI_CAPABILITIES_1 0x44 +#define RT_SDHCI_SUPPORT_SDR50 0x00000001 +#define RT_SDHCI_SUPPORT_SDR104 0x00000002 +#define RT_SDHCI_SUPPORT_DDR50 0x00000004 +#define RT_SDHCI_DRIVER_TYPE_A 0x00000010 +#define RT_SDHCI_DRIVER_TYPE_C 0x00000020 +#define RT_SDHCI_DRIVER_TYPE_D 0x00000040 +#define RT_SDHCI_RETUNING_TIMER_COUNT_MASK RT_GENMASK(11, 8) +#define RT_SDHCI_USE_SDR50_TUNING 0x00002000 +#define RT_SDHCI_RETUNING_MODE_MASK RT_GENMASK(15, 14) +#define RT_SDHCI_CLOCK_MUL_MASK RT_GENMASK(23, 16) +#define RT_SDHCI_CAN_DO_ADMA3 0x08000000 +#define RT_SDHCI_SUPPORT_HS400 0x80000000 /* Non-standard */ + +#define RT_SDHCI_MAX_CURRENT 0x48 +#define RT_SDHCI_MAX_CURRENT_LIMIT RT_GENMASK(7, 0) +#define RT_SDHCI_MAX_CURRENT_330_MASK RT_GENMASK(7, 0) +#define RT_SDHCI_MAX_CURRENT_300_MASK RT_GENMASK(15, 8) +#define RT_SDHCI_MAX_CURRENT_180_MASK RT_GENMASK(23, 16) +#define RT_SDHCI_MAX_CURRENT_MULTIPLIER 4 + +/* 4C-4F reserved for more max current */ + +#define RT_SDHCI_SET_ACMD12_ERROR 0x50 +#define RT_SDHCI_SET_INT_ERROR 0x52 + +#define RT_SDHCI_ADMA_ERROR 0x54 + +/* 55-57 reserved */ + +#define RT_SDHCI_ADMA_ADDRESS 0x58 +#define RT_SDHCI_ADMA_ADDRESS_HI 0x5c + +/* 60-FB reserved */ + +#define RT_SDHCI_PRESET_FOR_HIGH_SPEED 0x64 +#define RT_SDHCI_PRESET_FOR_SDR12 0x66 +#define RT_SDHCI_PRESET_FOR_SDR25 0x68 +#define RT_SDHCI_PRESET_FOR_SDR50 0x6a +#define RT_SDHCI_PRESET_FOR_SDR104 0x6c +#define RT_SDHCI_PRESET_FOR_DDR50 0x6e +#define RT_SDHCI_PRESET_FOR_HS400 0x74 /* Non-standard */ +#define RT_SDHCI_PRESET_DRV_MASK RT_GENMASK(15, 14) + +#define RT_SDHCI_PRESET_CLKGEN_SEL RT_BIT(10) +#define RT_SDHCI_PRESET_SDCLK_FREQ_MASK RT_GENMASK(9, 0) + +#define RT_SDHCI_SLOT_INT_STATUS 0xfc + +#define RT_SDHCI_HOST_VERSION 0xfe +#define RT_SDHCI_VENDOR_VER_MASK 0xff00 +#define RT_SDHCI_VENDOR_VER_SHIFT 8 +#define RT_SDHCI_SPEC_VER_MASK 0x00ff +#define RT_SDHCI_SPEC_VER_SHIFT 0 +#define RT_SDHCI_SPEC_100 0 +#define RT_SDHCI_SPEC_200 1 +#define RT_SDHCI_SPEC_300 2 +#define RT_SDHCI_SPEC_400 3 +#define RT_SDHCI_SPEC_410 4 +#define RT_SDHCI_SPEC_420 5 + +/* + * End of controller registers. + */ + +#define RT_SDHCI_MAX_DIV_SPEC_200 256 +#define RT_SDHCI_MAX_DIV_SPEC_300 2046 + +/* + * Host SDMA buffer boundary. Valid values from 4K to 512K in powers of 2. + */ +#define RT_SDHCI_DEFAULT_BOUNDARY_SIZE (512 * 1024) +#define RT_SDHCI_DEFAULT_BOUNDARY_ARG (rt_ilog2(RT_SDHCI_DEFAULT_BOUNDARY_SIZE) - 12) +#define RT_SDHCI_MAX_SEGS 128 + +/* Allow for a command request and a data request at the same time */ +#define RT_SDHCI_MAX_MRQS 2 +#define MMC_CMD_TRANSFER_TIME (10 * 1000000L) /* max 10 ms */ + +enum rt_sdhci_cookie +{ + RT_SDHCI_COOKIE_UNMAPPED, + RT_SDHCI_COOKIE_PRE_MAPPED, + RT_SDHCI_COOKIE_MAPPED, +}; + +struct rt_sdhci_host +{ + const char *hw_name; /* Hardware bus name */ + + unsigned int quirks; /* Deviations from spec. */ + +/* Controller doesn't honor resets unless we touch the clock register */ +#define RT_SDHCI_QUIRK_CLOCK_BEFORE_RESET (1 << 0) +/* Controller has bad caps bits, but really supports DMA */ +#define RT_SDHCI_QUIRK_FORCE_DMA (1 << 1) +/* Controller doesn't like to be reset when there is no card inserted. */ +#define RT_SDHCI_QUIRK_NO_CARD_NO_RESET (1 << 2) +/* Controller doesn't like clearing the power reg before a change */ +#define RT_SDHCI_QUIRK_SINGLE_POWER_WRITE (1 << 3) +/* Controller has an unusable DMA engine */ +#define RT_SDHCI_QUIRK_BROKEN_DMA (1 << 5) +/* Controller has an unusable ADMA engine */ +#define RT_SDHCI_QUIRK_BROKEN_ADMA (1 << 6) +/* Controller can only DMA from 32-bit aligned addresses */ +#define RT_SDHCI_QUIRK_32BIT_DMA_ADDR (1 << 7) +/* Controller can only DMA chunk sizes that are a multiple of 32 bits */ +#define RT_SDHCI_QUIRK_32BIT_DMA_SIZE (1 << 8) +/* Controller can only ADMA chunks that are a multiple of 32 bits */ +#define RT_SDHCI_QUIRK_32BIT_ADMA_SIZE (1 << 9) +/* Controller needs to be reset after each request to stay stable */ +#define RT_SDHCI_QUIRK_RESET_AFTER_REQUEST (1 << 10) +/* Controller needs voltage and power writes to happen separately */ +#define RT_SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1 << 11) +/* Controller provides an incorrect timeout value for transfers */ +#define RT_SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1 << 12) +/* Controller has an issue with buffer bits for small transfers */ +#define RT_SDHCI_QUIRK_BROKEN_SMALL_PIO (1 << 13) +/* Controller does not provide transfer-complete interrupt when not busy */ +#define RT_SDHCI_QUIRK_NO_BUSY_IRQ (1 << 14) +/* Controller has unreliable card detection */ +#define RT_SDHCI_QUIRK_BROKEN_CARD_DETECTION (1 << 15) +/* Controller reports inverted write-protect state */ +#define RT_SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1 << 16) +/* Controller has unusable command queue engine */ +#define RT_SDHCI_QUIRK_BROKEN_CQE (1 << 17) +/* Controller does not like fast PIO transfers */ +#define RT_SDHCI_QUIRK_PIO_NEEDS_DELAY (1 << 18) +/* Controller does not have a LED */ +#define RT_SDHCI_QUIRK_NO_LED (1 << 19) +/* Controller has to be forced to use block size of 2048 bytes */ +#define RT_SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1 << 20) +/* Controller cannot do multi-block transfers */ +#define RT_SDHCI_QUIRK_NO_MULTIBLOCK (1 << 21) +/* Controller can only handle 1-bit data transfers */ +#define RT_SDHCI_QUIRK_FORCE_1_BIT_DATA (1 << 22) +/* Controller needs 10ms delay between applying power and clock */ +#define RT_SDHCI_QUIRK_DELAY_AFTER_POWER (1 << 23) +/* Controller uses SDCLK instead of TMCLK for data timeouts */ +#define RT_SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1 << 24) +/* Controller reports wrong base clock capability */ +#define RT_SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN (1 << 25) +/* Controller cannot support End Attribute in NOP ADMA descriptor */ +#define RT_SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC (1 << 26) +/* Controller uses Auto CMD12 command to stop the transfer */ +#define RT_SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 (1 << 28) +/* Controller doesn't have HISPD bit field in HI-SPEED SD card */ +#define RT_SDHCI_QUIRK_NO_HISPD_BIT (1 << 29) +/* Controller treats ADMA descriptors with length 0000h incorrectly */ +#define RT_SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC (1 << 30) +/* The read-only detection via RT_SDHCI_PRESENT_STATE register is unstable */ +#define RT_SDHCI_QUIRK_UNSTABLE_RO_DETECT (1 << 31) + + unsigned int quirks2; /* More deviations from spec. */ + +#define RT_SDHCI_QUIRK2_HOST_OFF_CARD_ON (1 << 0) +#define RT_SDHCI_QUIRK2_HOST_NO_CMD23 (1 << 1) +/* The system physically doesn't support 1.8v, even if the host does */ +#define RT_SDHCI_QUIRK2_NO_1_8_V (1 << 2) +#define RT_SDHCI_QUIRK2_PRESET_VALUE_BROKEN (1 << 3) +#define RT_SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON (1 << 4) +/* Controller has a non-standard host control register */ +#define RT_SDHCI_QUIRK2_BROKEN_HOST_CONTROL (1 << 5) +/* Controller does not support HS200 */ +#define RT_SDHCI_QUIRK2_BROKEN_HS200 (1 << 6) +/* Controller does not support DDR50 */ +#define RT_SDHCI_QUIRK2_BROKEN_DDR50 (1 << 7) +/* Stop command (CMD12) can set Transfer Complete when not using MMC_RSP_BUSY */ +#define RT_SDHCI_QUIRK2_STOP_WITH_TC (1 << 8) +/* Controller does not support 64-bit DMA */ +#define RT_SDHCI_QUIRK2_BROKEN_64_BIT_DMA (1 << 9) +/* need clear transfer mode register before send cmd */ +#define RT_SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD (1 << 10) +/* Capability register bit-63 indicates HS400 support */ +#define RT_SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400 (1 << 11) +/* forced tuned clock */ +#define RT_SDHCI_QUIRK2_TUNING_WORK_AROUND (1 << 12) +/* disable the block count for single block transactions */ +#define RT_SDHCI_QUIRK2_SUPPORT_SINGLE (1 << 13) +/* Controller broken with using ACMD23 */ +#define RT_SDHCI_QUIRK2_ACMD23_BROKEN (1 << 14) +/* Broken Clock divider zero in controller */ +#define RT_SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN (1 << 15) +/* Controller has CRC in 136 bit Command Response */ +#define RT_SDHCI_QUIRK2_RSP_136_HAS_CRC (1 << 16) + +#define RT_SDHCI_QUIRK2_DISABLE_HW_TIMEOUT (1 << 17) + +#define RT_SDHCI_QUIRK2_USE_32BIT_BLK_CNT (1 << 18) +/* Issue CMD and DATA reset together */ +#define RT_SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER (1 << 19) + + void *data_buf; + + int irq; /* Device IRQ */ + void *ioaddr; /* Mapped address */ + char *bounce_buffer; /* For packing SDMA reads/writes */ + rt_uint64_t bounce_addr; + unsigned int bounce_buffer_size; + + const struct rt_sdhci_ops *ops; /* Low level hw interface */ + + /* Internal data */ + struct rt_mmc_host *mmc; /* MMC structure */ + struct rt_mmc_host_ops mmc_host_ops; /* MMC host ops */ + rt_uint64_t dma_mask; /* custom DMA mask */ + + rt_spinlock_t lock; + int flags; /* Host attributes */ +#define RT_SDHCI_USE_SDMA (1 << 0) /* Host is SDMA capable */ +#define RT_SDHCI_USE_ADMA (1 << 1) /* Host is ADMA capable */ +#define RT_SDHCI_REQ_USE_DMA (1 << 2) /* Use DMA for this req. */ +#define RT_SDHCI_DEVICE_DEAD (1 << 3) /* Device unresponsive */ +#define RT_SDHCI_SDR50_NEEDS_TUNING (1 << 4) /* SDR50 needs tuning */ +#define RT_SDHCI_AUTO_CMD12 (1 << 6) /* Auto CMD12 support */ +#define RT_SDHCI_AUTO_CMD23 (1 << 7) /* Auto CMD23 support */ +#define RT_SDHCI_PV_ENABLED (1 << 8) /* Preset value enabled */ +#define RT_SDHCI_USE_64_BIT_DMA (1 << 12) /* Use 64-bit DMA */ +#define RT_SDHCI_HS400_TUNING (1 << 13) /* Tuning for HS400 */ +#define RT_SDHCI_SIGNALING_330 (1 << 14) /* Host is capable of 3.3V signaling */ +#define RT_SDHCI_SIGNALING_180 (1 << 15) /* Host is capable of 1.8V signaling */ +#define RT_SDHCI_SIGNALING_120 (1 << 16) /* Host is capable of 1.2V signaling */ + + unsigned int version; /* RT_SDHCI spec. version */ + + unsigned int max_clk; /* Max possible freq (MHz) */ + unsigned int timeout_clk; /* Timeout freq (KHz) */ + rt_uint8_t max_timeout_count; /* Vendor specific max timeout count */ + unsigned int clk_mul; /* Clock Muliplier value */ + + unsigned int clock; /* Current clock (MHz) */ + rt_uint8_t pwr; /* Current voltage */ + rt_uint8_t drv_type; /* Current UHS-I driver type */ + rt_bool_t reinit_uhs; /* Force UHS-related re-initialization */ + + rt_bool_t runtime_suspended; /* Host is runtime suspended */ + rt_bool_t bus_on; /* Bus power prevents runtime suspend */ + rt_bool_t preset_enabled; /* Preset is enabled */ + rt_bool_t pending_reset; /* Cmd/data reset is pending */ + rt_bool_t irq_wake_enabled; /* IRQ wakeup is enabled */ + rt_bool_t v4_mode; /* Host Version 4 Enable */ + rt_bool_t always_defer_done; /* Always defer to complete requests */ + + struct rt_mmcsd_req *mrqs_done[RT_SDHCI_MAX_MRQS]; /* Requests done */ + struct rt_mmcsd_cmd *cmd; /* Current command */ + struct rt_mmcsd_cmd *data_cmd; /* Current data command */ + struct rt_mmcsd_cmd *deferred_cmd; /* Deferred command */ + struct rt_mmcsd_data *data; /* Current data request */ + unsigned int data_early : 1; /* Data finished before cmd */ + + unsigned int blocks; /* remaining PIO blocks */ + rt_size_t align_buffer_sz; /* Bounce buffer size */ + rt_uint64_t align_addr; /* Mapped bounce buffer */ + + struct rt_workqueue *complete_wq; /* Request completion wq */ + struct rt_work complete_work; /* Request completion work */ + + struct rt_workqueue *irq_wq; + struct rt_work irq_work; + + struct rt_timer timer; /* Timer for timeouts */ + struct rt_timer data_timer; /* Timer for data timeouts */ + + rt_uint32_t caps; /* CAPABILITY_0 */ + rt_uint32_t caps1; /* CAPABILITY_1 */ + rt_bool_t read_caps; /* Capability flags have been read */ + + rt_bool_t sdhci_core_to_disable_vqmmc; /* sdhci core can disable vqmmc */ + unsigned int ocr_avail_sdio; /* OCR bit masks */ + unsigned int ocr_avail_sd; + unsigned int ocr_avail_mmc; + rt_uint32_t ocr_mask; /* available voltages */ + + unsigned timing; /* Current timing */ + + rt_uint32_t thread_isr; + + rt_uint32_t ier; /* Cached registers */ + + rt_bool_t cqe_on; /* CQE is operating */ + rt_uint32_t cqe_ier; /* CQE interrupt mask */ + rt_uint32_t cqe_err_ier; /* CQE error interrupt mask */ + + rt_wqueue_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */ + unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */ + + unsigned int tuning_count; /* Timer count for re-tuning */ + unsigned int tuning_mode; /* Re-tuning mode supported by host */ + unsigned int tuning_err; /* Error code for re-tuning */ +#define RT_SDHCI_TUNING_MODE_1 0 +#define RT_SDHCI_TUNING_MODE_2 1 +#define RT_SDHCI_TUNING_MODE_3 2 + + int tuning_delay; + int tuning_loop_count; + rt_uint32_t sdma_boundary; + rt_uint64_t data_timeout; + + rt_ubase_t private[]; +}; + +struct rt_sdhci_ops +{ + rt_uint32_t (*read_l)(struct rt_sdhci_host *host, int reg); + rt_uint16_t (*read_w)(struct rt_sdhci_host *host, int reg); + rt_uint8_t (*read_b)(struct rt_sdhci_host *host, int reg); + void (*write_l)(struct rt_sdhci_host *host, rt_uint32_t val, int reg); + void (*write_w)(struct rt_sdhci_host *host, rt_uint16_t val, int reg); + void (*write_b)(struct rt_sdhci_host *host, rt_uint8_t val, int reg); + void (*set_clock)(struct rt_sdhci_host *host, unsigned int clock); + void (*set_power)(struct rt_sdhci_host *host, unsigned char mode, unsigned short vdd); + rt_uint32_t (*irq)(struct rt_sdhci_host *host, rt_uint32_t intmask); + int (*set_dma_mask)(struct rt_sdhci_host *host); + int (*enable_dma)(struct rt_sdhci_host *host); + unsigned int (*get_max_clock)(struct rt_sdhci_host *host); + unsigned int (*get_min_clock)(struct rt_sdhci_host *host); + unsigned int (*get_timeout_clock)(struct rt_sdhci_host *host); + unsigned int (*get_max_timeout_count)(struct rt_sdhci_host *host); + void (*set_timeout)(struct rt_sdhci_host *host, struct rt_mmcsd_cmd *cmd); + void (*set_bus_width)(struct rt_sdhci_host *host, int width); + unsigned int (*get_ro)(struct rt_sdhci_host *host); + void (*reset)(struct rt_sdhci_host *host, rt_uint8_t mask); + int (*platform_execute_tuning)(struct rt_sdhci_host *host, rt_uint32_t opcode); + void (*set_uhs_signaling)(struct rt_sdhci_host *host, unsigned int uhs); + void (*hw_reset)(struct rt_sdhci_host *host); + void (*card_event)(struct rt_sdhci_host *host); + void (*voltage_switch)(struct rt_sdhci_host *host); + void (*request_done)(struct rt_sdhci_host *host, struct rt_mmcsd_req *mrq); +}; + +rt_inline void rt_sdhci_writel(struct rt_sdhci_host *host, rt_uint32_t val, int reg) +{ + if (host->ops->write_l) + { + host->ops->write_l(host, val, reg); + } + else + { + HWREG32(host->ioaddr + reg) = val; + } +} + +rt_inline void rt_sdhci_writew(struct rt_sdhci_host *host, rt_uint16_t val, int reg) +{ + if (host->ops->write_w) + { + host->ops->write_w(host, val, reg); + } + else + { + HWREG16(host->ioaddr + reg) = val; + } +} + +rt_inline void rt_sdhci_writeb(struct rt_sdhci_host *host, rt_uint8_t val, int reg) +{ + if (host->ops->write_b) + { + host->ops->write_b(host, val, reg); + } + else + { + HWREG8(host->ioaddr + reg) = val; + } +} + +rt_inline rt_uint32_t rt_sdhci_readl(struct rt_sdhci_host *host, int reg) +{ + if (host->ops->read_l) + { + return host->ops->read_l(host, reg); + } + + return HWREG32(host->ioaddr + reg); +} + +rt_inline rt_uint16_t rt_sdhci_readw(struct rt_sdhci_host *host, int reg) +{ + if (host->ops->read_w) + { + return host->ops->read_w(host, reg); + } + + return HWREG16(host->ioaddr + reg); +} + +rt_inline rt_uint8_t rt_sdhci_readb(struct rt_sdhci_host *host, int reg) +{ + if (host->ops->read_b) + { + return host->ops->read_b(host, reg); + } + + return HWREG8(host->ioaddr + reg); +} + +struct rt_sdhci_host *rt_sdhci_alloc_host(struct rt_device *dev, rt_size_t priv_size); +void rt_sdhci_free_host(struct rt_sdhci_host *host); + +rt_inline void *rt_sdhci_priv(struct rt_sdhci_host *host) +{ + return host->private; +} + +void rt_sdhci_read_caps(struct rt_sdhci_host *host, const rt_uint16_t *ver, + const rt_uint32_t *caps, const rt_uint32_t *caps1); +int rt_sdhci_setup_host(struct rt_sdhci_host *host); +void rt_sdhci_cleanup_host(struct rt_sdhci_host *host); +int rt_sdhci_set_and_add_host(struct rt_sdhci_host *host); +int rt_sdhci_init_host(struct rt_sdhci_host *host); +void rt_sdhci_uninit_host(struct rt_sdhci_host *host, rt_bool_t dead); + +rt_uint16_t rt_sdhci_clk_set(struct rt_sdhci_host *host, unsigned int clock, unsigned int *actual_clock); +void rt_sdhci_set_clock(struct rt_sdhci_host *host, unsigned int clock); +void rt_sdhci_clk_enable(struct rt_sdhci_host *host, rt_uint16_t clk); +void rt_sdhci_set_power(struct rt_sdhci_host *host, unsigned char mode,unsigned short vdd); +void rt_read_reg(struct rt_sdhci_host* host); + +void rt_sdhci_set_power_and_bus_voltage(struct rt_sdhci_host *host, unsigned char mode, unsigned short vdd); +void rt_sdhci_set_power_with_noreg(struct rt_sdhci_host *host, unsigned char mode, unsigned short vdd); +void rt_sdhci_start_request(struct rt_mmc_host *mmc, struct rt_mmcsd_req *mrq); +int rt_sdhci_start_request_atomic(struct rt_mmc_host *mmc, struct rt_mmcsd_req *mrq); +void rt_sdhci_set_bus_width(struct rt_sdhci_host *host, int width); +void rt_sdhci_reset(struct rt_sdhci_host *host, rt_uint8_t mask); +void rt_sdhci_set_uhs(struct rt_sdhci_host *host, unsigned timing); +int rt_sdhci_execute_tuning(struct rt_mmc_host *mmc, rt_uint32_t opcode); +int __sdhci_execute_tuning(struct rt_sdhci_host *host, rt_uint32_t opcode); +void rt_sdhci_ios_set(struct rt_mmc_host *mmc, struct rt_mmcsd_io_cfg *ios); +int rt_sdhci_start_signal_voltage_switch(struct rt_mmc_host *mmc, struct rt_mmcsd_io_cfg *ios); +void rt_sdhci_enable_io_irq(struct rt_mmc_host *mmc, int enable); +void rt_sdhci_start_tuning(struct rt_sdhci_host *host); +void rt_sdhci_end_tuning(struct rt_sdhci_host *host); +void rt_sdhci_reset_tuning(struct rt_sdhci_host *host); +void rt_sdhci_send_tuning(struct rt_sdhci_host *host, rt_uint32_t opcode); +void rt_sdhci_abort_tuning(struct rt_sdhci_host *host, rt_uint32_t opcode); +void rt_sdhci_enable_v4_mode(struct rt_sdhci_host *host); +void rt_sdhci_data_irq_timeout(struct rt_sdhci_host *host, rt_bool_t enable); +void rt_sdhci_timeout_set(struct rt_sdhci_host *host, struct rt_mmcsd_cmd *cmd); +void rt_sdhci_read_reg_debug(struct rt_sdhci_host* host); + +#endif /* __DEV_SDHCI_H__ */ diff --git a/components/drivers/include/drivers/dev_sdhci_host.h b/components/drivers/include/drivers/dev_sdhci_host.h new file mode 100755 index 0000000000..3ba360d543 --- /dev/null +++ b/components/drivers/include/drivers/dev_sdhci_host.h @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2006-2024 RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2024-08-16 zhujiale first version + */ + +#ifndef __DEV_SDHCI_HOST_H__ +#define __DEV_SDHCI_HOST_H__ + +#include <rtthread.h> + +#include <drivers/dma.h> +#include <drivers/mmcsd_cmd.h> +#include <drivers/mmcsd_host.h> +#include <drivers/dev_mmcsd_core.h> + +#define rt_mmc_dev(x) ((x)->parent) + +#define MMC_SEND_TUNING_BLOCK_HS200 SEND_TUNING_BLOCK_HS200 +#define MMC_SEND_TUNING_BLOCK SEND_TUNING_BLOCK +#define MMC_STOP_TRANSMISSION STOP_TRANSMISSION +#define MMC_BUS_TEST_R 14 /* adtc R1 */ +#define MMC_WRITE_MULTIPLE_BLOCK WRITE_MULTIPLE_BLOCK +#define MMC_READ_MULTIPLE_BLOCK READ_MULTIPLE_BLOCK + +#define MMC_TIMING_UHS_DDR50 MMCSD_TIMING_UHS_DDR50 +#define MMC_TIMING_UHS_SDR50 MMCSD_TIMING_UHS_SDR50 +#define MMC_TIMING_MMC_HS200 MMCSD_TIMING_MMC_HS200 +#define MMC_TIMING_MMC_HS400 MMCSD_TIMING_MMC_HS400 +#define MMC_TIMING_UHS_SDR104 MMCSD_TIMING_UHS_SDR104 +#define MMC_TIMING_UHS_SDR25 MMCSD_TIMING_UHS_SDR25 +#define MMC_TIMING_MMC_DDR52 MMCSD_TIMING_MMC_DDR52 +#define MMC_TIMING_UHS_SDR12 MMCSD_TIMING_UHS_SDR12 +#define MMC_TIMING_SD_HS MMCSD_TIMING_SD_HS +#define MMC_TIMING_MMC_HS MMCSD_TIMING_MMC_HS + +#define MMC_POWER_OFF MMCSD_POWER_OFF +#define MMC_POWER_UP MMCSD_POWER_UP +#define MMC_POWER_ON MMCSD_POWER_ON +#define MMC_POWER_UNDEFINED 3 + +#define MMC_SET_DRIVER_TYPE_B 0 +#define MMC_SET_DRIVER_TYPE_A 1 +#define MMC_SET_DRIVER_TYPE_C 2 +#define MMC_SET_DRIVER_TYPE_D 3 + +#define MMC_SIGNAL_VOLTAGE_330 0 +#define MMC_SIGNAL_VOLTAGE_180 1 +#define MMC_SIGNAL_VOLTAGE_120 2 + +#define MMC_RSP_PRESENT (1 << 16) +#define MMC_RSP_136 (1 << 17) /* 136 bit response */ +#define MMC_RSP_CRC (1 << 18) /* expect valid crc */ +#define MMC_RSP_BUSY (1 << 19) /* card may send busy */ +#define MMC_RSP_OPCODE (1 << 20) /* response contains opcode */ + +#define MMC_RSP_NONE (0) +#define MMC_RSP_R1 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) +#define MMC_RSP_R1B (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | MMC_RSP_BUSY) +#define MMC_RSP_R2 (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC) +#define MMC_RSP_R3 (MMC_RSP_PRESENT) +#define MMC_RSP_R4 (MMC_RSP_PRESENT) +#define MMC_RSP_R5 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) +#define MMC_RSP_R6 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) +#define MMC_RSP_R7 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE) + +#define MMC_CMD_ADTC CMD_ADTC + +#define MMC_BUS_WIDTH_8 MMCSD_BUS_WIDTH_8 +#define MMC_BUS_WIDTH_4 MMCSD_BUS_WIDTH_4 +#define MMC_BUS_WIDTH_1 MMCSD_BUS_WIDTH_1 + +#define MMC_PM_KEEP_POWER (1 << 0) /* preserve card power during suspend */ +#define MMC_PM_WAKE_SDIO_IRQ (1 << 1) /* wake up host system on SDIO IRQ assertion */ + +enum mmc_blk_status +{ + MMC_BLK_SUCCESS = 0, + MMC_BLK_PARTIAL, + MMC_BLK_CMD_ERR, + MMC_BLK_RETRY, + MMC_BLK_ABORT, + MMC_BLK_DATA_ERR, + MMC_BLK_ECC_ERR, + MMC_BLK_NOMEDIUM, + MMC_BLK_NEW_REQUEST, +}; + +#define MMC_NUM_CLK_PHASES (MMC_TIMING_MMC_HS400 + 1) + +struct rt_mmc_host; + +struct rt_mmc_host_ops +{ + void (*request)(struct rt_mmc_host *host, struct rt_mmcsd_req *req); + void (*set_ios)(struct rt_mmc_host *host, struct rt_mmcsd_io_cfg *ios); + int (*get_ro)(struct rt_mmc_host *host); + int (*get_cd)(struct rt_mmc_host *host); + void (*enable_sdio_irq)(struct rt_mmc_host *host, int enable); + void (*ack_sdio_irq)(struct rt_mmc_host *host); + int (*start_signal_voltage_switch)(struct rt_mmc_host *host, struct rt_mmcsd_io_cfg *ios); + int (*card_busy)(struct rt_mmc_host *host); + int (*execute_tuning)(struct rt_mmc_host *host, unsigned opcode); + int (*prepare_hs400_tuning)(struct rt_mmc_host *host, struct rt_mmcsd_io_cfg *ios); + int (*hs400_prepare_ddr)(struct rt_mmc_host *host); + void (*hs400_downgrade)(struct rt_mmc_host *host); + void (*hs400_complete)(struct rt_mmc_host *host); + void (*hs400_enhanced_strobe)(struct rt_mmc_host *host, struct rt_mmcsd_io_cfg *ios); + void (*hw_reset)(struct rt_mmc_host *host); + void (*card_event)(struct rt_mmc_host *host); +}; + +/* VDD voltage 3.3 ~ 3.4 */ +#define MMC_VDD_34_35 0x00400000 /* VDD voltage 3.4 ~ 3.5 */ +#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */ + +#define MMC_CAP2_HS200_1_8V_SDR MMCSD_SUP_HS200_1V8 +#define MMC_CAP2_HS200_1_2V_SDR MMCSD_SUP_HS200_1V2 +#define MMC_CAP_4_BIT_DATA MMCSD_BUSWIDTH_4 +#define MMC_CAP_8_BIT_DATA MMCSD_BUSWIDTH_8 +#define MMC_CAP2_HS200 MMCSD_SUP_HS200 +#define MMC_CAP_MMC_HIGHSPEED MMCSD_SUP_HIGHSPEED +#define MMC_CAP_SD_HIGHSPEED MMCSD_SUP_HIGHSPEED +#define MMC_CAP_1_8V_DDR MMCSD_SUP_DDR_1V8 +#define MMC_CAP_3_3V_DDR MMCSD_SUP_DDR_3V3 +#define MMC_CAP_1_2V_DDR MMCSD_SUP_DDR_1V2 +#define MMC_CAP_NONREMOVABLE MMCSD_SUP_NONREMOVABLE + +#define MMC_CAP_UHS_DDR50 0 +#define MMC_CAP2_HS400 0 +#define MMC_CAP_UHS_SDR50 0 +#define MMC_CAP_UHS_SDR25 0 +#define MMC_CAP_UHS_SDR12 0 +#define MMC_CAP_UHS_SDR104 0 +#define MMC_CAP_UHS 0 +#define MMC_CAP2_HSX00_1_8V 0 +#define MMC_CAP2_HS400_ES 0 +#define MMC_CAP_NEEDS_POLL 0 +#define MMC_CAP2_HSX00_1_2V 0 +#define MMC_CAP2_HS400_1_2V 0 +#define MMC_CAP2_HS400_1_8V 0 +#define MMC_CAP_DRIVER_TYPE_D 0 +#define MMC_CAP_DRIVER_TYPE_C 0 +#define MMC_SET_DRIVER_TYPE_B 0 +#define MMC_CAP_DRIVER_TYPE_A 0 +#define MMC_CAP2_SDIO_IRQ_NOTHREAD 0 +#define MMC_CAP_CMD23 0 +#define MMC_CAP_SDIO_IRQ 0 + +#define MMC_CAP2_NO_SDIO (1 << 19) +#define MMC_CAP2_NO_SD (1 << 21) +#define MMC_CAP2_NO_MMC (1 << 22) +#define MMC_CAP2_CQE (1 << 23) + +#define MMC_VDD_165_195 VDD_165_195 +#define MMC_VDD_20_21 VDD_20_21 +#define MMC_VDD_29_30 VDD_29_30 +#define MMC_VDD_30_31 VDD_30_31 +#define MMC_VDD_32_33 VDD_32_33 +#define MMC_VDD_33_34 VDD_33_34 + +struct rt_mmc_host +{ + struct rt_mmcsd_host rthost; + struct rt_device *parent; + int index; + const struct rt_mmc_host_ops *ops; + unsigned int f_min; + unsigned int f_max; + unsigned int f_init; + rt_uint32_t ocr_avail; + rt_uint32_t ocr_avail_sdio; /* SDIO-specific OCR */ + rt_uint32_t ocr_avail_sd; /* SD-specific OCR */ + rt_uint32_t ocr_avail_mmc; /* MMC-specific OCR */ + struct wakeup_source *ws; /* Enable consume of uevents */ + rt_uint32_t max_current_330; + rt_uint32_t max_current_300; + rt_uint32_t max_current_180; + rt_uint32_t caps; /* Host capabilities */ + rt_uint32_t caps2; /* More host capabilities */ + + + /* host specific block data */ + unsigned int max_seg_size; /* see blk_queue_max_segment_size */ + unsigned short max_segs; /* see blk_queue_max_segments */ + unsigned short unused; + unsigned int max_req_size; /* maximum number of bytes in one req */ + unsigned int max_blk_size; /* maximum size of one mmc block */ + unsigned int max_blk_count; /* maximum number of blocks in one req */ + unsigned int max_busy_timeout; /* max busy timeout in ms */ + struct rt_mmcsd_io_cfg ios; /* current io bus settings */ + unsigned int retune_period; + /* group bitfields together to minimize padding */ + unsigned int use_spi_crc : 1; + unsigned int claimed : 1; /* host exclusively claimed */ + unsigned int doing_init_tune : 1; /* initial tuning in progress */ + unsigned int can_retune : 1; /* re-tuning can be used */ + unsigned int doing_retune : 1; /* re-tuning in progress */ + unsigned int retune_now : 1; /* do re-tuning at next req */ + unsigned int retune_paused : 1; /* re-tuning is temporarily disabled */ + unsigned int retune_crc_disable : 1; /* don't trigger retune upon crc */ + unsigned int can_dma_map_merge : 1; /* merging can be used */ + unsigned int vqmmc_enabled : 1; /* vqmmc regulator is enabled */ + + int need_retune; /* re-tuning is needed */ + int hold_retune; /* hold off re-tuning */ + rt_bool_t trigger_card_event; /* card_event necessary */ + unsigned int sdio_irqs; + rt_bool_t sdio_irq_pending; + + /* Ongoing data transfer that allows commands during transfer */ + struct rt_mmcsd_req *ongoing_mrq; + + rt_uint32_t actual_clock; /* Actual HC clock rate */ + rt_uint32_t pm_caps; + rt_ubase_t private[]; +}; + +rt_inline int mmc_card_is_removable(struct rt_mmc_host *host) +{ + return !(host->caps & MMC_CAP_NONREMOVABLE); +} + +struct rt_mmc_host *rt_mmc_alloc_host(int extra, struct rt_device *); +rt_err_t rt_mmc_add_host(struct rt_mmc_host *); +void rt_mmc_remove_host(struct rt_mmc_host *); +void rt_mmc_free_host(struct rt_mmc_host *); +rt_err_t rt_mmc_of_parse(struct rt_mmc_host *host); + +rt_inline void *rt_mmc_priv(struct rt_mmc_host *host) +{ + return (void *)host->private; +} + +#define mmc_host_is_spi(host) ((host)->caps & MMC_CAP_SPI) + +#define mmc_dev(x) ((x)->parent) +#define mmc_classdev(x) (&(x)->class_dev) +#define mmc_hostname(x) (x->parent->parent.name) + +void rt_mmc_detect_change(struct rt_mmc_host *host, rt_ubase_t delay); +void rt_mmc_request_done(struct rt_mmc_host *host, struct rt_mmcsd_req *req); + +rt_inline rt_bool_t sdio_irq_claimed(struct rt_mmc_host *host) +{ + return host->sdio_irqs > 0; +} + +void mmc_retune_timer_stop(struct rt_mmc_host* host); + +enum dma_data_direction +{ + DMA_BIDIRECTIONAL = 0, + DMA_TO_DEVICE = 1, + DMA_FROM_DEVICE = 2, + DMA_NONE = 3, +}; + +rt_inline void mmc_retune_needed(struct rt_mmc_host *host) +{ + if (host->can_retune) + { + host->need_retune = 1; + } +} + +rt_inline rt_bool_t mmc_can_retune(struct rt_mmc_host *host) +{ + return host->can_retune == 1; +} + +rt_inline rt_bool_t mmc_doing_retune(struct rt_mmc_host *host) +{ + return host->doing_retune == 1; +} + +rt_inline rt_bool_t mmc_doing_tune(struct rt_mmc_host *host) +{ + return host->doing_retune == 1 || host->doing_init_tune == 1; +} + +rt_inline int mmc_get_dma_dir(struct rt_mmcsd_data *data) +{ + return data->flags & DATA_DIR_WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE; +} + +rt_inline rt_bool_t mmc_op_multi(rt_uint32_t opcode) +{ + return opcode == MMC_WRITE_MULTIPLE_BLOCK || + opcode == MMC_READ_MULTIPLE_BLOCK; +} + +rt_inline rt_bool_t mmc_op_tuning(rt_uint32_t opcode) +{ + return opcode == MMC_SEND_TUNING_BLOCK || + opcode == MMC_SEND_TUNING_BLOCK_HS200; +} + +rt_err_t rt_mmc_gpio_get_cd(struct rt_mmc_host *host); +void rt_mmc_detect_change(struct rt_mmc_host *host, rt_ubase_t delay); +rt_bool_t rt_mmc_can_gpio_ro(struct rt_mmc_host *host); +rt_err_t rt_mmc_gpio_get_ro(struct rt_mmc_host *host); + +rt_err_t rt_mmc_send_abort_tuning(struct rt_mmc_host *host, rt_uint32_t opcode); + +#endif /* __DEV_SDHCI_HOST_H__ */ diff --git a/components/drivers/include/drivers/mmcsd_host.h b/components/drivers/include/drivers/mmcsd_host.h index 5632ee1075..68508de612 100644 --- a/components/drivers/include/drivers/mmcsd_host.h +++ b/components/drivers/include/drivers/mmcsd_host.h @@ -76,6 +76,8 @@ struct rt_mmcsd_io_cfg #define MMCSD_SIGNAL_VOLTAGE_330 0 #define MMCSD_SIGNAL_VOLTAGE_180 1 #define MMCSD_SIGNAL_VOLTAGE_120 2 + + rt_bool_t enhanced_strobe; }; struct rt_mmcsd_host; @@ -88,9 +90,23 @@ struct rt_mmcsd_host_ops rt_int32_t (*get_card_status)(struct rt_mmcsd_host *host); void (*enable_sdio_irq)(struct rt_mmcsd_host *host, rt_int32_t en); rt_int32_t (*execute_tuning)(struct rt_mmcsd_host *host, rt_int32_t opcode); - rt_int32_t (*switch_uhs_voltage)(struct rt_mmcsd_host *host); + rt_bool_t (*card_busy)(struct rt_mmcsd_host *host); + rt_err_t (*signal_voltage_switch)(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg); }; +#ifdef RT_USING_REGULATOR +struct rt_regulator; + +struct rt_mmcsd_supply +{ + rt_bool_t vqmmc_enabled; + rt_bool_t regulator_enabled; + + struct rt_regulator *vmmc; /* Card power supply */ + struct rt_regulator *vqmmc; /* Optional Vccq supply */ +}; +#endif /* RT_USING_REGULATOR */ + struct rt_mmcsd_host { char name[RT_NAME_MAX]; @@ -158,6 +174,13 @@ struct rt_mmcsd_host struct rt_semaphore *sdio_irq_sem; struct rt_thread *sdio_irq_thread; +#ifdef RT_USING_REGULATOR + struct rt_mmcsd_supply supply; +#endif +#ifdef RT_USING_OFW + void *ofw_node; +#endif + void *private_data; }; #ifdef __cplusplus diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index ce7d730793..50a97beee5 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -215,6 +215,10 @@ extern "C" { #include "drivers/dev_mmcsd_core.h" #include "drivers/dev_sd.h" #include "drivers/dev_sdio.h" +#if defined(RT_USING_DM) && defined(RT_USING_SDHCI) +#include "drivers/dev_sdhci.h" +#include "drivers/dev_sdhci_host.h" +#endif /* RT_USING_DM && RT_USING_SDHCI */ #endif /* RT_USING_SDIO */ |
