1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <inttypes.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 
10 #include <ddk/device.h>
11 #include <ddk/debug.h>
12 #include <ddk/protocol/sdmmc.h>
13 
14 #include "sdmmc.h"
15 
16 // If this bit is set in the Operating Conditions Register, then we know that
17 // the card is a SDHC (high capacity) card.
18 #define OCR_SDHC      0xc0000000
19 
20 // The "STRUCTURE" field of the "Card Specific Data" register defines the
21 // version of the structure and how to interpret the rest of the bits.
22 #define CSD_STRUCT_V1 0x0
23 #define CSD_STRUCT_V2 0x1
24 
sdmmc_probe_sd(sdmmc_device_t * dev)25 zx_status_t sdmmc_probe_sd(sdmmc_device_t* dev) {
26     // TODO comment ths out for now, we do not have SD card support
27     return ZX_ERR_NOT_SUPPORTED;
28 #if 0
29     // Issue the SEND_IF_COND command, this will tell us that we can talk to
30     // the card correctly and it will also tell us if the voltage range that we
31     // have supplied has been accepted.
32     zx_status_t st = sd_send_if_cond(dev);
33     if (st != ZX_OK) {
34         return st;
35     } else {
36         return ZX_OK;
37     }
38 
39     // Get the operating conditions from the card.
40     if ((st = sdmmc_do_command(sdmmc->host_zxdev, SDMMC_APP_CMD, 0, setup_txn)) != ZX_OK) {
41         zxlogf(ERROR, "sd: SDMMC_APP_CMD failed, retcode = %d\n", st);
42         goto err;
43     }
44     if ((sdmmc_do_command(sdmmc->host_zxdev, SDMMC_SD_SEND_OP_COND, 0, setup_txn)) != ZX_OK) {
45         zxlogf(ERROR, "sd: SDMMC_SD_SEND_OP_COND failed, retcode = %d\n", st);
46         goto err;
47     }
48 
49     int attempt = 0;
50     const int max_attempts = 10;
51     bool card_supports_18v_signalling = false;
52     while (true) {
53         // Ask for high speed.
54         const uint32_t flags = (1 << 30)  | 0x00ff8000 | (1 << 24);
55         if ((st = sdmmc_do_command(sdmmc->host_zxdev, SDMMC_APP_CMD, 0, setup_txn)) != ZX_OK) {
56             zxlogf(ERROR, "sd: APP_CMD failed with retcode = %d\n", st);
57             goto err;
58         }
59         if ((st = sdmmc_do_command(sdmmc->host_zxdev, SDMMC_SD_SEND_OP_COND, flags, setup_txn)) != ZX_OK) {
60             zxlogf(ERROR, "sd: SD_SEND_OP_COND failed with retcode = %d\n", st);
61             goto err;
62         }
63 
64         const uint32_t ocr = pdata->response[0];
65         if (ocr & (1 << 31)) {
66             if (!(ocr & OCR_SDHC)) {
67                 // Card is not an SDHC card. We currently don't support this.
68                 zxlogf(ERROR, "sd: unsupported card type, must use sdhc card\n");
69                 goto err;
70             }
71             card_supports_18v_signalling = !!((ocr >> 24) & 0x1);
72             break;
73         }
74 
75         if (++attempt == max_attempts) {
76             zxlogf(ERROR, "sd: too many attempt trying to negotiate card OCR\n");
77             goto err;
78         }
79 
80         zx_nanosleep(zx_deadline_after(ZX_MSEC(5)));
81     }
82 
83     st = sdmmc_set_bus_freq(&sdmmc->host, 25000000);
84     if (st != ZX_OK) {
85         // This is non-fatal but the card will run slowly.
86         zxlogf(ERROR, "sd: failed to increase bus frequency.\n");
87     }
88 
89     // Try to switch the bus voltage to 1.8v
90     if (card_supports_18v_signalling) {
91         if ((st = sdmmc_do_command(sdmmc->host_zxdev, SDMMC_VOLTAGE_SWITCH, 0, setup_txn)) != ZX_OK) {
92             zxlogf(ERROR, "sd: failed to send switch voltage command to card, "
93                     "retcode = %d\n", st);
94             goto err;
95         }
96 
97         st = sdmmc_set_signal_voltage(&sdmmc->host, SDMMC_VOLTAGE_180);
98         if (st != ZX_OK) {
99             zxlogf(ERROR, "sd: Card supports 1.8v signalling but was unable to "
100                     "switch to 1.8v mode, retcode = %d\n", st);
101             goto err;
102         }
103     }
104 
105     if ((st = sdmmc_do_command(sdmmc->host_zxdev, SDMMC_ALL_SEND_CID, 0, setup_txn)) != ZX_OK) {
106         zxlogf(ERROR, "sd: ALL_SEND_CID failed with retcode = %d\n", st);
107         goto err;
108     }
109 
110     if ((st = sdmmc_do_command(sdmmc->host_zxdev, SDMMC_SEND_RELATIVE_ADDR, 0, setup_txn)) != ZX_OK) {
111         zxlogf(ERROR, "sd: SEND_RELATIVE_ADDR failed with retcode = %d\n", st);
112         goto err;
113     }
114 
115     sdmmc->type = SDMMC_TYPE_SD;
116     sdmmc->rca = (pdata->response[0] >> 16) & 0xffff;
117     if (pdata->response[0] & 0xe000) {
118         zxlogf(ERROR, "sd: SEND_RELATIVE_ADDR failed with resp = %d\n",
119                 (pdata->response[0] & 0xe000));
120         st = ZX_ERR_INTERNAL;
121         goto err;
122     }
123     if ((pdata->response[0] & (1u << 8)) == 0) {
124         zxlogf(ERROR, "sd: SEND_RELATIVE_ADDR failed. Card not ready.\n");
125         st = ZX_ERR_INTERNAL;
126         goto err;
127     }
128 
129     // Determine the size of the card.
130     if ((st = sdmmc_do_command(sdmmc->host_zxdev, SDMMC_SEND_CSD, sdmmc->rca << 16, setup_txn)) != ZX_OK) {
131         zxlogf(ERROR, "sd: failed to send app cmd, retcode = %d\n", st);
132         goto err;
133     }
134 
135     // For now we only support SDHC cards. These cards must have a CSD type = 1,
136     // since CSD type 0 is unable to support SDHC sized cards.
137     uint8_t csd_structure = (pdata->response[0] >> 30) & 0x3;
138     if (csd_structure != CSD_STRUCT_V2) {
139         zxlogf(ERROR, "sd: unsupported card type, expected CSD version = %d, "
140                 "got version %d\n", CSD_STRUCT_V2, csd_structure);
141         goto err;
142     }
143 
144     const uint32_t c_size = ((pdata->response[2] >> 16) |
145                              (pdata->response[1] << 16)) & 0x3fffff;
146     sdmmc->capacity = (c_size + 1ul) * 512ul * 1024ul;
147     printf("sd: found card with capacity = %"PRIu64"B\n", sdmmc->capacity);
148 
149     if ((st = sdmmc_do_command(sdmmc->host_zxdev, SDMMC_SELECT_CARD, sdmmc->rca << 16, setup_txn)) != ZX_OK) {
150         zxlogf(ERROR, "sd: SELECT_CARD failed with retcode = %d\n", st);
151         goto err;
152     }
153 
154     pdata->blockcount = 1;
155     pdata->blocksize = 8;
156     if ((st = sdmmc_do_command(sdmmc->host_zxdev, SDMMC_APP_CMD, sdmmc->rca << 16, setup_txn)) != ZX_OK) {
157         zxlogf(ERROR, "sd: APP_CMD failed with retcode = %d\n", st);
158         goto err;
159     }
160     if ((st = sdmmc_do_command(sdmmc->host_zxdev, SDMMC_SEND_SCR, 0, setup_txn)) != ZX_OK) {
161         zxlogf(ERROR, "sd: SEND_SCR failed with retcode = %d\n", st);
162         goto err;
163     }
164     pdata->blockcount = 512;
165     pdata->blocksize = 1;
166 
167     uint32_t scr;
168     iotxn_copyfrom(setup_txn, &scr, sizeof(scr), 0);
169     scr = be32toh(scr);
170 
171     // If this card supports 4 bit mode, then put it into 4 bit mode.
172     const uint32_t supported_bus_widths = (scr >> 16) & 0xf;
173     if (supported_bus_widths & 0x4) {
174         do {
175             // First tell the card to go into four bit mode:
176             if ((st = sdmmc_do_command(sdmmc->host_zxdev, SDMMC_APP_CMD, sdmmc->rca << 16, setup_txn)) != ZX_OK) {
177                 zxlogf(ERROR, "sd: failed to send app cmd, retcode = %d\n", st);
178                 break;
179             }
180             if ((st = sdmmc_do_command(sdmmc->host_zxdev, SDMMC_SET_BUS_WIDTH, 2, setup_txn)) != ZX_OK) {
181                 zxlogf(ERROR, "sd: failed to set card bus width, retcode = %d\n", st);
182                 break;
183             }
184             st = sdmmc_set_bus_width(&sdmmc->host, SDMMC_BUS_WIDTH_4);
185             if (st != ZX_OK) {
186                 zxlogf(ERROR, "sd: failed to set host bus width, retcode = %d\n", st);
187             }
188         } while (false);
189     }
190 #endif
191 }
192 
193