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