Skip to content

Commit

Permalink
[DM/SDIO] Support DM mode
Browse files Browse the repository at this point in the history
1. Support features read by DM.
2. Support regulator API in drivers.
3. Support send tuning option CMD.

Signed-off-by: GuEe-GUI <2991707448@qq.com>
  • Loading branch information
GuEe-GUI committed Dec 2, 2024
1 parent 03a9729 commit 742c491
Show file tree
Hide file tree
Showing 7 changed files with 605 additions and 0 deletions.
2 changes: 2 additions & 0 deletions components/drivers/include/drivers/dev_mmcsd_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ 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_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);
Expand Down
20 changes: 20 additions & 0 deletions components/drivers/include/drivers/mmcsd_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,19 @@ struct rt_mmcsd_host_ops
rt_int32_t (*switch_uhs_voltage)(struct rt_mmcsd_host *host);
};

#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];
Expand Down Expand Up @@ -158,6 +171,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
Expand Down
6 changes: 6 additions & 0 deletions components/drivers/sdio/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ dev_mmc.c
# The set of source files associated with this SConscript file.
path = [cwd + '/../include']

if GetDepend(['RT_USING_DM']):
src += ['dev_sdio_dm.c']

if GetDepend(['RT_USING_REGULATOR']):
src += ['dev_regulator.c']

group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SDIO'], CPPPATH = path)

Return('group')
141 changes: 141 additions & 0 deletions components/drivers/sdio/dev_mmcsd_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,147 @@ rt_uint32_t mmcsd_select_voltage(struct rt_mmcsd_host *host, rt_uint32_t ocr)
return ocr;
}

static const rt_uint8_t tuning_blk_pattern_4bit[] =
{
0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef,
0xff, 0xdf, 0xff, 0xdd, 0xff, 0xfb, 0xff, 0xfb,
0xbf, 0xff, 0x7f, 0xff, 0x77, 0xf7, 0xbd, 0xef,
0xff, 0xf0, 0xff, 0xf0, 0x0f, 0xfc, 0xcc, 0x3c,
0xcc, 0x33, 0xcc, 0xcf, 0xff, 0xef, 0xff, 0xee,
0xff, 0xfd, 0xff, 0xfd, 0xdf, 0xff, 0xbf, 0xff,
0xbb, 0xff, 0xf7, 0xff, 0xf7, 0x7f, 0x7b, 0xde,
};

static const rt_uint8_t tuning_blk_pattern_8bit[] =
{
0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc, 0xcc,
0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff, 0xff,
0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee, 0xff,
0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd, 0xdd,
0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb,
0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff, 0xff,
0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, 0xff,
0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
0x00, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0x33, 0xcc,
0xcc, 0xcc, 0x33, 0x33, 0xcc, 0xcc, 0xcc, 0xff,
0xff, 0xff, 0xee, 0xff, 0xff, 0xff, 0xee, 0xee,
0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0xff, 0xdd,
0xdd, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff, 0xff,
0xbb, 0xbb, 0xff, 0xff, 0xff, 0x77, 0xff, 0xff,
0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
};

rt_err_t mmcsd_send_tuning(struct rt_mmcsd_host *host, rt_uint32_t opcode, rt_err_t *cmd_error)
{
rt_err_t err = RT_EOK;
int size;
rt_uint8_t *data_buf;
const rt_uint8_t *tuning_block_pattern;
struct rt_mmcsd_req req = {};
struct rt_mmcsd_cmd cmd = {};
struct rt_mmcsd_data data = {};
struct rt_mmcsd_io_cfg *io_cfg = &host->io_cfg;

if (io_cfg->bus_width == MMCSD_BUS_WIDTH_8)
{
tuning_block_pattern = tuning_blk_pattern_8bit;
size = sizeof(tuning_blk_pattern_8bit);
}
else if (io_cfg->bus_width == MMCSD_BUS_WIDTH_4)
{
tuning_block_pattern = tuning_blk_pattern_4bit;
size = sizeof(tuning_blk_pattern_4bit);
}
else
{
return -RT_EINVAL;
}

data_buf = rt_malloc(size);
if (!data_buf)
{
return -RT_ENOMEM;
}

rt_memset(data_buf, 0, size);
rt_memset(&req, 0, sizeof(struct rt_mmcsd_req));
rt_memset(&cmd, 0, sizeof(struct rt_mmcsd_cmd));
rt_memset(&data, 0, sizeof(struct rt_mmcsd_data));

req.cmd = &cmd;
req.data = &data;

cmd.cmd_code = opcode;
cmd.flags = RESP_R1 | CMD_ADTC;

data.blksize = size;
data.blks = 1;
data.flags = DATA_DIR_READ;

/*
* According to the tuning specs, Tuning process
* is normally shorter 40 executions of CMD19,
* and timeout value should be shorter than 150 ms
*/
data.timeout_ns = 150 * 1000000;

mmcsd_send_request(host, &req);

if (cmd_error)
{
*cmd_error = cmd.err;
}

if (cmd.err)
{
err = cmd.err;
goto out_free;
}

if (data.err)
{
err = data.err;
goto out_free;
}

if (rt_memcmp(data_buf, tuning_block_pattern, size))
{
err = -RT_EIO;
}

out_free:
rt_free(data_buf);

return err;
}

rt_err_t mmcsd_send_abort_tuning(struct rt_mmcsd_host *host, rt_uint32_t opcode)
{
struct rt_mmcsd_cmd cmd = {};

/*
* eMMC specification specifies that CMD12 can be used to stop a tuning
* command, but SD specification does not, so do nothing unless it is eMMC.
*/
if (opcode != SEND_TUNING_BLOCK_HS200)
{
return 0;
}

cmd.cmd_code = STOP_TRANSMISSION;
cmd.flags = RESP_SPI_R1 | RESP_R1 | CMD_AC;

/*
* For drivers that override R1 to R1b, set an arbitrary timeout based
* on the tuning timeout i.e. 150ms.
*/
cmd.busy_timeout = 150;

return mmcsd_send_cmd(host, &cmd, 0);
}

static void mmcsd_power_up(struct rt_mmcsd_host *host)
{
int bit = __rt_fls(host->valid_ocr) - 1;
Expand Down
Loading

0 comments on commit 742c491

Please sign in to comment.