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 25zx_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