895fbffecfcdb3ad108031f62b04fc02e1e8cf7c
[platform/kernel/u-boot.git] / drivers / mmc / sandbox_mmc.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2015 Google, Inc
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <fdtdec.h>
11 #include <log.h>
12 #include <mmc.h>
13 #include <asm/test.h>
14
15 struct sandbox_mmc_plat {
16         struct mmc_config cfg;
17         struct mmc mmc;
18 };
19
20 #define MMC_CSIZE 0
21 #define MMC_CMULT 8 /* 8 because the card is high-capacity */
22 #define MMC_BL_LEN_SHIFT 10
23 #define MMC_BL_LEN BIT(MMC_BL_LEN_SHIFT)
24 #define MMC_CAPACITY (((MMC_CSIZE + 1) << (MMC_CMULT + 2)) \
25                       * MMC_BL_LEN) /* 1 MiB */
26
27 struct sandbox_mmc_priv {
28         u8 buf[MMC_CAPACITY];
29 };
30
31 /**
32  * sandbox_mmc_send_cmd() - Emulate SD commands
33  *
34  * This emulate an SD card version 2. Single-block reads result in zero data.
35  * Multiple-block reads return a test string.
36  */
37 static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
38                                 struct mmc_data *data)
39 {
40         struct sandbox_mmc_priv *priv = dev_get_priv(dev);
41         struct mmc *mmc = mmc_get_mmc_dev(dev);
42         static ulong erase_start, erase_end;
43
44         switch (cmd->cmdidx) {
45         case MMC_CMD_ALL_SEND_CID:
46                 memset(cmd->response, '\0', sizeof(cmd->response));
47                 break;
48         case SD_CMD_SEND_RELATIVE_ADDR:
49                 cmd->response[0] = 0 << 16; /* mmc->rca */
50         case MMC_CMD_GO_IDLE_STATE:
51                 break;
52         case SD_CMD_SEND_IF_COND:
53                 cmd->response[0] = 0xaa;
54                 break;
55         case MMC_CMD_SEND_STATUS:
56                 cmd->response[0] = MMC_STATUS_RDY_FOR_DATA;
57                 break;
58         case MMC_CMD_SELECT_CARD:
59                 break;
60         case MMC_CMD_SEND_CSD:
61                 cmd->response[0] = 0;
62                 cmd->response[1] = (MMC_BL_LEN_SHIFT << 16) |
63                                    ((MMC_CSIZE >> 16) & 0x3f);
64                 cmd->response[2] = (MMC_CSIZE & 0xffff) << 16;
65                 cmd->response[3] = 0;
66                 break;
67         case SD_CMD_SWITCH_FUNC: {
68                 if (!data)
69                         break;
70                 u32 *resp = (u32 *)data->dest;
71                 resp[3] = 0;
72                 resp[7] = cpu_to_be32(SD_HIGHSPEED_BUSY);
73                 if ((cmd->cmdarg & 0xF) == UHS_SDR12_BUS_SPEED)
74                         resp[4] = (cmd->cmdarg & 0xF) << 24;
75                 break;
76         }
77         case MMC_CMD_READ_SINGLE_BLOCK:
78         case MMC_CMD_READ_MULTIPLE_BLOCK:
79                 memcpy(data->dest, &priv->buf[cmd->cmdarg * data->blocksize],
80                        data->blocks * data->blocksize);
81                 break;
82         case MMC_CMD_WRITE_SINGLE_BLOCK:
83         case MMC_CMD_WRITE_MULTIPLE_BLOCK:
84                 memcpy(&priv->buf[cmd->cmdarg * data->blocksize], data->src,
85                        data->blocks * data->blocksize);
86                 break;
87         case MMC_CMD_STOP_TRANSMISSION:
88                 break;
89         case SD_CMD_ERASE_WR_BLK_START:
90                 erase_start = cmd->cmdarg;
91                 break;
92         case SD_CMD_ERASE_WR_BLK_END:
93                 erase_end = cmd->cmdarg;
94                 break;
95         case MMC_CMD_ERASE:
96                 memset(&priv->buf[erase_start * mmc->write_bl_len], '\0',
97                        (erase_end - erase_start + 1) * mmc->write_bl_len);
98                 break;
99         case SD_CMD_APP_SEND_OP_COND:
100                 cmd->response[0] = OCR_BUSY | OCR_HCS;
101                 cmd->response[1] = 0;
102                 cmd->response[2] = 0;
103                 break;
104         case MMC_CMD_APP_CMD:
105                 break;
106         case MMC_CMD_SET_BLOCKLEN:
107                 debug("block len %d\n", cmd->cmdarg);
108                 break;
109         case SD_CMD_APP_SEND_SCR: {
110                 u32 *scr = (u32 *)data->dest;
111
112                 scr[0] = cpu_to_be32(2 << 24 | 1 << 15);  /* SD version 3 */
113                 break;
114         }
115         default:
116                 debug("%s: Unknown command %d\n", __func__, cmd->cmdidx);
117                 break;
118         }
119
120         return 0;
121 }
122
123 static int sandbox_mmc_set_ios(struct udevice *dev)
124 {
125         return 0;
126 }
127
128 static int sandbox_mmc_get_cd(struct udevice *dev)
129 {
130         return 1;
131 }
132
133 static const struct dm_mmc_ops sandbox_mmc_ops = {
134         .send_cmd = sandbox_mmc_send_cmd,
135         .set_ios = sandbox_mmc_set_ios,
136         .get_cd = sandbox_mmc_get_cd,
137 };
138
139 static int sandbox_mmc_of_to_plat(struct udevice *dev)
140 {
141         struct sandbox_mmc_plat *plat = dev_get_plat(dev);
142         struct mmc_config *cfg = &plat->cfg;
143         struct blk_desc *blk;
144         int ret;
145
146         ret = mmc_of_parse(dev, cfg);
147         if (ret)
148                 return ret;
149         blk = mmc_get_blk_desc(&plat->mmc);
150         if (blk)
151                 blk->removable = !(cfg->host_caps & MMC_CAP_NONREMOVABLE);
152
153         return 0;
154 }
155
156 static int sandbox_mmc_probe(struct udevice *dev)
157 {
158         struct sandbox_mmc_plat *plat = dev_get_plat(dev);
159
160         return mmc_init(&plat->mmc);
161 }
162
163 static int sandbox_mmc_bind(struct udevice *dev)
164 {
165         struct sandbox_mmc_plat *plat = dev_get_plat(dev);
166         struct mmc_config *cfg = &plat->cfg;
167
168         cfg->name = dev->name;
169         cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_8BIT;
170         cfg->voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
171         cfg->f_min = 1000000;
172         cfg->f_max = 52000000;
173         cfg->b_max = U32_MAX;
174
175         return mmc_bind(dev, &plat->mmc, cfg);
176 }
177
178 static int sandbox_mmc_unbind(struct udevice *dev)
179 {
180         mmc_unbind(dev);
181
182         return 0;
183 }
184
185 static const struct udevice_id sandbox_mmc_ids[] = {
186         { .compatible = "sandbox,mmc" },
187         { }
188 };
189
190 U_BOOT_DRIVER(mmc_sandbox) = {
191         .name           = "mmc_sandbox",
192         .id             = UCLASS_MMC,
193         .of_match       = sandbox_mmc_ids,
194         .ops            = &sandbox_mmc_ops,
195         .bind           = sandbox_mmc_bind,
196         .unbind         = sandbox_mmc_unbind,
197         .of_to_plat     = sandbox_mmc_of_to_plat,
198         .probe          = sandbox_mmc_probe,
199         .priv_auto = sizeof(struct sandbox_mmc_priv),
200         .plat_auto = sizeof(struct sandbox_mmc_plat),
201 };