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 <pretty/hexdump.h>
15 
16 #include "sdmmc.h"
17 
18 #define FREQ_200MHZ 200000000
19 #define FREQ_52MHZ 52000000
20 #define FREQ_25MHZ 25000000
21 
22 #define MMC_SECTOR_SIZE  512ul  // physical sector size
23 #define MMC_BLOCK_SIZE   512ul  // block size is 512 bytes always because it is the required
24                                 // value if the card is in DDR mode
25 
mmc_do_switch(sdmmc_device_t * dev,uint8_t index,uint8_t value)26 static zx_status_t mmc_do_switch(sdmmc_device_t* dev, uint8_t index, uint8_t value) {
27     // Send the MMC_SWITCH command
28     zx_status_t st = mmc_switch(dev, index, value);
29     if (st != ZX_OK) {
30         zxlogf(ERROR, "mmc: failed to MMC_SWITCH (0x%x=%d), retcode = %d\n", index, value, st);
31         return st;
32     }
33 
34     // Check status after MMC_SWITCH
35     uint32_t resp;
36     st = sdmmc_send_status(dev, &resp);
37     if (st == ZX_OK) {
38         if (resp & MMC_STATUS_SWITCH_ERR) {
39             zxlogf(ERROR, "mmc: mmc status error after MMC_SWITCH (0x%x=%d), status = 0x%08x\n",
40                    index, value, resp);
41             st = ZX_ERR_INTERNAL;
42         }
43     } else {
44         zxlogf(ERROR, "mmc: failed to MMC_SEND_STATUS (%x=%d), retcode = %d\n", index, value, st);
45     }
46 
47     return ZX_OK;
48 }
49 
mmc_set_bus_width(sdmmc_device_t * dev,sdmmc_bus_width_t bus_width,uint8_t mmc_ext_csd_bus_width)50 static zx_status_t mmc_set_bus_width(sdmmc_device_t* dev, sdmmc_bus_width_t bus_width,
51                                      uint8_t mmc_ext_csd_bus_width) {
52     // Switch the card to the new bus width
53     zx_status_t st = mmc_do_switch(dev, MMC_EXT_CSD_BUS_WIDTH, mmc_ext_csd_bus_width);
54     if (st != ZX_OK) {
55         zxlogf(ERROR, "mmc: failed to switch bus width to EXT_CSD %d, retcode = %d\n",
56                mmc_ext_csd_bus_width, st);
57         return ZX_ERR_INTERNAL;
58     }
59 
60     if (bus_width != dev->bus_width) {
61         // Switch the host to the new bus width
62         if ((st = sdmmc_set_bus_width(&dev->host, bus_width)) != ZX_OK) {
63             zxlogf(ERROR, "mmc: failed to switch the host bus width to %d, retcode = %d\n",
64                    bus_width, st);
65             return ZX_ERR_INTERNAL;
66         }
67     }
68     dev->bus_width = bus_width;
69     return ZX_OK;
70 }
71 
mmc_select_bus_width(sdmmc_device_t * dev)72 static uint8_t mmc_select_bus_width(sdmmc_device_t* dev) {
73     // TODO verify host 8-bit support
74     uint8_t bus_widths[] = { SDMMC_BUS_WIDTH_EIGHT, MMC_EXT_CSD_BUS_WIDTH_8,
75                              SDMMC_BUS_WIDTH_FOUR, MMC_EXT_CSD_BUS_WIDTH_4,
76                              SDMMC_BUS_WIDTH_ONE, MMC_EXT_CSD_BUS_WIDTH_1 };
77     for (unsigned i = 0; i < (sizeof(bus_widths)/sizeof(uint8_t)); i += 2) {
78         if (mmc_set_bus_width(dev, bus_widths[i], bus_widths[i+1]) == ZX_OK) {
79             break;
80         }
81     }
82     return dev->bus_width;
83 }
84 
mmc_switch_timing(sdmmc_device_t * dev,sdmmc_timing_t new_timing)85 static zx_status_t mmc_switch_timing(sdmmc_device_t* dev, sdmmc_timing_t new_timing) {
86     // Switch the device timing
87     uint8_t ext_csd_timing;
88     switch (new_timing) {
89     case SDMMC_TIMING_LEGACY:
90         ext_csd_timing = MMC_EXT_CSD_HS_TIMING_LEGACY;
91         break;
92     case SDMMC_TIMING_HS:
93         ext_csd_timing = MMC_EXT_CSD_HS_TIMING_HS;
94         break;
95     case SDMMC_TIMING_HSDDR:
96         // sdhci has a different timing constant for HSDDR vs HS
97         ext_csd_timing = MMC_EXT_CSD_HS_TIMING_HS;
98         break;
99     case SDMMC_TIMING_HS200:
100         ext_csd_timing = MMC_EXT_CSD_HS_TIMING_HS200;
101         break;
102     case SDMMC_TIMING_HS400:
103         ext_csd_timing = MMC_EXT_CSD_HS_TIMING_HS400;
104         break;
105     default:
106         return ZX_ERR_INVALID_ARGS;
107     };
108 
109     zx_status_t st = mmc_do_switch(dev, MMC_EXT_CSD_HS_TIMING, ext_csd_timing);
110     if (st != ZX_OK) {
111         zxlogf(ERROR, "mmc: failed to switch device timing to %d\n", new_timing);
112         return st;
113     }
114 
115     // Switch the host timing
116     if ((st = sdmmc_set_timing(&dev->host, new_timing)) != ZX_OK) {
117         zxlogf(ERROR, "mmc: failed to switch host timing to %d\n", new_timing);
118         return st;
119     }
120 
121     dev->timing = new_timing;
122     return st;
123 }
124 
mmc_switch_freq(sdmmc_device_t * dev,uint32_t new_freq)125 static zx_status_t mmc_switch_freq(sdmmc_device_t* dev, uint32_t new_freq) {
126     zx_status_t st;
127     if ((st = sdmmc_set_bus_freq(&dev->host, new_freq)) != ZX_OK) {
128         zxlogf(ERROR, "mmc: failed to set host bus frequency, retcode = %d\n", st);
129         return st;
130     }
131     dev->clock_rate = new_freq;
132     return ZX_OK;
133 }
134 
mmc_decode_cid(sdmmc_device_t * dev,const uint8_t * raw_cid)135 static zx_status_t mmc_decode_cid(sdmmc_device_t* dev, const uint8_t* raw_cid) {
136     printf("mmc: product name=%c%c%c%c%c%c\n",
137             raw_cid[MMC_CID_PRODUCT_NAME_START], raw_cid[MMC_CID_PRODUCT_NAME_START + 1],
138             raw_cid[MMC_CID_PRODUCT_NAME_START + 2], raw_cid[MMC_CID_PRODUCT_NAME_START + 3],
139             raw_cid[MMC_CID_PRODUCT_NAME_START + 4], raw_cid[MMC_CID_PRODUCT_NAME_START + 5]);
140     printf("       revision=%u.%u\n", (raw_cid[MMC_CID_REVISION] >> 4) & 0xf,
141             raw_cid[MMC_CID_REVISION] & 0xf);
142     printf("       serial=%u\n", *((uint32_t*)&raw_cid[MMC_CID_SERIAL]));
143     return ZX_OK;
144 }
145 
mmc_decode_csd(sdmmc_device_t * dev,const uint8_t * raw_csd)146 static zx_status_t mmc_decode_csd(sdmmc_device_t* dev, const uint8_t* raw_csd) {
147     uint8_t spec_vrsn = (raw_csd[MMC_CSD_SPEC_VERSION] >> 2) & 0xf;
148     // Only support spec version > 4.0
149     if (spec_vrsn < MMC_CID_SPEC_VRSN_40) {
150         return ZX_ERR_NOT_SUPPORTED;
151     }
152 
153     zxlogf(SPEW, "mmc: CSD version %u spec version %u\n",
154            (raw_csd[MMC_CSD_SPEC_VERSION] >> 6) & 0x3, spec_vrsn);
155     if (driver_get_log_flags() & DDK_LOG_SPEW) {
156         zxlogf(SPEW, "CSD:\n");
157         hexdump8_ex(raw_csd, 16, 0);
158     }
159 
160     // Only support high capacity (> 2GB) cards
161     uint16_t c_size = ((raw_csd[MMC_CSD_SIZE_START] >> 6) & 0x3) |
162                       (raw_csd[MMC_CSD_SIZE_START + 1] << 2) |
163                       ((raw_csd[MMC_CSD_SIZE_START + 2] & 0x3) << 10);
164     if (c_size != 0xfff) {
165         zxlogf(ERROR, "mmc: unsupported C_SIZE 0x%04x\n", c_size);
166         return ZX_ERR_NOT_SUPPORTED;
167     }
168     return ZX_OK;
169 }
170 
mmc_decode_ext_csd(sdmmc_device_t * dev,const uint8_t * raw_ext_csd)171 static zx_status_t mmc_decode_ext_csd(sdmmc_device_t* dev, const uint8_t* raw_ext_csd) {
172     zxlogf(SPEW, "mmc: EXT_CSD version %u CSD version %u\n", raw_ext_csd[192], raw_ext_csd[194]);
173 
174     // Get the capacity for the card
175     uint32_t sectors = (raw_ext_csd[212] << 0) | (raw_ext_csd[213] << 8) |
176                        (raw_ext_csd[214] << 16) | (raw_ext_csd[215] << 24);
177     dev->block_info.block_count = sectors * MMC_SECTOR_SIZE / MMC_BLOCK_SIZE;
178     dev->block_info.block_size = (uint32_t)MMC_BLOCK_SIZE;
179 
180     zxlogf(TRACE, "mmc: found card with capacity = %" PRIu64 "B\n",
181            dev->block_info.block_count * dev->block_info.block_size);
182 
183     return ZX_OK;
184 }
185 
mmc_supports_hs(sdmmc_device_t * dev)186 static bool mmc_supports_hs(sdmmc_device_t* dev) {
187     uint8_t device_type = dev->raw_ext_csd[MMC_EXT_CSD_DEVICE_TYPE];
188     return (device_type & (1 << 1));
189 }
190 
mmc_supports_hsddr(sdmmc_device_t * dev)191 static bool mmc_supports_hsddr(sdmmc_device_t* dev) {
192     uint8_t device_type = dev->raw_ext_csd[MMC_EXT_CSD_DEVICE_TYPE];
193     // Only support HSDDR @ 1.8V/3V
194     return (device_type & (1 << 2));
195 }
196 
mmc_supports_hs200(sdmmc_device_t * dev)197 static bool mmc_supports_hs200(sdmmc_device_t* dev) {
198     uint8_t device_type = dev->raw_ext_csd[MMC_EXT_CSD_DEVICE_TYPE];
199     // Only support HS200 @ 1.8V
200     return (device_type & (1 << 4));
201 }
202 
mmc_supports_hs400(sdmmc_device_t * dev)203 static bool mmc_supports_hs400(sdmmc_device_t* dev) {
204     uint8_t device_type = dev->raw_ext_csd[MMC_EXT_CSD_DEVICE_TYPE];
205     // Only support HS400 @ 1.8V
206     return (device_type & (1 << 6));
207 }
208 
209 //Called with dev->lock held
sdmmc_probe_mmc(sdmmc_device_t * dev)210 zx_status_t sdmmc_probe_mmc(sdmmc_device_t* dev) {
211     zx_status_t st = ZX_OK;
212 
213     // Query OCR
214     uint32_t ocr = 0;
215     if ((st = mmc_send_op_cond(dev, ocr, &ocr)) != ZX_OK) {
216         zxlogf(ERROR, "mmc: MMC_SEND_OP_COND failed, retcode = %d\n", st);
217         goto err;
218     }
219 
220     // Indicate sector mode
221     if ((st = mmc_send_op_cond(dev, ocr, &ocr)) != ZX_OK) {
222         zxlogf(ERROR, "mmc: MMC_SEND_OP_COND failed, retcode = %d\n", st);
223         goto err;
224     }
225 
226     // Get CID from card
227     // Only supports 1 card currently so no need to loop
228     if ((st = mmc_all_send_cid(dev, dev->raw_cid)) != ZX_OK) {
229         zxlogf(ERROR, "mmc: MMC_ALL_SEND_CID failed, retcode = %d\n", st);
230         goto err;
231     }
232     zxlogf(SPEW, "mmc: MMC_ALL_SEND_CID cid 0x%08x 0x%08x 0x%08x 0x%08x\n",
233         dev->raw_cid[0],
234         dev->raw_cid[1],
235         dev->raw_cid[2],
236         dev->raw_cid[3]);
237 
238     mmc_decode_cid(dev, (const uint8_t*)dev->raw_cid);
239 
240     // Set relative card address
241     if ((st = mmc_set_relative_addr(dev, 1)) != ZX_OK) {
242         zxlogf(ERROR, "mmc: MMC_SET_RELATIVE_ADDR failed, retcode = %d\n", st);
243         goto err;
244     }
245     dev->rca = 1;
246 
247     // Read CSD register
248     if ((st = mmc_send_csd(dev, dev->raw_csd)) != ZX_OK) {
249         zxlogf(ERROR, "mmc: MMC_SEND_CSD failed, retcode = %d\n", st);
250         goto err;
251     }
252 
253     if ((st = mmc_decode_csd(dev, (const uint8_t*)dev->raw_csd)) != ZX_OK) {
254         goto err;
255     }
256 
257     // Select the card
258     if ((st = mmc_select_card(dev)) != ZX_OK) {
259         zxlogf(ERROR, "mmc: MMC_SELECT_CARD failed, retcode = %d\n", st);
260         goto err;
261     }
262 
263     // Read extended CSD register
264     if ((st = mmc_send_ext_csd(dev, dev->raw_ext_csd)) != ZX_OK) {
265         zxlogf(ERROR, "mmc: MMC_SEND_EXT_CSD failed, retcode = %d\n", st);
266         goto err;
267     }
268 
269     if ((st = mmc_decode_ext_csd(dev, (const uint8_t*)dev->raw_ext_csd)) != ZX_OK) {
270         goto err;
271     }
272     dev->type = SDMMC_TYPE_MMC;
273     dev->bus_width = SDMMC_BUS_WIDTH_ONE;
274     dev->signal_voltage = SDMMC_VOLTAGE_V330;
275 
276     // Switch to high-speed timing
277     if (mmc_supports_hs(dev) || mmc_supports_hsddr(dev) || mmc_supports_hs200(dev)) {
278         // Switch to 1.8V signal voltage
279         sdmmc_voltage_t new_voltage = SDMMC_VOLTAGE_V180;
280         if ((st = sdmmc_set_signal_voltage(&dev->host, new_voltage)) != ZX_OK) {
281             zxlogf(ERROR, "mmc: failed to switch to 1.8V signalling, retcode = %d\n", st);
282             goto err;
283         }
284         dev->signal_voltage = new_voltage;
285 
286         mmc_select_bus_width(dev);
287 
288         // Must perform tuning at HS200 first if HS400 is supported
289         if (mmc_supports_hs200(dev) && dev->bus_width != SDMMC_BUS_WIDTH_ONE &&
290                 !(dev->host_info.prefs & SDMMC_HOST_PREFS_DISABLE_HS200)) {
291             if ((st = mmc_switch_timing(dev, SDMMC_TIMING_HS200)) != ZX_OK) {
292                 goto err;
293             }
294 
295             if ((st = mmc_switch_freq(dev, FREQ_200MHZ)) != ZX_OK) {
296                 goto err;
297             }
298 
299             if ((st = sdmmc_perform_tuning(&dev->host, MMC_SEND_TUNING_BLOCK)) != ZX_OK) {
300                 zxlogf(ERROR, "mmc: tuning failed %d\n", st);
301                 goto err;
302             }
303 
304             if (mmc_supports_hs400(dev) && dev->bus_width == SDMMC_BUS_WIDTH_EIGHT &&
305                     !(dev->host_info.prefs & SDMMC_HOST_PREFS_DISABLE_HS400)) {
306                 if ((st = mmc_switch_timing(dev, SDMMC_TIMING_HS)) != ZX_OK) {
307                     goto err;
308                 }
309 
310                 if ((st = mmc_switch_freq(dev, FREQ_52MHZ)) != ZX_OK) {
311                     goto err;
312                 }
313 
314                 if ((st = mmc_set_bus_width(dev, SDMMC_BUS_WIDTH_EIGHT,
315                                             MMC_EXT_CSD_BUS_WIDTH_8_DDR)) != ZX_OK) {
316                     goto err;
317                 }
318 
319                 if ((st = mmc_switch_timing(dev, SDMMC_TIMING_HS400)) != ZX_OK) {
320                     goto err;
321                 }
322 
323                 if ((st = mmc_switch_freq(dev, FREQ_200MHZ)) != ZX_OK) {
324                     goto err;
325                 }
326             }
327         } else {
328             if ((st = mmc_switch_timing(dev, SDMMC_TIMING_HS)) != ZX_OK) {
329                 goto err;
330             }
331 
332             if (mmc_supports_hsddr(dev) && (dev->bus_width != SDMMC_BUS_WIDTH_ONE)) {
333                 if ((st = mmc_switch_timing(dev, SDMMC_TIMING_HSDDR)) != ZX_OK) {
334                     goto err;
335                 }
336 
337                 uint8_t mmc_bus_width = (dev->bus_width == SDMMC_BUS_WIDTH_FOUR) ?
338                                             MMC_EXT_CSD_BUS_WIDTH_4_DDR :
339                                             MMC_EXT_CSD_BUS_WIDTH_8_DDR;
340                 if ((st = mmc_set_bus_width(dev, dev->bus_width, mmc_bus_width)) != ZX_OK) {
341                     goto err;
342                 }
343             }
344 
345             if ((st = mmc_switch_freq(dev, FREQ_52MHZ)) != ZX_OK) {
346                 goto err;
347             }
348         }
349     } else {
350         // Set the bus frequency to legacy timing
351         if ((st = mmc_switch_freq(dev, FREQ_25MHZ)) != ZX_OK) {
352             goto err;
353         }
354         dev->timing = SDMMC_TIMING_LEGACY;
355     }
356 
357     zxlogf(INFO, "mmc: initialized mmc @ %u MHz, bus width %d, timing %d\n",
358             dev->clock_rate / 1000000, dev->bus_width, dev->timing);
359 
360 err:
361     return st;
362 }
363