source: umon/ports/beagleboneblack/am335x_mmc.c @ d8325a1

Last change on this file since d8325a1 was d8325a1, checked in by Jarielle Catbagan <jcatbagan93@…>, on 08/04/15 at 18:03:25

BBB: Add am335x_mmc.c and am335x_mmc.h that implement "mmc" command with initialization functionality

  • Property mode set to 100644
File size: 10.4 KB
Line 
1/*
2 * Copyright (c) 2015 Jarielle Catbagan <jcatbagan93@gmail.com>
3 *
4 * The license and distribution terms for this file may be
5 * found in the file LICENSE in this distribution or at
6 * http://www.apache.org/licenses/LICENSE-2.0
7 */
8
9#include "genlib.h"
10#include "cli.h"
11#include "stddefs.h"
12#include "am335x.h"
13#include "am335x_mmc.h"
14
15uint16_t mmcrca;
16int mmcInum;
17
18char *mmcHelp[] = {
19        "MultiMediaCard Interface",
20        "[options] {operation} [args]...",
21#if INCLUDE_VERBOSEHELP
22        "",
23        "Options:",
24        " -i ## interface # (default is 0)",
25        " -v    additive verbosity",
26        "",
27        "Operations:",
28        " init",
29        " read {dest} {blk} {blktot}",
30        " write {source} {blk} {blktot}",
31#endif /* INCLUDE_VERBOSEHELP */
32        0
33};
34
35int
36mmccmd(uint32_t cmd, uint32_t arg, uint32_t resp[4])
37{
38        /* Clear the SD_STAT register for proper update of status bits after CMD invocation */
39        MMC1_REG(SD_STAT) = 0xFFFFFFFF;
40
41        MMC1_REG(SD_ARG) = arg;
42        MMC1_REG(SD_CMD) = cmd;
43
44        /* CMDx complete? */
45        while (!(MMC1_REG(SD_STAT) & (SD_STAT_CC | SD_STAT_ERRI)));
46
47        resp[0] = MMC1_REG(SD_RSP10);
48        resp[1] = MMC1_REG(SD_RSP32);
49        resp[2] = MMC1_REG(SD_RSP54);
50        resp[3] = MMC1_REG(SD_RSP76);
51
52        /* CMDx error? */
53        if (MMC1_REG(SD_STAT) & SD_STAT_ERRI)
54                return(-1);
55        else
56                return(0);
57}
58
59int
60mmc(int argc, char *argv[])
61{
62        char *cmd, *buf;
63        int opt, verbose, mmcret, blknum, blkcnt;
64
65        verbose = 0;
66
67        while ((opt = getopt(argc, argv, "i:v")) != -1) {
68                switch (opt) {
69                        case 'i':
70                                mmcInum = atoi(optarg);
71                                break;
72                        case 'v':
73                                verbose++;
74                                break;
75                        default:
76                                return(CMD_PARAM_ERROR);
77                }
78        }
79
80        if (argc < optind + 1)
81                return(CMD_PARAM_ERROR);
82
83        cmd = argv[optind];
84
85        if (mmcInstalled(mmcInum) == 0) {
86                printf("MMC not installed\n");
87                return(CMD_FAILURE);
88        }
89
90        if (strcmp(cmd, "init") == 0) {
91                mmcret = mmcInit(mmcInum, verbose);
92                if(mmcret < 0) {
93                        printf("mmcInit returned %d\n", mmcret);
94                        return(CMD_FAILURE);
95                }
96        }
97        else if (strcmp(cmd, "read") == 0) {
98                if (argc != (optind + 4))
99                        return(CMD_PARAM_ERROR);
100
101                buf = (char *)strtoul(argv[optind + 1], 0, 0);
102                blknum = strtoul(argv[optind + 2], 0, 0);
103                blkcnt = strtoul(argv[optind + 3], 0, 0);
104
105                mmcret = mmcRead(mmcInum, buf, blknum, blkcnt);
106                if (mmcret < 0) {
107                        printf("mmcRead returned %d\n", mmcret);
108                        return(CMD_FAILURE);
109                }
110        }
111        else if (strcmp(cmd, "write") == 0) {
112                if (argc != (optind + 4))
113                        return(CMD_PARAM_ERROR);
114
115                buf = (char *)strtoul(argv[optind + 1], 0, 0);
116                blknum = strtoul(argv[optind + 2], 0, 0);
117                blkcnt = strtoul(argv[optind + 3], 0, 0);
118
119                mmcret = mmcWrite(mmcInum, buf, blknum, blkcnt);
120                if (mmcret < 0) {
121                        printf("mmcWrite returned %d\n", mmcret);
122                        return(CMD_FAILURE);
123                }
124        }
125        else {
126                printf("mmc op <%s> not found\n", cmd);
127                return(CMD_FAILURE);
128        }
129
130        return(CMD_SUCCESS);
131}
132
133int
134mmcInit(int interface, int verbose)
135{
136        uint32_t cmd, arg, resp[4];
137
138        /* Enable MMC1 clocks */
139        CM_PER_REG(CM_PER_MMC1_CLKCTRL) |= CM_PER_MMC1_CLKCTRL_MODULEMODE_ENABLE;
140        while (CM_PER_REG(CM_PER_MMC1_CLKCTRL) & CM_PER_MMC0_CLKCTRL_IDLEST);
141
142        /* Reset the MMC1 Controller */
143        MMC1_REG(SD_SYSCONFIG) = SD_SYSCONFIG_SOFTRESET;
144        while (!(MMC1_REG(SD_SYSSTATUS) & SD_SYSSTATUS_RESETDONE));
145
146        /* Reset the command and data lines */
147        MMC1_REG(SD_SYSCTL) |= SD_SYSCTL_SRA;
148        while (MMC1_REG(SD_SYSCTL) & SD_SYSCTL_SRA);
149
150        /* Configure the MMC1 controller capabilities to enable 3.0 V operating voltage */
151        MMC1_REG(SD_CAPA) |= SD_CAPA_VS30;
152
153        /* Configure SD_IE register to update certain status bits in SD_STAT */
154        MMC1_REG(SD_IE) = SD_IE_BADA_ENABLE | SD_IE_CERR_ENABLE | SD_IE_ACE_ENABLE |
155                SD_IE_DEB_ENABLE | SD_IE_DCRC_ENABLE | SD_IE_DTO_ENABLE | SD_IE_CIE_ENABLE |
156                SD_IE_CEB_ENABLE | SD_IE_CCRC_ENABLE | SD_IE_CIRQ_ENABLE | SD_IE_CREM_ENABLE |
157                SD_IE_CINS_ENABLE | SD_IE_BRR_ENABLE | SD_IE_BWR_ENABLE |
158                SD_IE_TC_ENABLE | SD_IE_CC_ENABLE;
159
160        /* Configure the operating voltage to 3.0 V */
161        MMC1_REG(SD_HCTL) &= ~(SD_HCTL_SDVS);
162        MMC1_REG(SD_HCTL) |= SD_HCTL_SDVS_VS30;
163
164        /* Turn on the bus */
165        MMC1_REG(SD_HCTL) |= SD_HCTL_SDBP;
166        while (!(MMC1_REG(SD_HCTL) & SD_HCTL_SDBP));
167
168        /* Enable the internal clock */
169        MMC1_REG(SD_SYSCTL) |= SD_SYSCTL_ICE;
170
171        /* Configure Clock Frequency Select to 100 KHz */
172        MMC1_REG(SD_SYSCTL) = (MMC1_REG(SD_SYSCTL) & ~SD_SYSCTL_CLKD) | (960 << 6);
173
174        /* Wait for clock to stabilize */
175        while (!(MMC1_REG(SD_SYSCTL) & SD_SYSCTL_ICS));
176
177        /* Configure SD_SYSCONFIG */
178        MMC1_REG(SD_SYSCONFIG) &= ~(SD_SYSCONFIG_CLOCKACTIVITY | SD_SYSCONFIG_SIDLEMODE);
179        MMC1_REG(SD_SYSCONFIG) |= SD_SYSCONFIG_SIDLEMODE_WKUP | SD_SYSCONFIG_ENAWAKEUP_ENABLE |
180                SD_SYSCONFIG_AUTOIDLE_AUTOGATE;
181
182        /* Enable the clock to the eMMC */
183        MMC1_REG(SD_SYSCTL) |= SD_SYSCTL_CEN;
184
185        /* Perform the Initialization Stream as specified in the AM335x TRM, Section 18.3.3.2
186           "Card Detection, Identification, and Selection" */
187        MMC1_REG(SD_CON) |= SD_CON_INIT;
188        /* Clear the SD_STAT register */
189        MMC1_REG(SD_STAT) = 0xFFFFFFFF;
190        MMC1_REG(SD_ARG) = 0x00000000;
191        MMC1_REG(SD_CMD) = 0x00000000;
192        while (!(MMC1_REG(SD_STAT) & SD_STAT_CC));
193        /* Clear CC flag in SD_STAT */
194        MMC1_REG(SD_STAT) |= SD_STAT_CC;
195        MMC1_REG(SD_CON) &= ~SD_CON_INIT;
196
197        /* Clear the SD_STAT register */
198        MMC1_REG(SD_STAT) = 0xFFFFFFFF;
199
200        /* Enable open-drain mode until we enter Stand-by State as illustrated in the
201           JEDEC JESD84-A43 Embedded MultiMediaCard Product Standard specification, Table 5 */
202        MMC1_REG(SD_CON) |= SD_CON_OD;
203
204        /* Send CMD0/GO_IDLE_STATE to reset the eMMC on MMC1 interface */
205        arg = 0x00000000;
206        cmd = SD_CMD_CMD0_GO_IDLE_STATE | SD_CMD_CMD_TYPE_NORMAL | SD_CMD_DP_NO_DATA_PRESENT |
207                SD_CMD_CICE_DISABLE | SD_CMD_CCCE_DISABLE | SD_CMD_RSP_TYPE_NO_RESPONSE;
208        if (mmccmd(cmd, arg, resp) == -1)
209                return(-1);
210
211        /* Send CMD1 and poll busy bit in response */
212        do {
213                arg = 0x40FF8000;
214                cmd = SD_CMD_CMD1_SEND_OP_COND | SD_CMD_CMD_TYPE_NORMAL | SD_CMD_DP_NO_DATA_PRESENT |
215                        SD_CMD_CICE_DISABLE | SD_CMD_CCCE_DISABLE | SD_CMD_RSP_TYPE_R3;
216                if (mmccmd(cmd, arg, resp) == -1)
217                        return(-1);
218        } while (!(MMC1_REG(SD_RSP10) & 0x80000000));
219
220        /* Send CMD2, i.e. ALL_SEND_CID */
221        arg = 0x00000000;
222        cmd = SD_CMD_CMD2_ALL_SEND_CID | SD_CMD_CMD_TYPE_NORMAL | SD_CMD_DP_NO_DATA_PRESENT |
223                SD_CMD_CICE_DISABLE | SD_CMD_CCCE_ENABLE | SD_CMD_RSP_TYPE_R2;
224        if (mmccmd(cmd, arg, resp) == -1)
225                return(-1);
226
227        /* Set RCA of eMMC */
228        mmcrca = 0x3A3A;
229
230        /* Send CMD3 to set the relative card address (RCA) of the eMMC */
231        arg = (mmcrca << 16) & 0xFFFF0000;
232        cmd = SD_CMD_CMD3_SET_RELATIVE_ADDR | SD_CMD_CMD_TYPE_NORMAL | SD_CMD_DP_NO_DATA_PRESENT |
233                SD_CMD_CICE_ENABLE | SD_CMD_CCCE_ENABLE | SD_CMD_RSP_TYPE_R1;
234        if (mmccmd(cmd, arg, resp) == -1)
235                return(-1);
236
237        /* Wait for the eMMC to enter Stand-by State */
238        do {
239                /* Send CMD13 to get the status of the MMC */
240                arg = (mmcrca << 16) & 0xFFFF0000;
241                cmd = SD_CMD_CMD13_SEND_STATUS | SD_CMD_CMD_TYPE_NORMAL | SD_CMD_DP_NO_DATA_PRESENT |
242                        SD_CMD_CICE_ENABLE | SD_CMD_CCCE_ENABLE | SD_CMD_RSP_TYPE_R1;
243                if (mmccmd(cmd, arg, resp) == -1)
244                        return(-1);
245        } while ((resp[0] & SD_RSP10_R1_CURRENT_STATE) != SD_RSP10_R1_CURRENT_STATE_STANDBY);
246
247        /* Disable open-drain mode */
248        MMC1_REG(SD_CON) &= ~SD_CON_OD;
249
250        /* Send CMD7 to put the eMMC into Transfer State */
251        arg = (mmcrca << 16) & 0xFFFF0000;
252        cmd = SD_CMD_CMD7_SELECT_DESELECT_CARD | SD_CMD_CMD_TYPE_NORMAL | SD_CMD_DP_NO_DATA_PRESENT |
253                SD_CMD_CICE_ENABLE | SD_CMD_CCCE_ENABLE | SD_CMD_RSP_TYPE_R1;
254        if (mmccmd(cmd, arg, resp) == -1)
255                return(-1);
256
257        /* Wait for eMMC to enter Transfer State */
258        do {
259                /* Send CMD13 to get the status of the eMMC */
260                arg = (mmcrca << 16) & 0xFFFF0000;
261                cmd = SD_CMD_CMD13_SEND_STATUS | SD_CMD_CMD_TYPE_NORMAL | SD_CMD_DP_NO_DATA_PRESENT |
262                        SD_CMD_CICE_ENABLE | SD_CMD_CCCE_ENABLE | SD_CMD_RSP_TYPE_R1;
263                if (mmccmd(cmd, arg, resp) == -1)
264                        return(-1);
265        } while ((resp[0] & SD_RSP10_R1_CURRENT_STATE) != SD_RSP10_R1_CURRENT_STATE_TRANSFER);
266
267        /* Send CMD6 to change bus-width to 8-bits */
268        arg = (3 << 24) | (183 << 16) | (2 << 8);
269        cmd = SD_CMD_CMD6_SWITCH | SD_CMD_CMD_TYPE_NORMAL | SD_CMD_DP_NO_DATA_PRESENT |
270                SD_CMD_CICE_ENABLE | SD_CMD_CCCE_ENABLE | SD_CMD_RSP_TYPE_R1B;
271        if (mmccmd(cmd, arg, resp) == -1)
272                return(-1);
273        while (!(MMC1_REG(SD_STAT) & SD_STAT_TC));
274
275        /* Wait while CMD6 is still in effect, i.e. while eMMC is not in Transfer State */
276        do {
277                arg = (mmcrca << 16) & 0xFFFF0000;
278                cmd = SD_CMD_CMD13_SEND_STATUS | SD_CMD_CMD_TYPE_NORMAL | SD_CMD_DP_NO_DATA_PRESENT |
279                        SD_CMD_CICE_ENABLE | SD_CMD_CCCE_ENABLE | SD_CMD_RSP_TYPE_R1;
280                if (mmccmd(cmd, arg, resp) == -1)
281                        return(-1);
282        } while ((resp[0] & SD_RSP10_R1_CURRENT_STATE) != SD_RSP10_R1_CURRENT_STATE_TRANSFER);
283
284        /* Configure the MMC1 controller to use an 8-bit data width */
285        MMC1_REG(SD_CON) |= SD_CON_DW8_8BIT;
286
287        /* Send CMD6 to change to high-speed mode */
288        arg = 0x03B90100;
289        cmd = SD_CMD_CMD6_SWITCH | SD_CMD_CMD_TYPE_NORMAL | SD_CMD_DP_NO_DATA_PRESENT |
290                SD_CMD_CICE_ENABLE | SD_CMD_CCCE_ENABLE | SD_CMD_RSP_TYPE_R1B;
291        if (mmccmd(cmd, arg, resp) == -1)
292                return(-1);
293        while (!(MMC1_REG(SD_STAT) & SD_STAT_TC));
294
295        /* Wait while CMD6 is still in effect, i.e. while eMMC is not in Transfer State */
296        do {
297                arg = (mmcrca << 16) & 0xFFFF0000;
298                cmd = SD_CMD_CMD13_SEND_STATUS | SD_CMD_CMD_TYPE_NORMAL | SD_CMD_DP_NO_DATA_PRESENT |
299                        SD_CMD_CICE_ENABLE | SD_CMD_CCCE_ENABLE | SD_CMD_RSP_TYPE_R1;
300                if (mmccmd(cmd, arg, resp) == -1)
301                        return(-1);
302        } while ((resp[0] & SD_RSP10_R1_CURRENT_STATE) != SD_RSP10_R1_CURRENT_STATE_TRANSFER);
303
304        /* Change the clock frequency to 48 MHz and set the DTO to the maximum value setting */
305        MMC1_REG(SD_SYSCTL) &= ~SD_SYSCTL_DTO;
306        MMC1_REG(SD_SYSCTL) |= SD_SYSCTL_DTO_TCF_2_27;
307        MMC1_REG(SD_SYSCTL) = (MMC1_REG(SD_SYSCTL) & ~SD_SYSCTL_CLKD) | (2 << 6);
308
309        /* Wait for clock to stabilize */
310        while ((MMC1_REG(SD_SYSCTL) & SD_SYSCTL_ICS) != SD_SYSCTL_ICS);
311
312        /* Put the eMMC into Stand-by State */
313        arg = 0x00000000;
314        cmd = SD_CMD_CMD7_SELECT_DESELECT_CARD | SD_CMD_CMD_TYPE_NORMAL | SD_CMD_DP_NO_DATA_PRESENT |
315                SD_CMD_CICE_DISABLE | SD_CMD_CCCE_DISABLE | SD_CMD_RSP_TYPE_NO_RESPONSE;
316        if (mmccmd(cmd, arg, resp) == -1)
317                return(-1);
318
319        /* Wait for the eMMC to enter Stand-by State */
320        do {
321                arg = (mmcrca << 16) & 0xFFFF0000;
322                cmd = SD_CMD_CMD13_SEND_STATUS | SD_CMD_CMD_TYPE_NORMAL | SD_CMD_DP_NO_DATA_PRESENT |
323                        SD_CMD_CICE_ENABLE | SD_CMD_CCCE_ENABLE | SD_CMD_RSP_TYPE_R1;
324                if (mmccmd(cmd, arg, resp) == -1)
325                        return(-1);
326        } while ((resp[0] & SD_RSP10_R1_CURRENT_STATE) != SD_RSP10_R1_CURRENT_STATE_STANDBY);
327
328        return(0);
329}
330
331int
332mmcRead(int interface, char *buf, int blknum, int blkcnt)
333{
334        return(-1);
335}
336
337int
338mmcWrite(int interface, char *buf, int blknum, int blkcnt)
339{
340        return(-1);
341}
342
343int
344mmcInstalled(int interface)
345{
346        return(1);
347}
Note: See TracBrowser for help on using the repository browser.