aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Garry <john.garry@huawei.com>2018-05-08 06:27:31 -0400
committerWei Xu <xuwei5@hisilicon.com>2018-05-10 12:35:46 -0400
commit99c0228d6ff1fabdd56fa78c2283b5b155fa8664 (patch)
tree89295aee7e5b9067a63a8d6bf3e519edd5d521a3
parent332f632ec3d1dccdb89fadd5ce0850f02e14824d (diff)
HISI LPC: Re-Add ACPI child enumeration support
Since we no longer use the MFD APIs to enumerate the child devices on the bus, use the platform driver APIs directly. In this patch we iterate of the children devices for the host, and create a platform device directly per child. For the iterating, we match the child ACPI HID against a known list of supported child devices and their respective ACPIs HID, to find the device name and any other supplementary data. Signed-off-by: John Garry <john.garry@huawei.com> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Wei Xu <xuwei5@hisilicon.com>
-rw-r--r--drivers/bus/hisi_lpc.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index 252a6a401a42..eb5b3fc186e0 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -442,12 +442,28 @@ static int hisi_lpc_acpi_set_io_res(struct device *child,
442 return 0; 442 return 0;
443} 443}
444 444
445static int hisi_lpc_acpi_remove_subdev(struct device *dev, void *unused)
446{
447 platform_device_unregister(to_platform_device(dev));
448 return 0;
449}
450
451struct hisi_lpc_acpi_cell {
452 const char *hid;
453 const char *name;
454 void *pdata;
455 size_t pdata_size;
456};
457
445/* 458/*
446 * hisi_lpc_acpi_probe - probe children for ACPI FW 459 * hisi_lpc_acpi_probe - probe children for ACPI FW
447 * @hostdev: LPC host device pointer 460 * @hostdev: LPC host device pointer
448 * 461 *
449 * Returns 0 when successful, and a negative value for failure. 462 * Returns 0 when successful, and a negative value for failure.
450 * 463 *
464 * Create a platform device per child, fixing up the resources
465 * from bus addresses to Logical PIO addresses.
466 *
451 */ 467 */
452static int hisi_lpc_acpi_probe(struct device *hostdev) 468static int hisi_lpc_acpi_probe(struct device *hostdev)
453{ 469{
@@ -457,17 +473,75 @@ static int hisi_lpc_acpi_probe(struct device *hostdev)
457 473
458 /* Only consider the children of the host */ 474 /* Only consider the children of the host */
459 list_for_each_entry(child, &adev->children, node) { 475 list_for_each_entry(child, &adev->children, node) {
476 const char *hid = acpi_device_hid(child);
477 const struct hisi_lpc_acpi_cell *cell;
478 struct platform_device *pdev;
460 const struct resource *res; 479 const struct resource *res;
480 bool found = false;
461 int num_res; 481 int num_res;
462 482
463 ret = hisi_lpc_acpi_set_io_res(&child->dev, &adev->dev, &res, 483 ret = hisi_lpc_acpi_set_io_res(&child->dev, &adev->dev, &res,
464 &num_res); 484 &num_res);
465 if (ret) { 485 if (ret) {
466 dev_warn(hostdev, "set resource fail (%d)\n", ret); 486 dev_warn(hostdev, "set resource fail (%d)\n", ret);
487 goto fail;
488 }
489
490 cell = (struct hisi_lpc_acpi_cell []){
491 /* ipmi */
492 {
493 .hid = "IPI0001",
494 .name = "hisi-lpc-ipmi",
495 },
496 {}
497 };
498
499 for (; cell && cell->name; cell++) {
500 if (!strcmp(cell->hid, hid)) {
501 found = true;
502 break;
503 }
467 } 504 }
505
506 if (!found) {
507 dev_warn(hostdev,
508 "could not find cell for child device (%s)\n",
509 hid);
510 ret = -ENODEV;
511 goto fail;
512 }
513
514 pdev = platform_device_alloc(cell->name, PLATFORM_DEVID_AUTO);
515 if (!pdev) {
516 ret = -ENOMEM;
517 goto fail;
518 }
519
520 pdev->dev.parent = hostdev;
521 ACPI_COMPANION_SET(&pdev->dev, child);
522
523 ret = platform_device_add_resources(pdev, res, num_res);
524 if (ret)
525 goto fail;
526
527 ret = platform_device_add_data(pdev, cell->pdata,
528 cell->pdata_size);
529 if (ret)
530 goto fail;
531
532 ret = platform_device_add(pdev);
533 if (ret)
534 goto fail;
535
536 acpi_device_set_enumerated(child);
468 } 537 }
469 538
470 return 0; 539 return 0;
540
541fail:
542 device_for_each_child(hostdev, NULL,
543 hisi_lpc_acpi_remove_subdev);
544 return ret;
471} 545}
472 546
473static const struct acpi_device_id hisi_lpc_acpi_match[] = { 547static const struct acpi_device_id hisi_lpc_acpi_match[] = {