xref: /openbmc/u-boot/drivers/mmc/sandbox_mmc.c (revision e8f80a5a)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
28e6cc461SSimon Glass /*
38e6cc461SSimon Glass  * Copyright (c) 2015 Google, Inc
48e6cc461SSimon Glass  * Written by Simon Glass <sjg@chromium.org>
58e6cc461SSimon Glass  */
68e6cc461SSimon Glass 
78e6cc461SSimon Glass #include <common.h>
88e6cc461SSimon Glass #include <dm.h>
98e6cc461SSimon Glass #include <errno.h>
10f376a3cbSSimon Glass #include <fdtdec.h>
118e6cc461SSimon Glass #include <mmc.h>
128e6cc461SSimon Glass #include <asm/test.h>
138e6cc461SSimon Glass 
14f376a3cbSSimon Glass struct sandbox_mmc_plat {
15f376a3cbSSimon Glass 	struct mmc_config cfg;
16f376a3cbSSimon Glass 	struct mmc mmc;
17f376a3cbSSimon Glass };
18f376a3cbSSimon Glass 
19f376a3cbSSimon Glass /**
20f376a3cbSSimon Glass  * sandbox_mmc_send_cmd() - Emulate SD commands
21f376a3cbSSimon Glass  *
22f376a3cbSSimon Glass  * This emulate an SD card version 2. Single-block reads result in zero data.
23f376a3cbSSimon Glass  * Multiple-block reads return a test string.
24f376a3cbSSimon Glass  */
sandbox_mmc_send_cmd(struct udevice * dev,struct mmc_cmd * cmd,struct mmc_data * data)259a46bd3fSSimon Glass static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
26f376a3cbSSimon Glass 				struct mmc_data *data)
27f376a3cbSSimon Glass {
28f376a3cbSSimon Glass 	switch (cmd->cmdidx) {
29f376a3cbSSimon Glass 	case MMC_CMD_ALL_SEND_CID:
30f376a3cbSSimon Glass 		break;
31f376a3cbSSimon Glass 	case SD_CMD_SEND_RELATIVE_ADDR:
32f376a3cbSSimon Glass 		cmd->response[0] = 0 << 16; /* mmc->rca */
33f376a3cbSSimon Glass 	case MMC_CMD_GO_IDLE_STATE:
34f376a3cbSSimon Glass 		break;
35f376a3cbSSimon Glass 	case SD_CMD_SEND_IF_COND:
36f376a3cbSSimon Glass 		cmd->response[0] = 0xaa;
37f376a3cbSSimon Glass 		break;
38f376a3cbSSimon Glass 	case MMC_CMD_SEND_STATUS:
39f376a3cbSSimon Glass 		cmd->response[0] = MMC_STATUS_RDY_FOR_DATA;
40f376a3cbSSimon Glass 		break;
41f376a3cbSSimon Glass 	case MMC_CMD_SELECT_CARD:
42f376a3cbSSimon Glass 		break;
43f376a3cbSSimon Glass 	case MMC_CMD_SEND_CSD:
44f376a3cbSSimon Glass 		cmd->response[0] = 0;
45f376a3cbSSimon Glass 		cmd->response[1] = 10 << 16;	/* 1 << block_len */
46f376a3cbSSimon Glass 		break;
47f376a3cbSSimon Glass 	case SD_CMD_SWITCH_FUNC: {
4849f89252SJean-Jacques Hiblot 		if (!data)
4949f89252SJean-Jacques Hiblot 			break;
50f376a3cbSSimon Glass 		u32 *resp = (u32 *)data->dest;
51f376a3cbSSimon Glass 		resp[7] = cpu_to_be32(SD_HIGHSPEED_BUSY);
5249f89252SJean-Jacques Hiblot 		if ((cmd->cmdarg & 0xF) == UHS_SDR12_BUS_SPEED)
5349f89252SJean-Jacques Hiblot 			resp[4] = (cmd->cmdarg & 0xF) << 24;
54f376a3cbSSimon Glass 		break;
55f376a3cbSSimon Glass 	}
56f376a3cbSSimon Glass 	case MMC_CMD_READ_SINGLE_BLOCK:
57f376a3cbSSimon Glass 		memset(data->dest, '\0', data->blocksize);
58f376a3cbSSimon Glass 		break;
59f376a3cbSSimon Glass 	case MMC_CMD_READ_MULTIPLE_BLOCK:
60f376a3cbSSimon Glass 		strcpy(data->dest, "this is a test");
61f376a3cbSSimon Glass 		break;
62f376a3cbSSimon Glass 	case MMC_CMD_STOP_TRANSMISSION:
63f376a3cbSSimon Glass 		break;
64f376a3cbSSimon Glass 	case SD_CMD_APP_SEND_OP_COND:
65f376a3cbSSimon Glass 		cmd->response[0] = OCR_BUSY | OCR_HCS;
66f376a3cbSSimon Glass 		cmd->response[1] = 0;
67f376a3cbSSimon Glass 		cmd->response[2] = 0;
68f376a3cbSSimon Glass 		break;
69f376a3cbSSimon Glass 	case MMC_CMD_APP_CMD:
70f376a3cbSSimon Glass 		break;
71f376a3cbSSimon Glass 	case MMC_CMD_SET_BLOCKLEN:
72f376a3cbSSimon Glass 		debug("block len %d\n", cmd->cmdarg);
73f376a3cbSSimon Glass 		break;
74f376a3cbSSimon Glass 	case SD_CMD_APP_SEND_SCR: {
75f376a3cbSSimon Glass 		u32 *scr = (u32 *)data->dest;
76f376a3cbSSimon Glass 
77f376a3cbSSimon Glass 		scr[0] = cpu_to_be32(2 << 24 | 1 << 15);  /* SD version 3 */
78f376a3cbSSimon Glass 		break;
79f376a3cbSSimon Glass 	}
80f376a3cbSSimon Glass 	default:
81f376a3cbSSimon Glass 		debug("%s: Unknown command %d\n", __func__, cmd->cmdidx);
82f376a3cbSSimon Glass 		break;
83f376a3cbSSimon Glass 	}
84f376a3cbSSimon Glass 
85f376a3cbSSimon Glass 	return 0;
86f376a3cbSSimon Glass }
87f376a3cbSSimon Glass 
sandbox_mmc_set_ios(struct udevice * dev)889a46bd3fSSimon Glass static int sandbox_mmc_set_ios(struct udevice *dev)
89f376a3cbSSimon Glass {
90f376a3cbSSimon Glass 	return 0;
91f376a3cbSSimon Glass }
92f376a3cbSSimon Glass 
sandbox_mmc_get_cd(struct udevice * dev)939a46bd3fSSimon Glass static int sandbox_mmc_get_cd(struct udevice *dev)
94f376a3cbSSimon Glass {
95f376a3cbSSimon Glass 	return 1;
96f376a3cbSSimon Glass }
97f376a3cbSSimon Glass 
989a46bd3fSSimon Glass static const struct dm_mmc_ops sandbox_mmc_ops = {
99f376a3cbSSimon Glass 	.send_cmd = sandbox_mmc_send_cmd,
100f376a3cbSSimon Glass 	.set_ios = sandbox_mmc_set_ios,
1019a46bd3fSSimon Glass 	.get_cd = sandbox_mmc_get_cd,
102f376a3cbSSimon Glass };
103f376a3cbSSimon Glass 
sandbox_mmc_probe(struct udevice * dev)104f376a3cbSSimon Glass int sandbox_mmc_probe(struct udevice *dev)
105f376a3cbSSimon Glass {
106f376a3cbSSimon Glass 	struct sandbox_mmc_plat *plat = dev_get_platdata(dev);
107f376a3cbSSimon Glass 
108f376a3cbSSimon Glass 	return mmc_init(&plat->mmc);
109f376a3cbSSimon Glass }
110f376a3cbSSimon Glass 
sandbox_mmc_bind(struct udevice * dev)111f376a3cbSSimon Glass int sandbox_mmc_bind(struct udevice *dev)
112f376a3cbSSimon Glass {
113f376a3cbSSimon Glass 	struct sandbox_mmc_plat *plat = dev_get_platdata(dev);
114f376a3cbSSimon Glass 	struct mmc_config *cfg = &plat->cfg;
115f376a3cbSSimon Glass 
116f376a3cbSSimon Glass 	cfg->name = dev->name;
117f376a3cbSSimon Glass 	cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_8BIT;
118f376a3cbSSimon Glass 	cfg->voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
119f376a3cbSSimon Glass 	cfg->f_min = 1000000;
120f376a3cbSSimon Glass 	cfg->f_max = 52000000;
121f376a3cbSSimon Glass 	cfg->b_max = U32_MAX;
122f376a3cbSSimon Glass 
12324f5aec3SMasahiro Yamada 	return mmc_bind(dev, &plat->mmc, cfg);
124f376a3cbSSimon Glass }
125f376a3cbSSimon Glass 
sandbox_mmc_unbind(struct udevice * dev)126f376a3cbSSimon Glass int sandbox_mmc_unbind(struct udevice *dev)
127f376a3cbSSimon Glass {
128f376a3cbSSimon Glass 	mmc_unbind(dev);
129f376a3cbSSimon Glass 
130f376a3cbSSimon Glass 	return 0;
131f376a3cbSSimon Glass }
132f376a3cbSSimon Glass 
1338e6cc461SSimon Glass static const struct udevice_id sandbox_mmc_ids[] = {
1348e6cc461SSimon Glass 	{ .compatible = "sandbox,mmc" },
1358e6cc461SSimon Glass 	{ }
1368e6cc461SSimon Glass };
1378e6cc461SSimon Glass 
138f376a3cbSSimon Glass U_BOOT_DRIVER(mmc_sandbox) = {
1398e6cc461SSimon Glass 	.name		= "mmc_sandbox",
1408e6cc461SSimon Glass 	.id		= UCLASS_MMC,
1418e6cc461SSimon Glass 	.of_match	= sandbox_mmc_ids,
1429a46bd3fSSimon Glass 	.ops		= &sandbox_mmc_ops,
143f376a3cbSSimon Glass 	.bind		= sandbox_mmc_bind,
144f376a3cbSSimon Glass 	.unbind		= sandbox_mmc_unbind,
145f376a3cbSSimon Glass 	.probe		= sandbox_mmc_probe,
146f376a3cbSSimon Glass 	.platdata_auto_alloc_size = sizeof(struct sandbox_mmc_plat),
1478e6cc461SSimon Glass };
148