xref: /rk3399_rockchip-uboot/drivers/mmc/sandbox_mmc.c (revision f376a3cbbf34d3114d92789540ba2d2e9e904758)
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>
11*f376a3cbSSimon 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 
17*f376a3cbSSimon Glass struct sandbox_mmc_plat {
18*f376a3cbSSimon Glass 	struct mmc_config cfg;
19*f376a3cbSSimon Glass 	struct mmc mmc;
20*f376a3cbSSimon Glass };
21*f376a3cbSSimon Glass 
22*f376a3cbSSimon Glass /**
23*f376a3cbSSimon Glass  * sandbox_mmc_send_cmd() - Emulate SD commands
24*f376a3cbSSimon Glass  *
25*f376a3cbSSimon Glass  * This emulate an SD card version 2. Single-block reads result in zero data.
26*f376a3cbSSimon Glass  * Multiple-block reads return a test string.
27*f376a3cbSSimon Glass  */
28*f376a3cbSSimon Glass static int sandbox_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
29*f376a3cbSSimon Glass 				struct mmc_data *data)
30*f376a3cbSSimon Glass {
31*f376a3cbSSimon Glass 	switch (cmd->cmdidx) {
32*f376a3cbSSimon Glass 	case MMC_CMD_ALL_SEND_CID:
33*f376a3cbSSimon Glass 		break;
34*f376a3cbSSimon Glass 	case SD_CMD_SEND_RELATIVE_ADDR:
35*f376a3cbSSimon Glass 		cmd->response[0] = 0 << 16; /* mmc->rca */
36*f376a3cbSSimon Glass 	case MMC_CMD_GO_IDLE_STATE:
37*f376a3cbSSimon Glass 		break;
38*f376a3cbSSimon Glass 	case SD_CMD_SEND_IF_COND:
39*f376a3cbSSimon Glass 		cmd->response[0] = 0xaa;
40*f376a3cbSSimon Glass 		break;
41*f376a3cbSSimon Glass 	case MMC_CMD_SEND_STATUS:
42*f376a3cbSSimon Glass 		cmd->response[0] = MMC_STATUS_RDY_FOR_DATA;
43*f376a3cbSSimon Glass 		break;
44*f376a3cbSSimon Glass 	case MMC_CMD_SELECT_CARD:
45*f376a3cbSSimon Glass 		break;
46*f376a3cbSSimon Glass 	case MMC_CMD_SEND_CSD:
47*f376a3cbSSimon Glass 		cmd->response[0] = 0;
48*f376a3cbSSimon Glass 		cmd->response[1] = 10 << 16;	/* 1 << block_len */
49*f376a3cbSSimon Glass 		break;
50*f376a3cbSSimon Glass 	case SD_CMD_SWITCH_FUNC: {
51*f376a3cbSSimon Glass 		u32 *resp = (u32 *)data->dest;
52*f376a3cbSSimon Glass 
53*f376a3cbSSimon Glass 		resp[7] = cpu_to_be32(SD_HIGHSPEED_BUSY);
54*f376a3cbSSimon Glass 		break;
55*f376a3cbSSimon Glass 	}
56*f376a3cbSSimon Glass 	case MMC_CMD_READ_SINGLE_BLOCK:
57*f376a3cbSSimon Glass 		memset(data->dest, '\0', data->blocksize);
58*f376a3cbSSimon Glass 		break;
59*f376a3cbSSimon Glass 	case MMC_CMD_READ_MULTIPLE_BLOCK:
60*f376a3cbSSimon Glass 		strcpy(data->dest, "this is a test");
61*f376a3cbSSimon Glass 		break;
62*f376a3cbSSimon Glass 	case MMC_CMD_STOP_TRANSMISSION:
63*f376a3cbSSimon Glass 		break;
64*f376a3cbSSimon Glass 	case SD_CMD_APP_SEND_OP_COND:
65*f376a3cbSSimon Glass 		cmd->response[0] = OCR_BUSY | OCR_HCS;
66*f376a3cbSSimon Glass 		cmd->response[1] = 0;
67*f376a3cbSSimon Glass 		cmd->response[2] = 0;
68*f376a3cbSSimon Glass 		break;
69*f376a3cbSSimon Glass 	case MMC_CMD_APP_CMD:
70*f376a3cbSSimon Glass 		break;
71*f376a3cbSSimon Glass 	case MMC_CMD_SET_BLOCKLEN:
72*f376a3cbSSimon Glass 		debug("block len %d\n", cmd->cmdarg);
73*f376a3cbSSimon Glass 		break;
74*f376a3cbSSimon Glass 	case SD_CMD_APP_SEND_SCR: {
75*f376a3cbSSimon Glass 		u32 *scr = (u32 *)data->dest;
76*f376a3cbSSimon Glass 
77*f376a3cbSSimon Glass 		scr[0] = cpu_to_be32(2 << 24 | 1 << 15);  /* SD version 3 */
78*f376a3cbSSimon Glass 		break;
79*f376a3cbSSimon Glass 	}
80*f376a3cbSSimon Glass 	default:
81*f376a3cbSSimon Glass 		debug("%s: Unknown command %d\n", __func__, cmd->cmdidx);
82*f376a3cbSSimon Glass 		break;
83*f376a3cbSSimon Glass 	}
84*f376a3cbSSimon Glass 
85*f376a3cbSSimon Glass 	return 0;
86*f376a3cbSSimon Glass }
87*f376a3cbSSimon Glass 
88*f376a3cbSSimon Glass static void sandbox_mmc_set_ios(struct mmc *mmc)
89*f376a3cbSSimon Glass {
90*f376a3cbSSimon Glass }
91*f376a3cbSSimon Glass 
92*f376a3cbSSimon Glass static int sandbox_mmc_init(struct mmc *mmc)
93*f376a3cbSSimon Glass {
94*f376a3cbSSimon Glass 	return 0;
95*f376a3cbSSimon Glass }
96*f376a3cbSSimon Glass 
97*f376a3cbSSimon Glass static int sandbox_mmc_getcd(struct mmc *mmc)
98*f376a3cbSSimon Glass {
99*f376a3cbSSimon Glass 	return 1;
100*f376a3cbSSimon Glass }
101*f376a3cbSSimon Glass 
102*f376a3cbSSimon Glass static const struct mmc_ops sandbox_mmc_ops = {
103*f376a3cbSSimon Glass 	.send_cmd = sandbox_mmc_send_cmd,
104*f376a3cbSSimon Glass 	.set_ios = sandbox_mmc_set_ios,
105*f376a3cbSSimon Glass 	.init = sandbox_mmc_init,
106*f376a3cbSSimon Glass 	.getcd = sandbox_mmc_getcd,
107*f376a3cbSSimon Glass };
108*f376a3cbSSimon Glass 
109*f376a3cbSSimon Glass int sandbox_mmc_probe(struct udevice *dev)
110*f376a3cbSSimon Glass {
111*f376a3cbSSimon Glass 	struct sandbox_mmc_plat *plat = dev_get_platdata(dev);
112*f376a3cbSSimon Glass 
113*f376a3cbSSimon Glass 	return mmc_init(&plat->mmc);
114*f376a3cbSSimon Glass }
115*f376a3cbSSimon Glass 
116*f376a3cbSSimon Glass int sandbox_mmc_bind(struct udevice *dev)
117*f376a3cbSSimon Glass {
118*f376a3cbSSimon Glass 	struct sandbox_mmc_plat *plat = dev_get_platdata(dev);
119*f376a3cbSSimon Glass 	struct mmc_config *cfg = &plat->cfg;
120*f376a3cbSSimon Glass 	int ret;
121*f376a3cbSSimon Glass 
122*f376a3cbSSimon Glass 	cfg->name = dev->name;
123*f376a3cbSSimon Glass 	cfg->ops = &sandbox_mmc_ops;
124*f376a3cbSSimon Glass 	cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_8BIT;
125*f376a3cbSSimon Glass 	cfg->voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
126*f376a3cbSSimon Glass 	cfg->f_min = 1000000;
127*f376a3cbSSimon Glass 	cfg->f_max = 52000000;
128*f376a3cbSSimon Glass 	cfg->b_max = U32_MAX;
129*f376a3cbSSimon Glass 
130*f376a3cbSSimon Glass 	ret = mmc_bind(dev, &plat->mmc, cfg);
131*f376a3cbSSimon Glass 	if (ret)
132*f376a3cbSSimon Glass 		return ret;
133*f376a3cbSSimon Glass 
134*f376a3cbSSimon Glass 	return 0;
135*f376a3cbSSimon Glass }
136*f376a3cbSSimon Glass 
137*f376a3cbSSimon Glass int sandbox_mmc_unbind(struct udevice *dev)
138*f376a3cbSSimon Glass {
139*f376a3cbSSimon Glass 	mmc_unbind(dev);
140*f376a3cbSSimon Glass 
141*f376a3cbSSimon Glass 	return 0;
142*f376a3cbSSimon Glass }
143*f376a3cbSSimon Glass 
1448e6cc461SSimon Glass static const struct udevice_id sandbox_mmc_ids[] = {
1458e6cc461SSimon Glass 	{ .compatible = "sandbox,mmc" },
1468e6cc461SSimon Glass 	{ }
1478e6cc461SSimon Glass };
1488e6cc461SSimon Glass 
149*f376a3cbSSimon Glass U_BOOT_DRIVER(mmc_sandbox) = {
1508e6cc461SSimon Glass 	.name		= "mmc_sandbox",
1518e6cc461SSimon Glass 	.id		= UCLASS_MMC,
1528e6cc461SSimon Glass 	.of_match	= sandbox_mmc_ids,
153*f376a3cbSSimon Glass 	.bind		= sandbox_mmc_bind,
154*f376a3cbSSimon Glass 	.unbind		= sandbox_mmc_unbind,
155*f376a3cbSSimon Glass 	.probe		= sandbox_mmc_probe,
156*f376a3cbSSimon Glass 	.platdata_auto_alloc_size = sizeof(struct sandbox_mmc_plat),
1578e6cc461SSimon Glass };
158