1 /* 2 * Copyright 2018-2024 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 * Adrien Destugues, pulkomandy@pulkomandy.tk 8 * Ron Ben Aroya, sed4906birdie@gmail.com 9 */ 10 #include <algorithm> 11 #include <new> 12 #include <stdio.h> 13 #include <string.h> 14 15 #include <bus/PCI.h> 16 #include <ACPI.h> 17 #include "acpi.h" 18 19 #include <KernelExport.h> 20 21 #include "IOSchedulerSimple.h" 22 #include "mmc.h" 23 #include "sdhci.h" 24 25 26 //#define TRACE_SDHCI 27 #ifdef TRACE_SDHCI 28 # define TRACE(x...) dprintf("\33[33msdhci:\33[0m " x) 29 #else 30 # define TRACE(x...) ; 31 #endif 32 #define TRACE_ALWAYS(x...) dprintf("\33[33msdhci:\33[0m " x) 33 #define ERROR(x...) dprintf("\33[33msdhci:\33[0m " x) 34 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 35 36 37 #define SDHCI_DEVICE_MODULE_NAME "busses/mmc/sdhci/driver_v1" 38 #define SDHCI_PCI_MMC_BUS_MODULE_NAME "busses/mmc/sdhci/pci/device/v1" 39 40 #define SLOT_NUMBER "device/slot" 41 #define BAR_INDEX "device/bar" 42 43 status_t 44 init_bus_pci(device_node* node, void** bus_cookie) 45 { 46 CALLED(); 47 48 // Get the PCI driver and device 49 pci_device_module_info* pci; 50 pci_device* device; 51 52 device_node* parent = gDeviceManager->get_parent_node(node); 53 device_node* pciParent = gDeviceManager->get_parent_node(parent); 54 gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci, 55 (void**)&device); 56 gDeviceManager->put_node(pciParent); 57 gDeviceManager->put_node(parent); 58 59 uint8_t bar, slot; 60 if (gDeviceManager->get_attr_uint8(node, SLOT_NUMBER, &slot, false) < B_OK 61 || gDeviceManager->get_attr_uint8(node, BAR_INDEX, &bar, false) < B_OK) 62 return B_BAD_TYPE; 63 64 // Ignore invalid bars 65 TRACE("Register SD bus at slot %d, using bar %d\n", slot + 1, bar); 66 67 pci_info pciInfo; 68 pci->get_pci_info(device, &pciInfo); 69 70 for (; bar < 6 && slot > 0; bar++, slot--) { 71 if ((pciInfo.u.h0.base_register_flags[bar] & PCI_address_type) 72 == PCI_address_type_64) { 73 bar++; 74 } 75 } 76 77 phys_addr_t physicalAddress = pciInfo.u.h0.base_registers[bar]; 78 uint64 barSize = pciInfo.u.h0.base_register_sizes[bar]; 79 if ((pciInfo.u.h0.base_register_flags[bar] & PCI_address_type) 80 == PCI_address_type_64) { 81 physicalAddress |= (uint64)pciInfo.u.h0.base_registers[bar + 1] << 32; 82 barSize |= (uint64)pciInfo.u.h0.base_register_sizes[bar + 1] << 32; 83 } 84 85 if (physicalAddress == 0 || barSize == 0) { 86 ERROR("No registers to map\n"); 87 return B_IO_ERROR; 88 } 89 90 // enable bus master and io 91 uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2); 92 pcicmd &= ~(PCI_command_int_disable | PCI_command_io); 93 pcicmd |= PCI_command_master | PCI_command_memory; 94 pci->write_pci_config(device, PCI_command, 2, pcicmd); 95 96 // map the slot registers 97 area_id regs_area; 98 struct registers* _regs; 99 regs_area = map_physical_memory("sdhc_regs_map", 100 physicalAddress, barSize, B_ANY_KERNEL_BLOCK_ADDRESS, 101 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&_regs); 102 103 if (regs_area < B_OK) { 104 ERROR("Could not map registers\n"); 105 return B_BAD_VALUE; 106 } 107 108 // the interrupt is shared between all busses in an SDHC controller, but 109 // they each register an handler. Not a problem, we will just test the 110 // interrupt registers for all busses one after the other and find no 111 // interrupts on the idle busses. 112 uint8_t irq = pciInfo.u.h0.interrupt_line; 113 TRACE("irq interrupt line: %d\n", irq); 114 115 SdhciBus* bus = new(std::nothrow) SdhciBus(_regs, irq, false); 116 117 status_t status = B_NO_MEMORY; 118 if (bus != NULL) 119 status = bus->InitCheck(); 120 121 if (status != B_OK) { 122 if (bus != NULL) 123 delete bus; 124 else 125 delete_area(regs_area); 126 return status; 127 } 128 129 // Store the created object as a cookie, allowing users of the bus to 130 // locate it. 131 *bus_cookie = bus; 132 133 return status; 134 } 135 136 status_t 137 register_child_devices_pci(void* cookie) 138 { 139 CALLED(); 140 SdhciDevice* context = (SdhciDevice*)cookie; 141 device_node* parent = gDeviceManager->get_parent_node(context->fNode); 142 pci_device_module_info* pci; 143 pci_device* device; 144 145 gDeviceManager->get_driver(parent, (driver_module_info**)&pci, 146 (void**)&device); 147 uint8 slotsInfo = pci->read_pci_config(device, SDHCI_PCI_SLOT_INFO, 1); 148 uint8 bar = SDHCI_PCI_SLOT_INFO_FIRST_BASE_INDEX(slotsInfo); 149 uint8 slotsCount = SDHCI_PCI_SLOTS(slotsInfo); 150 151 TRACE("register_child_devices: %u, %u\n", bar, slotsCount); 152 153 char prettyName[25]; 154 155 if (slotsCount > 6 || bar > 5) { 156 ERROR("Invalid slots count: %d or BAR count: %d \n", slotsCount, bar); 157 return B_BAD_VALUE; 158 } 159 160 for (uint8_t slot = 0; slot < slotsCount; slot++) { 161 sprintf(prettyName, "SDHC bus %" B_PRIu8, slot); 162 device_attr attrs[] = { 163 // properties of this controller for mmc bus manager 164 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { .string = prettyName } }, 165 { B_DEVICE_FIXED_CHILD, B_STRING_TYPE, 166 {.string = MMC_BUS_MODULE_NAME} }, 167 { B_DEVICE_BUS, B_STRING_TYPE, {.string = "mmc"} }, 168 169 // DMA properties 170 // The high alignment is to force access only to complete sectors 171 // These constraints could be removed by using ADMA which allows 172 // use of the full 64bit address space and can do scatter-gather. 173 { B_DMA_ALIGNMENT, B_UINT32_TYPE, { .ui32 = 511 }}, 174 { B_DMA_HIGH_ADDRESS, B_UINT64_TYPE, { .ui64 = 0x100000000LL }}, 175 { B_DMA_BOUNDARY, B_UINT32_TYPE, { .ui32 = (1 << 19) - 1 }}, 176 { B_DMA_MAX_SEGMENT_COUNT, B_UINT32_TYPE, { .ui32 = 1 }}, 177 { B_DMA_MAX_SEGMENT_BLOCKS, B_UINT32_TYPE, { .ui32 = (1 << 10) - 1 }}, 178 179 // private data to identify device 180 { SLOT_NUMBER, B_UINT8_TYPE, { .ui8 = slot} }, 181 { BAR_INDEX, B_UINT8_TYPE, { .ui8 = bar} }, 182 { NULL } 183 }; 184 device_node* node; 185 if (gDeviceManager->register_node(context->fNode, 186 SDHCI_PCI_MMC_BUS_MODULE_NAME, attrs, NULL, 187 &node) != B_OK) 188 return B_BAD_VALUE; 189 } 190 return B_OK; 191 } 192 193 status_t 194 init_device_pci(device_node* node, SdhciDevice* context) 195 { 196 // Get the PCI driver and device 197 pci_device_module_info* pci; 198 pci_device* device; 199 uint16 vendorId, deviceId; 200 201 device_node* pciParent = gDeviceManager->get_parent_node(context->fNode); 202 gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci, 203 (void**)&device); 204 gDeviceManager->put_node(pciParent); 205 206 if (gDeviceManager->get_attr_uint16(node, B_DEVICE_VENDOR_ID, 207 &vendorId, true) != B_OK 208 || gDeviceManager->get_attr_uint16(node, B_DEVICE_ID, &deviceId, 209 true) != B_OK) { 210 panic("No vendor or device id attribute\n"); 211 return B_OK; // Let's hope it didn't need the quirk? 212 } 213 214 if (vendorId == 0x1180 && deviceId == 0xe823) { 215 // Switch the device to SD2.0 mode 216 // This should change its device id to 0xe822 if succesful. 217 // The device then remains in SD2.0 mode even after reboot. 218 pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE_KEY, 1, 0xfc); 219 context->fRicohOriginalMode = pci->read_pci_config(device, 220 SDHCI_PCI_RICOH_MODE, 1); 221 pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE, 1, 222 SDHCI_PCI_RICOH_MODE_SD20); 223 pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE_KEY, 1, 0); 224 225 deviceId = pci->read_pci_config(device, 2, 2); 226 TRACE("Device ID after Ricoh quirk: %x\n", deviceId); 227 } 228 229 return B_OK; 230 } 231 232 void 233 uninit_device_pci(SdhciDevice* context, device_node* pciParent) 234 { 235 // Get the PCI driver and device 236 pci_device_module_info* pci; 237 pci_device* device; 238 uint16 vendorId, deviceId; 239 240 gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci, 241 (void**)&device); 242 243 if (gDeviceManager->get_attr_uint16(context->fNode, B_DEVICE_VENDOR_ID, 244 &vendorId, true) != B_OK 245 || gDeviceManager->get_attr_uint16(context->fNode, B_DEVICE_ID, 246 &deviceId, false) != B_OK) { 247 ERROR("No vendor or device id attribute\n"); 248 } else if (vendorId == 0x1180 && deviceId == 0xe823) { 249 pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE_KEY, 1, 0xfc); 250 pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE, 1, 251 context->fRicohOriginalMode); 252 pci->write_pci_config(device, SDHCI_PCI_RICOH_MODE_KEY, 1, 0); 253 } 254 } 255 256 float 257 supports_device_pci(device_node* parent) 258 { 259 uint16 type, subType; 260 uint16 vendorId, deviceId; 261 262 if (gDeviceManager->get_attr_uint16(parent, B_DEVICE_VENDOR_ID, &vendorId, 263 false) != B_OK 264 || gDeviceManager->get_attr_uint16(parent, B_DEVICE_ID, &deviceId, 265 false) != B_OK) { 266 TRACE("No vendor or device id attribute\n"); 267 return 0.0f; 268 } 269 270 TRACE("supports_device(vid:%04x pid:%04x)\n", vendorId, deviceId); 271 272 if (gDeviceManager->get_attr_uint16(parent, B_DEVICE_SUB_TYPE, &subType, 273 false) < B_OK 274 || gDeviceManager->get_attr_uint16(parent, B_DEVICE_TYPE, &type, 275 false) < B_OK) { 276 TRACE("Could not find type/subtype attributes\n"); 277 return -1; 278 } 279 280 if (type == PCI_base_peripheral) { 281 if (subType != PCI_sd_host) { 282 // Also accept some compliant devices that do not advertise 283 // themselves as such. 284 if (vendorId != 0x1180 285 || (deviceId != 0xe823 && deviceId != 0xe822)) { 286 TRACE("Not the right subclass, and not a Ricoh device\n"); 287 return 0.0f; 288 } 289 } 290 291 pci_device_module_info* pci; 292 pci_device* device; 293 gDeviceManager->get_driver(parent, (driver_module_info**)&pci, 294 (void**)&device); 295 TRACE("SDHCI Device found! Subtype: 0x%04x, type: 0x%04x\n", 296 subType, type); 297 298 return 0.8f; 299 } 300 301 return 0.0f; 302 } 303 304 // Device node registered for each SD slot. It implements the MMC operations so 305 // the bus manager can use it to communicate with SD cards. 306 mmc_bus_interface gSDHCIPCIDeviceModule = { 307 .info = { 308 .info = { 309 .name = SDHCI_PCI_MMC_BUS_MODULE_NAME, 310 }, 311 312 .init_driver = init_bus_pci, 313 .uninit_driver = uninit_bus, 314 .device_removed = bus_removed, 315 }, 316 317 .set_clock = set_clock, 318 .execute_command = execute_command, 319 .do_io = do_io, 320 .set_scan_semaphore = set_scan_semaphore, 321 .set_bus_width = set_bus_width, 322 }; 323