Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.15-rc4 593 lines 13 kB view raw
1/* 2 * ipmi_si_platform.c 3 * 4 * Handling for platform devices in IPMI (ACPI, OF, and things 5 * coming from the platform. 6 */ 7#include <linux/types.h> 8#include <linux/module.h> 9#include <linux/of_device.h> 10#include <linux/of_platform.h> 11#include <linux/of_address.h> 12#include <linux/of_irq.h> 13#include <linux/acpi.h> 14#include "ipmi_si.h" 15#include "ipmi_dmi.h" 16 17#define PFX "ipmi_platform: " 18 19static bool si_tryplatform = true; 20#ifdef CONFIG_ACPI 21static bool si_tryacpi = true; 22#endif 23#ifdef CONFIG_OF 24static bool si_tryopenfirmware = true; 25#endif 26#ifdef CONFIG_DMI 27static bool si_trydmi = true; 28#else 29static bool si_trydmi = false; 30#endif 31 32module_param_named(tryplatform, si_tryplatform, bool, 0); 33MODULE_PARM_DESC(tryplatform, "Setting this to zero will disable the" 34 " default scan of the interfaces identified via platform" 35 " interfaces besides ACPI, OpenFirmware, and DMI"); 36#ifdef CONFIG_ACPI 37module_param_named(tryacpi, si_tryacpi, bool, 0); 38MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the" 39 " default scan of the interfaces identified via ACPI"); 40#endif 41#ifdef CONFIG_OF 42module_param_named(tryopenfirmware, si_tryopenfirmware, bool, 0); 43MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the" 44 " default scan of the interfaces identified via OpenFirmware"); 45#endif 46#ifdef CONFIG_DMI 47module_param_named(trydmi, si_trydmi, bool, 0); 48MODULE_PARM_DESC(trydmi, "Setting this to zero will disable the" 49 " default scan of the interfaces identified via DMI"); 50#endif 51 52#ifdef CONFIG_ACPI 53 54/* 55 * Once we get an ACPI failure, we don't try any more, because we go 56 * through the tables sequentially. Once we don't find a table, there 57 * are no more. 58 */ 59static int acpi_failure; 60 61/* For GPE-type interrupts. */ 62static u32 ipmi_acpi_gpe(acpi_handle gpe_device, 63 u32 gpe_number, void *context) 64{ 65 struct si_sm_io *io = context; 66 67 ipmi_si_irq_handler(io->irq, io->irq_handler_data); 68 return ACPI_INTERRUPT_HANDLED; 69} 70 71static void acpi_gpe_irq_cleanup(struct si_sm_io *io) 72{ 73 if (!io->irq) 74 return; 75 76 ipmi_irq_start_cleanup(io); 77 acpi_remove_gpe_handler(NULL, io->irq, &ipmi_acpi_gpe); 78} 79 80static int acpi_gpe_irq_setup(struct si_sm_io *io) 81{ 82 acpi_status status; 83 84 if (!io->irq) 85 return 0; 86 87 status = acpi_install_gpe_handler(NULL, 88 io->irq, 89 ACPI_GPE_LEVEL_TRIGGERED, 90 &ipmi_acpi_gpe, 91 io); 92 if (status != AE_OK) { 93 dev_warn(io->dev, 94 "Unable to claim ACPI GPE %d, running polled\n", 95 io->irq); 96 io->irq = 0; 97 return -EINVAL; 98 } else { 99 io->irq_cleanup = acpi_gpe_irq_cleanup; 100 ipmi_irq_finish_setup(io); 101 dev_info(io->dev, "Using ACPI GPE %d\n", io->irq); 102 return 0; 103 } 104} 105 106/* 107 * Defined at 108 * http://h21007.www2.hp.com/portal/download/files/unprot/hpspmi.pdf 109 */ 110struct SPMITable { 111 s8 Signature[4]; 112 u32 Length; 113 u8 Revision; 114 u8 Checksum; 115 s8 OEMID[6]; 116 s8 OEMTableID[8]; 117 s8 OEMRevision[4]; 118 s8 CreatorID[4]; 119 s8 CreatorRevision[4]; 120 u8 InterfaceType; 121 u8 IPMIlegacy; 122 s16 SpecificationRevision; 123 124 /* 125 * Bit 0 - SCI interrupt supported 126 * Bit 1 - I/O APIC/SAPIC 127 */ 128 u8 InterruptType; 129 130 /* 131 * If bit 0 of InterruptType is set, then this is the SCI 132 * interrupt in the GPEx_STS register. 133 */ 134 u8 GPE; 135 136 s16 Reserved; 137 138 /* 139 * If bit 1 of InterruptType is set, then this is the I/O 140 * APIC/SAPIC interrupt. 141 */ 142 u32 GlobalSystemInterrupt; 143 144 /* The actual register address. */ 145 struct acpi_generic_address addr; 146 147 u8 UID[4]; 148 149 s8 spmi_id[1]; /* A '\0' terminated array starts here. */ 150}; 151 152static int try_init_spmi(struct SPMITable *spmi) 153{ 154 struct si_sm_io io; 155 156 if (spmi->IPMIlegacy != 1) { 157 pr_info(PFX "Bad SPMI legacy %d\n", spmi->IPMIlegacy); 158 return -ENODEV; 159 } 160 161 memset(&io, 0, sizeof(io)); 162 io.addr_source = SI_SPMI; 163 pr_info(PFX "probing via SPMI\n"); 164 165 /* Figure out the interface type. */ 166 switch (spmi->InterfaceType) { 167 case 1: /* KCS */ 168 io.si_type = SI_KCS; 169 break; 170 case 2: /* SMIC */ 171 io.si_type = SI_SMIC; 172 break; 173 case 3: /* BT */ 174 io.si_type = SI_BT; 175 break; 176 case 4: /* SSIF, just ignore */ 177 return -EIO; 178 default: 179 pr_info(PFX "Unknown ACPI/SPMI SI type %d\n", 180 spmi->InterfaceType); 181 return -EIO; 182 } 183 184 if (spmi->InterruptType & 1) { 185 /* We've got a GPE interrupt. */ 186 io.irq = spmi->GPE; 187 io.irq_setup = acpi_gpe_irq_setup; 188 } else if (spmi->InterruptType & 2) { 189 /* We've got an APIC/SAPIC interrupt. */ 190 io.irq = spmi->GlobalSystemInterrupt; 191 io.irq_setup = ipmi_std_irq_setup; 192 } else { 193 /* Use the default interrupt setting. */ 194 io.irq = 0; 195 io.irq_setup = NULL; 196 } 197 198 if (spmi->addr.bit_width) { 199 /* A (hopefully) properly formed register bit width. */ 200 io.regspacing = spmi->addr.bit_width / 8; 201 } else { 202 io.regspacing = DEFAULT_REGSPACING; 203 } 204 io.regsize = io.regspacing; 205 io.regshift = spmi->addr.bit_offset; 206 207 if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { 208 io.addr_type = IPMI_MEM_ADDR_SPACE; 209 } else if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_IO) { 210 io.addr_type = IPMI_IO_ADDR_SPACE; 211 } else { 212 pr_warn(PFX "Unknown ACPI I/O Address type\n"); 213 return -EIO; 214 } 215 io.addr_data = spmi->addr.address; 216 217 pr_info("ipmi_si: SPMI: %s %#lx regsize %d spacing %d irq %d\n", 218 (io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem", 219 io.addr_data, io.regsize, io.regspacing, io.irq); 220 221 return ipmi_si_add_smi(&io); 222} 223 224static void spmi_find_bmc(void) 225{ 226 acpi_status status; 227 struct SPMITable *spmi; 228 int i; 229 230 if (acpi_disabled) 231 return; 232 233 if (acpi_failure) 234 return; 235 236 for (i = 0; ; i++) { 237 status = acpi_get_table(ACPI_SIG_SPMI, i+1, 238 (struct acpi_table_header **)&spmi); 239 if (status != AE_OK) 240 return; 241 242 try_init_spmi(spmi); 243 } 244} 245#endif 246 247static struct resource * 248ipmi_get_info_from_resources(struct platform_device *pdev, 249 struct si_sm_io *io) 250{ 251 struct resource *res, *res_second; 252 253 res = platform_get_resource(pdev, IORESOURCE_IO, 0); 254 if (res) { 255 io->addr_type = IPMI_IO_ADDR_SPACE; 256 } else { 257 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 258 if (res) 259 io->addr_type = IPMI_MEM_ADDR_SPACE; 260 } 261 if (!res) { 262 dev_err(&pdev->dev, "no I/O or memory address\n"); 263 return NULL; 264 } 265 io->addr_data = res->start; 266 267 io->regspacing = DEFAULT_REGSPACING; 268 res_second = platform_get_resource(pdev, 269 (io->addr_type == IPMI_IO_ADDR_SPACE) ? 270 IORESOURCE_IO : IORESOURCE_MEM, 271 1); 272 if (res_second) { 273 if (res_second->start > io->addr_data) 274 io->regspacing = res_second->start - io->addr_data; 275 } 276 io->regsize = DEFAULT_REGSIZE; 277 io->regshift = 0; 278 279 return res; 280} 281 282static int platform_ipmi_probe(struct platform_device *pdev) 283{ 284 struct si_sm_io io; 285 u8 type, slave_addr, addr_source; 286 int rv; 287 288 rv = device_property_read_u8(&pdev->dev, "addr-source", &addr_source); 289 if (rv) 290 addr_source = SI_PLATFORM; 291 if (addr_source >= SI_LAST) 292 return -EINVAL; 293 294 if (addr_source == SI_SMBIOS) { 295 if (!si_trydmi) 296 return -ENODEV; 297 } else { 298 if (!si_tryplatform) 299 return -ENODEV; 300 } 301 302 rv = device_property_read_u8(&pdev->dev, "ipmi-type", &type); 303 if (rv) 304 return -ENODEV; 305 306 memset(&io, 0, sizeof(io)); 307 io.addr_source = addr_source; 308 dev_info(&pdev->dev, PFX "probing via %s\n", 309 ipmi_addr_src_to_str(addr_source)); 310 311 switch (type) { 312 case SI_KCS: 313 case SI_SMIC: 314 case SI_BT: 315 io.si_type = type; 316 break; 317 default: 318 dev_err(&pdev->dev, "ipmi-type property is invalid\n"); 319 return -EINVAL; 320 } 321 322 if (!ipmi_get_info_from_resources(pdev, &io)) 323 return -EINVAL; 324 325 rv = device_property_read_u8(&pdev->dev, "slave-addr", &slave_addr); 326 if (rv) { 327 dev_warn(&pdev->dev, "device has no slave-addr property\n"); 328 io.slave_addr = 0x20; 329 } else { 330 io.slave_addr = slave_addr; 331 } 332 333 io.irq = platform_get_irq(pdev, 0); 334 if (io.irq > 0) 335 io.irq_setup = ipmi_std_irq_setup; 336 else 337 io.irq = 0; 338 339 io.dev = &pdev->dev; 340 341 pr_info("ipmi_si: SMBIOS: %s %#lx regsize %d spacing %d irq %d\n", 342 (io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem", 343 io.addr_data, io.regsize, io.regspacing, io.irq); 344 345 ipmi_si_add_smi(&io); 346 347 return 0; 348} 349 350#ifdef CONFIG_OF 351static const struct of_device_id of_ipmi_match[] = { 352 { .type = "ipmi", .compatible = "ipmi-kcs", 353 .data = (void *)(unsigned long) SI_KCS }, 354 { .type = "ipmi", .compatible = "ipmi-smic", 355 .data = (void *)(unsigned long) SI_SMIC }, 356 { .type = "ipmi", .compatible = "ipmi-bt", 357 .data = (void *)(unsigned long) SI_BT }, 358 {}, 359}; 360MODULE_DEVICE_TABLE(of, of_ipmi_match); 361 362static int of_ipmi_probe(struct platform_device *pdev) 363{ 364 const struct of_device_id *match; 365 struct si_sm_io io; 366 struct resource resource; 367 const __be32 *regsize, *regspacing, *regshift; 368 struct device_node *np = pdev->dev.of_node; 369 int ret; 370 int proplen; 371 372 if (!si_tryopenfirmware) 373 return -ENODEV; 374 375 dev_info(&pdev->dev, "probing via device tree\n"); 376 377 match = of_match_device(of_ipmi_match, &pdev->dev); 378 if (!match) 379 return -ENODEV; 380 381 if (!of_device_is_available(np)) 382 return -EINVAL; 383 384 ret = of_address_to_resource(np, 0, &resource); 385 if (ret) { 386 dev_warn(&pdev->dev, PFX "invalid address from OF\n"); 387 return ret; 388 } 389 390 regsize = of_get_property(np, "reg-size", &proplen); 391 if (regsize && proplen != 4) { 392 dev_warn(&pdev->dev, PFX "invalid regsize from OF\n"); 393 return -EINVAL; 394 } 395 396 regspacing = of_get_property(np, "reg-spacing", &proplen); 397 if (regspacing && proplen != 4) { 398 dev_warn(&pdev->dev, PFX "invalid regspacing from OF\n"); 399 return -EINVAL; 400 } 401 402 regshift = of_get_property(np, "reg-shift", &proplen); 403 if (regshift && proplen != 4) { 404 dev_warn(&pdev->dev, PFX "invalid regshift from OF\n"); 405 return -EINVAL; 406 } 407 408 memset(&io, 0, sizeof(io)); 409 io.si_type = (enum si_type) match->data; 410 io.addr_source = SI_DEVICETREE; 411 io.irq_setup = ipmi_std_irq_setup; 412 413 if (resource.flags & IORESOURCE_IO) 414 io.addr_type = IPMI_IO_ADDR_SPACE; 415 else 416 io.addr_type = IPMI_MEM_ADDR_SPACE; 417 418 io.addr_data = resource.start; 419 420 io.regsize = regsize ? be32_to_cpup(regsize) : DEFAULT_REGSIZE; 421 io.regspacing = regspacing ? be32_to_cpup(regspacing) : DEFAULT_REGSPACING; 422 io.regshift = regshift ? be32_to_cpup(regshift) : 0; 423 424 io.irq = irq_of_parse_and_map(pdev->dev.of_node, 0); 425 io.dev = &pdev->dev; 426 427 dev_dbg(&pdev->dev, "addr 0x%lx regsize %d spacing %d irq %d\n", 428 io.addr_data, io.regsize, io.regspacing, io.irq); 429 430 return ipmi_si_add_smi(&io); 431} 432#else 433#define of_ipmi_match NULL 434static int of_ipmi_probe(struct platform_device *dev) 435{ 436 return -ENODEV; 437} 438#endif 439 440#ifdef CONFIG_ACPI 441static int find_slave_address(struct si_sm_io *io, int slave_addr) 442{ 443#ifdef CONFIG_IPMI_DMI_DECODE 444 if (!slave_addr) { 445 u32 flags = IORESOURCE_IO; 446 447 if (io->addr_type == IPMI_MEM_ADDR_SPACE) 448 flags = IORESOURCE_MEM; 449 450 slave_addr = ipmi_dmi_get_slave_addr(io->si_type, flags, 451 io->addr_data); 452 } 453#endif 454 455 return slave_addr; 456} 457 458static int acpi_ipmi_probe(struct platform_device *pdev) 459{ 460 struct si_sm_io io; 461 acpi_handle handle; 462 acpi_status status; 463 unsigned long long tmp; 464 struct resource *res; 465 int rv = -EINVAL; 466 467 if (!si_tryacpi) 468 return -ENODEV; 469 470 handle = ACPI_HANDLE(&pdev->dev); 471 if (!handle) 472 return -ENODEV; 473 474 memset(&io, 0, sizeof(io)); 475 io.addr_source = SI_ACPI; 476 dev_info(&pdev->dev, PFX "probing via ACPI\n"); 477 478 io.addr_info.acpi_info.acpi_handle = handle; 479 480 /* _IFT tells us the interface type: KCS, BT, etc */ 481 status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp); 482 if (ACPI_FAILURE(status)) { 483 dev_err(&pdev->dev, 484 "Could not find ACPI IPMI interface type\n"); 485 goto err_free; 486 } 487 488 switch (tmp) { 489 case 1: 490 io.si_type = SI_KCS; 491 break; 492 case 2: 493 io.si_type = SI_SMIC; 494 break; 495 case 3: 496 io.si_type = SI_BT; 497 break; 498 case 4: /* SSIF, just ignore */ 499 rv = -ENODEV; 500 goto err_free; 501 default: 502 dev_info(&pdev->dev, "unknown IPMI type %lld\n", tmp); 503 goto err_free; 504 } 505 506 res = ipmi_get_info_from_resources(pdev, &io); 507 if (!res) { 508 rv = -EINVAL; 509 goto err_free; 510 } 511 512 /* If _GPE exists, use it; otherwise use standard interrupts */ 513 status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp); 514 if (ACPI_SUCCESS(status)) { 515 io.irq = tmp; 516 io.irq_setup = acpi_gpe_irq_setup; 517 } else { 518 int irq = platform_get_irq(pdev, 0); 519 520 if (irq > 0) { 521 io.irq = irq; 522 io.irq_setup = ipmi_std_irq_setup; 523 } 524 } 525 526 io.slave_addr = find_slave_address(&io, io.slave_addr); 527 528 io.dev = &pdev->dev; 529 530 dev_info(io.dev, "%pR regsize %d spacing %d irq %d\n", 531 res, io.regsize, io.regspacing, io.irq); 532 533 return ipmi_si_add_smi(&io); 534 535err_free: 536 return rv; 537} 538 539static const struct acpi_device_id acpi_ipmi_match[] = { 540 { "IPI0001", 0 }, 541 { }, 542}; 543MODULE_DEVICE_TABLE(acpi, acpi_ipmi_match); 544#else 545static int acpi_ipmi_probe(struct platform_device *dev) 546{ 547 return -ENODEV; 548} 549#endif 550 551static int ipmi_probe(struct platform_device *pdev) 552{ 553 if (pdev->dev.of_node && of_ipmi_probe(pdev) == 0) 554 return 0; 555 556 if (acpi_ipmi_probe(pdev) == 0) 557 return 0; 558 559 return platform_ipmi_probe(pdev); 560} 561 562static int ipmi_remove(struct platform_device *pdev) 563{ 564 return ipmi_si_remove_by_dev(&pdev->dev); 565} 566 567struct platform_driver ipmi_platform_driver = { 568 .driver = { 569 .name = DEVICE_NAME, 570 .of_match_table = of_ipmi_match, 571 .acpi_match_table = ACPI_PTR(acpi_ipmi_match), 572 }, 573 .probe = ipmi_probe, 574 .remove = ipmi_remove, 575}; 576 577void ipmi_si_platform_init(void) 578{ 579 int rv = platform_driver_register(&ipmi_platform_driver); 580 if (rv) 581 pr_err(PFX "Unable to register driver: %d\n", rv); 582 583#ifdef CONFIG_ACPI 584 if (si_tryacpi) 585 spmi_find_bmc(); 586#endif 587 588} 589 590void ipmi_si_platform_shutdown(void) 591{ 592 platform_driver_unregister(&ipmi_platform_driver); 593}