From: John Garry <john.garry@huawei.com>
To: <lenb@kernel.org>, <rafael@kernel.org>, <andy.shevchenko@gmail.com>
Cc: <linux-acpi@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<linuxarm@huawei.com>, John Garry <john.garry@huawei.com>
Subject: [PATCH PoC 3/3] bus: hisi_lpc: Use acpi_create_platform_device_ops()
Date: Tue, 16 Aug 2022 19:27:24 +0800 [thread overview]
Message-ID: <1660649244-146842-4-git-send-email-john.garry@huawei.com> (raw)
In-Reply-To: <1660649244-146842-1-git-send-email-john.garry@huawei.com>
Function acpi_create_platform_device_ops() was added to factor out the
duplicated code to create platform device between ACPI platform device
code and this driver.
Most of the complication added here comes from LPC UART support. To
support the LPC UART, we create a serial platform device. For this we
need to create a structure of plat_serial8250_port data. The specific
complication comes from the fact that the UART iobase in
plat_serial8250_port needs to be fixed up after the resource translation.
As such, we need to provide a pointer to this plat_serial8250_port data
to do the fix up in the xlat callback.
Signed-off-by: John Garry <john.garry@huawei.com>
---
drivers/bus/hisi_lpc.c | 165 +++++++++++++++++------------------------
1 file changed, 69 insertions(+), 96 deletions(-)
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index 2e564803e786..ada1cea1affc 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -390,70 +390,49 @@ static void hisi_lpc_acpi_fixup_child_resource(struct device *hostdev,
* host-relative address resource. This function will return the translated
* logical PIO addresses for each child devices resources.
*/
-static int hisi_lpc_acpi_set_io_res(struct acpi_device *adev,
- struct device *hostdev,
- const struct resource **res, int *num_res)
+struct hisi_lpc_acpi_cell_data;
+
+struct hisi_lpc_acpi_cell {
+ const char *hid;
+ const char *name;
+ struct hisi_lpc_acpi_cell_data *data;
+ size_t data_size;
+};
+
+struct hisi_lpc_acpi_cell_data {
+ const struct hisi_lpc_acpi_cell *owner;
+ union {
+ struct plat_serial8250_port serial[2];
+ };
+};
+
+int hisi_lpc_acpi_xlat_res(struct acpi_device *adev, struct resource *res,
+ void *data, size_t data_len)
{
struct acpi_device *host = to_acpi_device(adev->dev.parent);
- struct resource_entry *rentry;
- LIST_HEAD(resource_list);
- struct resource *resources;
- int count;
- int i;
-
- if (!adev->status.present) {
- dev_dbg(&adev->dev, "device is not present\n");
- return -EIO;
- }
+ struct device *dev = &adev->dev;
+ struct device *hostdev = dev->parent;
+ int ret;
- if (acpi_device_enumerated(adev)) {
- dev_dbg(&adev->dev, "has been enumerated\n");
- return -EIO;
- }
+ hisi_lpc_acpi_fixup_child_resource(hostdev, res);
- /*
- * The following code segment to retrieve the resources is common to
- * acpi_create_platform_device(), so consider a common helper function
- * in future.
- */
- count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
- if (count <= 0) {
- dev_dbg(&adev->dev, "failed to get resources\n");
- return count ? count : -EIO;
- }
+ if (!(res->flags & IORESOURCE_IO))
+ return 0;
- resources = devm_kcalloc(hostdev, count, sizeof(*resources),
- GFP_KERNEL);
- if (!resources) {
- dev_warn(hostdev, "could not allocate memory for %d resources\n",
- count);
- acpi_dev_free_resource_list(&resource_list);
- return -ENOMEM;
- }
- count = 0;
- list_for_each_entry(rentry, &resource_list, node) {
- resources[count] = *rentry->res;
- hisi_lpc_acpi_fixup_child_resource(hostdev, &resources[count]);
- count++;
- }
+ ret = hisi_lpc_acpi_xlat_io_res(adev, host, res);
+ if (data_len) {
+ struct hisi_lpc_acpi_cell_data *cell_data = container_of(data,
+ struct hisi_lpc_acpi_cell_data, serial);
+ const struct hisi_lpc_acpi_cell *cell;
- acpi_dev_free_resource_list(&resource_list);
+ cell = cell_data->owner;
- /* translate the I/O resources */
- for (i = 0; i < count; i++) {
- int ret;
+ if (!strcmp(cell->hid, "HISI1031")) {
+ struct plat_serial8250_port *serial = data;
- if (!(resources[i].flags & IORESOURCE_IO))
- continue;
- ret = hisi_lpc_acpi_xlat_io_res(adev, host, &resources[i]);
- if (ret) {
- dev_err(&adev->dev, "translate IO range %pR failed (%d)\n",
- &resources[i], ret);
- return ret;
+ serial->iobase = res->start;
}
}
- *res = resources;
- *num_res = count;
return 0;
}
@@ -470,13 +449,6 @@ static int hisi_lpc_acpi_clear_enumerated(struct acpi_device *adev, void *not_us
return 0;
}
-struct hisi_lpc_acpi_cell {
- const char *hid;
- const char *name;
- void *pdata;
- size_t pdata_size;
-};
-
static void hisi_lpc_acpi_remove(struct device *hostdev)
{
device_for_each_child(hostdev, NULL, hisi_lpc_acpi_remove_subdev);
@@ -490,15 +462,16 @@ static int hisi_lpc_acpi_add_child(struct acpi_device *child, void *data)
struct device *hostdev = data;
const struct hisi_lpc_acpi_cell *cell;
struct platform_device *pdev;
- const struct resource *res;
bool found = false;
- int num_res;
- int ret;
- ret = hisi_lpc_acpi_set_io_res(child, hostdev, &res, &num_res);
- if (ret) {
- dev_warn(hostdev, "set resource fail (%d)\n", ret);
- return ret;
+ if (!child->status.present) {
+ dev_err(&child->dev, "device is not present\n");
+ return -EIO;
+ }
+
+ if (acpi_device_enumerated(child)) {
+ dev_err(&child->dev, "has been enumerated\n");
+ return -EIO;
}
cell = (struct hisi_lpc_acpi_cell []){
@@ -511,16 +484,21 @@ static int hisi_lpc_acpi_add_child(struct acpi_device *child, void *data)
{
.hid = "HISI1031",
.name = "serial8250",
- .pdata = (struct plat_serial8250_port []) {
+ .data = (struct hisi_lpc_acpi_cell_data []) {
{
- .iobase = res->start,
- .uartclk = 1843200,
- .iotype = UPIO_PORT,
- .flags = UPF_BOOT_AUTOCONF,
+ .serial = {
+ {
+ // .iobase to be set after xlat'ing resources
+ .uartclk = 1843200,
+ .iotype = UPIO_PORT,
+ .flags = UPF_BOOT_AUTOCONF,
+ },
+ {}
+ },
},
{}
},
- .pdata_size = 2 *
+ .data_size = 2 *
sizeof(struct plat_serial8250_port),
},
{}
@@ -540,31 +518,26 @@ static int hisi_lpc_acpi_add_child(struct acpi_device *child, void *data)
return 0;
}
- pdev = platform_device_alloc(cell->name, PLATFORM_DEVID_AUTO);
- if (!pdev)
- return -ENOMEM;
-
- pdev->dev.parent = hostdev;
- ACPI_COMPANION_SET(&pdev->dev, child);
-
- ret = platform_device_add_resources(pdev, res, num_res);
- if (ret)
- goto fail;
-
- ret = platform_device_add_data(pdev, cell->pdata, cell->pdata_size);
- if (ret)
- goto fail;
+ if (cell->data) {
+ struct hisi_lpc_acpi_cell_data *cell_data = cell->data;
+ struct plat_serial8250_port *data = cell_data->serial;
+
+ cell_data->owner = cell;
+ pdev = acpi_create_platform_device_ops(child, cell->name, NULL,
+ data, cell->data_size,
+ hisi_lpc_acpi_xlat_res,
+ PLATFORM_DEVID_AUTO);
+ } else {
+ pdev = acpi_create_platform_device_ops(child, cell->name, NULL,
+ NULL, 0,
+ hisi_lpc_acpi_xlat_res,
+ PLATFORM_DEVID_AUTO);
+ }
- ret = platform_device_add(pdev);
- if (ret)
- goto fail;
+ if (IS_ERR_OR_NULL(pdev))
+ return -ENOMEM;
- acpi_device_set_enumerated(child);
return 0;
-
-fail:
- platform_device_put(pdev);
- return ret;
}
/*
--
2.35.3
prev parent reply other threads:[~2022-08-16 11:55 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-16 11:27 [PATCH PoC 0/3] ACPI/PNP/HISI_LPC: Refactor ACPI platform code for reuse John Garry
2022-08-16 11:27 ` [PATCH PoC 1/3] ACPI / PNP: Don't add enumeration_by_parent devices John Garry
2022-08-18 19:31 ` Andy Shevchenko
2022-08-19 8:05 ` John Garry
2022-08-19 9:59 ` Andy Shevchenko
2022-08-19 10:20 ` John Garry
2022-08-19 10:41 ` Andy Shevchenko
2022-08-16 11:27 ` [PATCH PoC 2/3] ACPI: platform: Refactor acpi_create_platform_device() John Garry
2022-08-18 19:41 ` Andy Shevchenko
2022-08-19 8:10 ` John Garry
2022-08-23 16:42 ` Rafael J. Wysocki
2022-09-01 10:52 ` John Garry
2022-08-16 11:27 ` John Garry [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1660649244-146842-4-git-send-email-john.garry@huawei.com \
--to=john.garry@huawei.com \
--cc=andy.shevchenko@gmail.com \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linuxarm@huawei.com \
--cc=rafael@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®