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

Merge tag 'hisi-drivers-for-4.18' of git://github.com/hisilicon/linux-hisi into next/drivers

ARM64: hisi: SoC driver updates for 4.18

- Update hisi LPC bus driver to use the platform driver APIs
other than the MFD APIs to support connected device like UART

* tag 'hisi-drivers-for-4.18' of git://github.com/hisilicon/linux-hisi:
HISI LPC: Add ACPI UART support
HISI LPC: Re-Add ACPI child enumeration support
HISI LPC: Stop using MFD APIs

Signed-off-by: Olof Johansson <olof@lixom.net>

+97 -63
-1
drivers/bus/Kconfig
··· 33 33 bool "Support for ISA I/O space on HiSilicon Hip06/7" 34 34 depends on ARM64 && (ARCH_HISI || COMPILE_TEST) 35 35 select INDIRECT_PIO 36 - select MFD_CORE if ACPI 37 36 help 38 37 Driver to enable I/O access to devices attached to the Low Pin 39 38 Count bus on the HiSilicon Hip06/7 SoC.
+97 -62
drivers/bus/hisi_lpc.c
··· 11 11 #include <linux/delay.h> 12 12 #include <linux/io.h> 13 13 #include <linux/logic_pio.h> 14 - #include <linux/mfd/core.h> 15 14 #include <linux/module.h> 16 15 #include <linux/of.h> 17 16 #include <linux/of_address.h> 18 17 #include <linux/of_platform.h> 19 18 #include <linux/pci.h> 19 + #include <linux/serial_8250.h> 20 20 #include <linux/slab.h> 21 21 22 22 #define DRV_NAME "hisi-lpc" ··· 341 341 }; 342 342 343 343 #ifdef CONFIG_ACPI 344 - #define MFD_CHILD_NAME_PREFIX DRV_NAME"-" 345 - #define MFD_CHILD_NAME_LEN (ACPI_ID_LEN + sizeof(MFD_CHILD_NAME_PREFIX) - 1) 346 - 347 - struct hisi_lpc_mfd_cell { 348 - struct mfd_cell_acpi_match acpi_match; 349 - char name[MFD_CHILD_NAME_LEN]; 350 - char pnpid[ACPI_ID_LEN]; 351 - }; 352 - 353 344 static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev, 354 345 struct acpi_device *host, 355 346 struct resource *res) ··· 359 368 } 360 369 361 370 /* 362 - * hisi_lpc_acpi_set_io_res - set the resources for a child's MFD 371 + * hisi_lpc_acpi_set_io_res - set the resources for a child 363 372 * @child: the device node to be updated the I/O resource 364 373 * @hostdev: the device node associated with host controller 365 374 * @res: double pointer to be set to the address of translated resources ··· 443 452 return 0; 444 453 } 445 454 455 + static int hisi_lpc_acpi_remove_subdev(struct device *dev, void *unused) 456 + { 457 + platform_device_unregister(to_platform_device(dev)); 458 + return 0; 459 + } 460 + 461 + struct hisi_lpc_acpi_cell { 462 + const char *hid; 463 + const char *name; 464 + void *pdata; 465 + size_t pdata_size; 466 + }; 467 + 446 468 /* 447 469 * hisi_lpc_acpi_probe - probe children for ACPI FW 448 470 * @hostdev: LPC host device pointer 449 471 * 450 472 * Returns 0 when successful, and a negative value for failure. 451 473 * 452 - * Scan all child devices and create a per-device MFD with 453 - * logical PIO translated IO resources. 474 + * Create a platform device per child, fixing up the resources 475 + * from bus addresses to Logical PIO addresses. 476 + * 454 477 */ 455 478 static int hisi_lpc_acpi_probe(struct device *hostdev) 456 479 { 457 480 struct acpi_device *adev = ACPI_COMPANION(hostdev); 458 - struct hisi_lpc_mfd_cell *hisi_lpc_mfd_cells; 459 - struct mfd_cell *mfd_cells; 460 481 struct acpi_device *child; 461 - int size, ret, count = 0, cell_num = 0; 482 + int ret; 462 483 463 - list_for_each_entry(child, &adev->children, node) 464 - cell_num++; 465 - 466 - /* allocate the mfd cell and companion ACPI info, one per child */ 467 - size = sizeof(*mfd_cells) + sizeof(*hisi_lpc_mfd_cells); 468 - mfd_cells = devm_kcalloc(hostdev, cell_num, size, GFP_KERNEL); 469 - if (!mfd_cells) 470 - return -ENOMEM; 471 - 472 - hisi_lpc_mfd_cells = (struct hisi_lpc_mfd_cell *)&mfd_cells[cell_num]; 473 484 /* Only consider the children of the host */ 474 485 list_for_each_entry(child, &adev->children, node) { 475 - struct mfd_cell *mfd_cell = &mfd_cells[count]; 476 - struct hisi_lpc_mfd_cell *hisi_lpc_mfd_cell = 477 - &hisi_lpc_mfd_cells[count]; 478 - struct mfd_cell_acpi_match *acpi_match = 479 - &hisi_lpc_mfd_cell->acpi_match; 480 - char *name = hisi_lpc_mfd_cell[count].name; 481 - char *pnpid = hisi_lpc_mfd_cell[count].pnpid; 482 - struct mfd_cell_acpi_match match = { 483 - .pnpid = pnpid, 486 + const char *hid = acpi_device_hid(child); 487 + const struct hisi_lpc_acpi_cell *cell; 488 + struct platform_device *pdev; 489 + const struct resource *res; 490 + bool found = false; 491 + int num_res; 492 + 493 + ret = hisi_lpc_acpi_set_io_res(&child->dev, &adev->dev, &res, 494 + &num_res); 495 + if (ret) { 496 + dev_warn(hostdev, "set resource fail (%d)\n", ret); 497 + goto fail; 498 + } 499 + 500 + cell = (struct hisi_lpc_acpi_cell []){ 501 + /* ipmi */ 502 + { 503 + .hid = "IPI0001", 504 + .name = "hisi-lpc-ipmi", 505 + }, 506 + /* 8250-compatible uart */ 507 + { 508 + .hid = "HISI1031", 509 + .name = "serial8250", 510 + .pdata = (struct plat_serial8250_port []) { 511 + { 512 + .iobase = res->start, 513 + .uartclk = 1843200, 514 + .iotype = UPIO_PORT, 515 + .flags = UPF_BOOT_AUTOCONF, 516 + }, 517 + {} 518 + }, 519 + .pdata_size = 2 * 520 + sizeof(struct plat_serial8250_port), 521 + }, 522 + {} 484 523 }; 485 524 486 - /* 487 - * For any instances of this host controller (Hip06 and Hip07 488 - * are the only chipsets), we would not have multiple slaves 489 - * with the same HID. And in any system we would have just one 490 - * controller active. So don't worrry about MFD name clashes. 491 - */ 492 - snprintf(name, MFD_CHILD_NAME_LEN, MFD_CHILD_NAME_PREFIX"%s", 493 - acpi_device_hid(child)); 494 - snprintf(pnpid, ACPI_ID_LEN, "%s", acpi_device_hid(child)); 495 - 496 - memcpy(acpi_match, &match, sizeof(*acpi_match)); 497 - mfd_cell->name = name; 498 - mfd_cell->acpi_match = acpi_match; 499 - 500 - ret = hisi_lpc_acpi_set_io_res(&child->dev, &adev->dev, 501 - &mfd_cell->resources, 502 - &mfd_cell->num_resources); 503 - if (ret) { 504 - dev_warn(&child->dev, "set resource fail (%d)\n", ret); 505 - return ret; 525 + for (; cell && cell->name; cell++) { 526 + if (!strcmp(cell->hid, hid)) { 527 + found = true; 528 + break; 529 + } 506 530 } 507 - count++; 508 - } 509 531 510 - ret = mfd_add_devices(hostdev, PLATFORM_DEVID_NONE, 511 - mfd_cells, cell_num, NULL, 0, NULL); 512 - if (ret) { 513 - dev_err(hostdev, "failed to add mfd cells (%d)\n", ret); 514 - return ret; 532 + if (!found) { 533 + dev_warn(hostdev, 534 + "could not find cell for child device (%s)\n", 535 + hid); 536 + ret = -ENODEV; 537 + goto fail; 538 + } 539 + 540 + pdev = platform_device_alloc(cell->name, PLATFORM_DEVID_AUTO); 541 + if (!pdev) { 542 + ret = -ENOMEM; 543 + goto fail; 544 + } 545 + 546 + pdev->dev.parent = hostdev; 547 + ACPI_COMPANION_SET(&pdev->dev, child); 548 + 549 + ret = platform_device_add_resources(pdev, res, num_res); 550 + if (ret) 551 + goto fail; 552 + 553 + ret = platform_device_add_data(pdev, cell->pdata, 554 + cell->pdata_size); 555 + if (ret) 556 + goto fail; 557 + 558 + ret = platform_device_add(pdev); 559 + if (ret) 560 + goto fail; 561 + 562 + acpi_device_set_enumerated(child); 515 563 } 516 564 517 565 return 0; 566 + 567 + fail: 568 + device_for_each_child(hostdev, NULL, 569 + hisi_lpc_acpi_remove_subdev); 570 + return ret; 518 571 } 519 572 520 573 static const struct acpi_device_id hisi_lpc_acpi_match[] = {