1 /* 2 * Copyright 2020, Jérôme Duval, jerome.duval@gmail.com. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <new> 8 #include <stdio.h> 9 #include <string.h> 10 11 #include <ACPI.h> 12 #include <ByteOrder.h> 13 #include <condition_variable.h> 14 #include <bus/PCI.h> 15 16 17 #include "pch_i2c.h" 18 19 20 typedef struct { 21 pch_i2c_sim_info info; 22 pci_device_module_info* pci; 23 pci_device* device; 24 pch_i2c_irq_type irq_type; 25 26 pci_info pciinfo; 27 } pch_i2c_pci_sim_info; 28 29 30 // #pragma mark - 31 32 33 static status_t 34 pci_scan_bus(i2c_bus_cookie cookie) 35 { 36 CALLED(); 37 pch_i2c_pci_sim_info* bus = (pch_i2c_pci_sim_info*)cookie; 38 device_node *acpiNode = NULL; 39 40 pci_info *pciInfo = &bus->pciinfo; 41 42 // search ACPI I2C nodes for this device 43 { 44 device_node* deviceRoot = gDeviceManager->get_root_node(); 45 uint32 addr = (pciInfo->device << 16) | pciInfo->function; 46 device_attr acpiAttrs[] = { 47 { B_DEVICE_BUS, B_STRING_TYPE, { .string = "acpi" }}, 48 { ACPI_DEVICE_ADDR_ITEM, B_UINT32_TYPE, {.ui32 = addr}}, 49 { NULL } 50 }; 51 if (addr != 0 && gDeviceManager->find_child_node(deviceRoot, acpiAttrs, 52 &acpiNode) != B_OK) { 53 ERROR("init_bus() acpi device not found\n"); 54 return B_DEV_CONFIGURATION_ERROR; 55 } 56 } 57 58 TRACE("init_bus() find_child_node() found %x %x %p\n", 59 pciInfo->device, pciInfo->function, acpiNode); 60 // TODO eventually check timings on acpi 61 acpi_device_module_info *acpi; 62 acpi_device acpiDevice; 63 if (gDeviceManager->get_driver(acpiNode, (driver_module_info **)&acpi, 64 (void **)&acpiDevice) == B_OK) { 65 // find out I2C device nodes 66 acpi->walk_namespace(acpiDevice, ACPI_TYPE_DEVICE, 1, 67 pch_i2c_scan_bus_callback, NULL, bus, NULL); 68 } 69 70 return B_OK; 71 } 72 73 74 static status_t 75 register_child_devices(void* cookie) 76 { 77 CALLED(); 78 79 pch_i2c_pci_sim_info* bus = (pch_i2c_pci_sim_info*)cookie; 80 device_node* node = bus->info.driver_node; 81 82 char prettyName[25]; 83 sprintf(prettyName, "PCH I2C Controller %" B_PRIu16, 0); 84 85 device_attr attrs[] = { 86 // properties of this controller for i2c bus manager 87 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, 88 { .string = prettyName }}, 89 { B_DEVICE_FIXED_CHILD, B_STRING_TYPE, 90 { .string = I2C_FOR_CONTROLLER_MODULE_NAME }}, 91 92 // private data to identify the device 93 { NULL } 94 }; 95 96 return gDeviceManager->register_node(node, PCH_I2C_SIM_MODULE_NAME, 97 attrs, NULL, NULL); 98 } 99 100 101 static status_t 102 init_device(device_node* node, void** device_cookie) 103 { 104 CALLED(); 105 status_t status = B_OK; 106 107 pch_i2c_pci_sim_info* bus = (pch_i2c_pci_sim_info*)calloc(1, 108 sizeof(pch_i2c_pci_sim_info)); 109 if (bus == NULL) 110 return B_NO_MEMORY; 111 112 pci_device_module_info* pci; 113 pci_device* device; 114 { 115 device_node* pciParent = gDeviceManager->get_parent_node(node); 116 gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci, 117 (void**)&device); 118 gDeviceManager->put_node(pciParent); 119 } 120 121 bus->pci = pci; 122 bus->device = device; 123 bus->info.driver_node = node; 124 bus->info.scan_bus = pci_scan_bus; 125 126 pci_info *pciInfo = &bus->pciinfo; 127 pci->get_pci_info(device, pciInfo); 128 129 bus->info.base_addr = pciInfo->u.h0.base_registers[0]; 130 bus->info.map_size = pciInfo->u.h0.base_register_sizes[0]; 131 if ((pciInfo->u.h0.base_register_flags[0] & PCI_address_type) 132 == PCI_address_type_64) { 133 bus->info.base_addr |= (uint64)pciInfo->u.h0.base_registers[1] << 32; 134 bus->info.map_size |= (uint64)pciInfo->u.h0.base_register_sizes[1] << 32; 135 } 136 137 if (bus->info.base_addr == 0) { 138 ERROR("PCI BAR not assigned\n"); 139 free(bus); 140 return B_ERROR; 141 } 142 143 // enable power 144 pci->set_powerstate(device, PCI_pm_state_d0); 145 146 // enable bus master and memory 147 uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2); 148 pcicmd |= PCI_command_master | PCI_command_memory; 149 pci->write_pci_config(device, PCI_command, 2, pcicmd); 150 151 // try MSI-X 152 if (pci->get_msix_count(device) >= 1) { 153 uint8 vector; 154 if (pci->configure_msix(device, 1, &vector) == B_OK 155 && pci->enable_msix(device) == B_OK) { 156 TRACE_ALWAYS("using MSI-X vector %u\n", vector); 157 bus->info.irq = vector; 158 bus->irq_type = PCH_I2C_IRQ_MSI_X_SHARED; 159 } else { 160 ERROR("couldn't use MSI-X SHARED\n"); 161 } 162 } else if (pci->get_msi_count(device) >= 1) { 163 // try MSI 164 uint8 vector; 165 if (pci->configure_msi(device, 1, &vector) == B_OK 166 && pci->enable_msi(device) == B_OK) { 167 TRACE_ALWAYS("using MSI vector %u\n", vector); 168 bus->info.irq = vector; 169 bus->irq_type = PCH_I2C_IRQ_MSI; 170 } else { 171 ERROR("couldn't use MSI\n"); 172 } 173 } 174 if (bus->irq_type == PCH_I2C_IRQ_LEGACY) { 175 bus->info.irq = pciInfo->u.h0.interrupt_line; 176 TRACE_ALWAYS("using legacy interrupt %u\n", bus->info.irq); 177 } 178 if (bus->info.irq == 0 || bus->info.irq == 0xff) { 179 ERROR("PCI IRQ not assigned\n"); 180 status = B_ERROR; 181 goto err; 182 } 183 184 *device_cookie = bus; 185 return B_OK; 186 187 err: 188 free(bus); 189 return status; 190 } 191 192 193 static void 194 uninit_device(void* device_cookie) 195 { 196 pch_i2c_pci_sim_info* bus = (pch_i2c_pci_sim_info*)device_cookie; 197 if (bus->irq_type != PCH_I2C_IRQ_LEGACY) { 198 bus->pci->disable_msi(bus->device); 199 bus->pci->unconfigure_msi(bus->device); 200 } 201 free(bus); 202 } 203 204 205 static status_t 206 register_device(device_node* parent) 207 { 208 device_attr attrs[] = { 209 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "PCH I2C PCI"}}, 210 {} 211 }; 212 213 return gDeviceManager->register_node(parent, 214 PCH_I2C_PCI_DEVICE_MODULE_NAME, attrs, NULL, NULL); 215 } 216 217 218 static float 219 supports_device(device_node* parent) 220 { 221 CALLED(); 222 const char* bus; 223 uint16 vendorID, deviceID; 224 225 // make sure parent is a PCH I2C PCI device node 226 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false) 227 < B_OK || gDeviceManager->get_attr_uint16(parent, B_DEVICE_VENDOR_ID, 228 &vendorID, false) < B_OK 229 || gDeviceManager->get_attr_uint16(parent, B_DEVICE_ID, &deviceID, 230 false) < B_OK) { 231 return -1; 232 } 233 234 if (strcmp(bus, "pci") != 0) 235 return 0.0f; 236 237 if (vendorID == 0x8086) { 238 switch (deviceID) { 239 case 0x02c5: 240 case 0x02c6: 241 case 0x02e8: 242 case 0x02e9: 243 case 0x02ea: 244 case 0x02eb: 245 case 0x06e8: 246 case 0x06e9: 247 case 0x06ea: 248 case 0x06eb: 249 case 0x0aac: 250 case 0x0aae: 251 case 0x0ab0: 252 case 0x0ab2: 253 case 0x0ab4: 254 case 0x0ab6: 255 case 0x0ab8: 256 case 0x0aba: 257 case 0x1aac: 258 case 0x1aae: 259 260 case 0x1ab0: 261 case 0x1ab2: 262 case 0x1ab4: 263 case 0x1ab6: 264 case 0x1ab8: 265 case 0x1aba: 266 267 case 0x31ac: 268 case 0x31ae: 269 case 0x31b0: 270 case 0x31b2: 271 case 0x31b4: 272 case 0x31b6: 273 case 0x31b8: 274 case 0x31ba: 275 276 case 0x34c5: 277 case 0x34c6: 278 case 0x34e8: 279 case 0x34e9: 280 case 0x34ea: 281 case 0x34eb: 282 283 case 0x43ad: 284 case 0x43ae: 285 case 0x43d8: 286 287 case 0x43e8: 288 case 0x43e9: 289 case 0x43ea: 290 case 0x43eb: 291 292 case 0x4b44: 293 case 0x4b45: 294 case 0x4b4b: 295 case 0x4b4c: 296 case 0x4b78: 297 case 0x4b79: 298 case 0x4b7a: 299 case 0x4b7b: 300 301 case 0x4dc5: 302 case 0x4dc6: 303 case 0x4de8: 304 case 0x4de9: 305 case 0x4dea: 306 case 0x4deb: 307 308 case 0x51c5: 309 case 0x51c6: 310 case 0x51d8: 311 case 0x51d9: 312 case 0x51e8: 313 case 0x51e9: 314 case 0x51ea: 315 case 0x51eb: 316 317 case 0x54c5: 318 case 0x54c6: 319 case 0x54e8: 320 case 0x54e9: 321 case 0x54ea: 322 case 0x54eb: 323 324 case 0x5aac: 325 case 0x5aae: 326 case 0x5ab0: 327 case 0x5ab2: 328 case 0x5ab4: 329 case 0x5ab6: 330 case 0x5ab8: 331 case 0x5aba: 332 333 case 0x7a4c: 334 case 0x7a4d: 335 case 0x7a4e: 336 case 0x7a4f: 337 case 0x7a7c: 338 case 0x7a7d: 339 340 case 0x7acc: 341 case 0x7acd: 342 case 0x7ace: 343 case 0x7acf: 344 case 0x7afc: 345 case 0x7afd: 346 347 case 0x7e50: 348 case 0x7e51: 349 case 0x7e78: 350 case 0x7e79: 351 case 0x7e7a: 352 case 0x7e7b: 353 354 case 0x98c5: 355 case 0x98c6: 356 case 0x98e8: 357 case 0x98e9: 358 case 0x98ea: 359 case 0x98eb: 360 361 case 0x9d60: 362 case 0x9d61: 363 case 0x9d62: 364 case 0x9d63: 365 case 0x9d64: 366 case 0x9d65: 367 368 case 0x9dc5: 369 case 0x9dc6: 370 case 0x9de8: 371 case 0x9de9: 372 case 0x9dea: 373 case 0x9deb: 374 375 case 0xa0c5: 376 case 0xa0c6: 377 case 0xa0d8: 378 case 0xa0d9: 379 case 0xa0e8: 380 case 0xa0e9: 381 case 0xa0ea: 382 case 0xa0eb: 383 384 case 0xa160: 385 case 0xa161: 386 case 0xa162: 387 388 case 0xa2e0: 389 case 0xa2e1: 390 case 0xa2e2: 391 case 0xa2e3: 392 393 case 0xa368: 394 case 0xa369: 395 case 0xa36a: 396 case 0xa36b: 397 398 case 0xa3e0: 399 case 0xa3e1: 400 case 0xa3e2: 401 case 0xa3e3: 402 break; 403 default: 404 return 0.0f; 405 } 406 pci_device_module_info* pci; 407 pci_device* device; 408 gDeviceManager->get_driver(parent, (driver_module_info**)&pci, 409 (void**)&device); 410 #ifdef TRACE_PCH_I2C 411 uint8 pciSubDeviceId = pci->read_pci_config(device, PCI_revision, 412 1); 413 414 TRACE("PCH I2C device found! vendor 0x%04x, device 0x%04x, subdevice 0x%02x\n", vendorID, 415 deviceID, pciSubDeviceId); 416 #endif 417 return 0.8f; 418 } 419 420 return 0.0f; 421 } 422 423 424 // #pragma mark - 425 426 427 driver_module_info gPchI2cPciDevice = { 428 { 429 PCH_I2C_PCI_DEVICE_MODULE_NAME, 430 0, 431 NULL 432 }, 433 434 supports_device, 435 register_device, 436 init_device, 437 uninit_device, 438 register_child_devices, 439 NULL, // rescan 440 NULL, // device removed 441 }; 442 443