1 /* 2 * Copyright 2018 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * B Krishnan Iyer, krishnaniyer97@gmail.com 7 */ 8 #include "mmc_bus.h" 9 10 #include <Errors.h> 11 12 #include <stdint.h> 13 14 15 MMCBus::MMCBus(device_node* node) 16 : 17 fNode(node), 18 fController(NULL), 19 fCookie(NULL), 20 fStatus(B_OK), 21 fWorkerThread(0) 22 { 23 CALLED(); 24 25 // Get the parent info, it includes the API to send commands to the hardware 26 device_node* parent = gDeviceManager->get_parent_node(node); 27 fStatus = gDeviceManager->get_driver(parent, 28 (driver_module_info**)&fController, &fCookie); 29 gDeviceManager->put_node(parent); 30 31 if (fStatus != B_OK) { 32 ERROR("Not able to establish the bus %s\n", 33 strerror(fStatus)); 34 return; 35 } 36 37 // TODO enumerate the bus (in a separate thread?) 38 fWorkerThread = spawn_kernel_thread(WorkerThread, "SD bus controller", 39 B_NORMAL_PRIORITY, this); 40 resume_thread(fWorkerThread); 41 } 42 43 44 MMCBus::~MMCBus() 45 { 46 CALLED(); 47 48 // stop worker thread 49 fStatus = B_SHUTTING_DOWN; 50 51 status_t result; 52 if (fWorkerThread != 0) 53 wait_for_thread(fWorkerThread, &result); 54 // TODO power off cards, stop clock, etc if needed. 55 } 56 57 58 status_t 59 MMCBus::InitCheck() 60 { 61 return fStatus; 62 } 63 64 65 status_t 66 MMCBus::ExecuteCommand(uint8_t command, uint32_t argument, uint32_t* response) 67 { 68 return fController->execute_command(fCookie, command, argument, response); 69 } 70 71 72 status_t 73 MMCBus::WorkerThread(void* cookie) 74 { 75 TRACE("worker thread spawned.\n"); 76 77 MMCBus* bus = (MMCBus*)cookie; 78 uint32_t response; 79 80 // FIXME wait for bus to signal a card is inserted 81 // We assume the bus defaults to 400kHz clock and has already powered on 82 // cards. 83 84 // Reset all cards on the bus 85 bus->ExecuteCommand(0, 0, NULL); 86 87 // Probe the voltage range 88 // FIXME MMC cards will not reply to this! They expect CMD1 instead 89 // SD v1 cards will also not reply, but we can proceed to ACMD41 90 // If ACMD41 also does not work, it may be an SDIO card, too 91 uint32_t probe = (1 << 8) | 0x55; 92 uint32_t hcs = 1 << 30; 93 if (bus->ExecuteCommand(8, probe, &response) != B_OK) { 94 TRACE("Card does not implement CMD8, may be a V1 SD card\n"); 95 // Do not check for SDHC support in this case 96 hcs = 0; 97 } else if (response != probe) { 98 ERROR("Card does not support voltage range (expected %x, reply %x)\n", 99 probe, response); 100 // TODO what now? 101 } 102 103 // Probe OCR, waiting for card to become ready 104 uint32_t ocr; 105 do { 106 uint32_t cardStatus; 107 while (bus->ExecuteCommand(55, 0, &cardStatus) 108 == B_BUSY) { 109 // FIXME we shouldn't get here if we handle CMD8 failure properly 110 ERROR("Card locked after CMD8...\n"); 111 snooze(1000000); 112 } 113 if ((cardStatus & 0xFFFF8000) != 0) 114 ERROR("SD card reports error\n"); 115 if ((cardStatus & (1 << 5)) == 0) 116 ERROR("Card did not enter ACMD mode"); 117 118 bus->ExecuteCommand(41, hcs | 0xFF8000, &ocr); 119 120 if ((ocr & (1 << 31)) == 0) { 121 TRACE("Card is busy\n"); 122 snooze(100000); 123 } 124 } while (((ocr & (1 << 31)) == 0)); 125 126 if (ocr & hcs != 0) 127 TRACE("Card is SDHC"); 128 if (ocr & (1 << 29) != 0) 129 TRACE("Card supports UHS-II"); 130 if (ocr & (1 << 24) != 0) 131 TRACE("Card supports 1.8v"); 132 TRACE("Voltage range: %x\n", ocr & 0xFFFFFF); 133 134 // TODO send CMD11 to switch to low voltage mode if card supports it? 135 136 uint32_t cid[4]; 137 bus->ExecuteCommand(2, 0, cid); 138 139 TRACE("Manufacturer: %02x%c%c\n", cid[3] >> 16, cid[3] >> 8, cid[3]); 140 TRACE("Name: %c%c%c%c%c\n", cid[2] >> 24, cid[2] >> 16, cid[2] >> 8, 141 cid[2], cid[1] >> 24); 142 TRACE("Revision: %d.%d\n", (cid[1] >> 20) & 0xF, (cid[1] >> 16) & 0xF); 143 TRACE("Serial number: %x\n", (cid[1] << 16) | (cid[0] >> 16)); 144 TRACE("Date: %d/%d\n", cid[0] & 0xF, 2000 + ((cid[0] >> 4) & 0xFF)); 145 146 bus->ExecuteCommand(3, 0, &response); 147 148 TRACE("RCA: %x Status: %x\n", response >> 16, response & 0xFFFF); 149 150 if ((response & 0xFF00) != 0x5000) 151 ERROR("Card did not enter data state\n"); 152 153 // The card now has an RCA and it entered the data phase, which means our 154 // initializing job is over, we can pass it on to the mmc_disk driver. 155 156 // TODO publish child device for the card 157 // TODO fill it with attributes from the CID 158 159 // TODO iterate CMD2/CMD3 to assign an RCA to all cards (and publish devices 160 // for each of them) 161 } 162