Messages in this thread Patch in this message | | | Date | Thu, 24 Nov 2022 15:09:31 +0800 | From | Wang Honghui <> | Subject | [PATCH 3/3] arm_scpi: modify to support acpi |
| |
arm_scpi: modify to support acpi
Signed-off-by: Wang Honghui <honghui.wang@ucas.com.cn> --- drivers/firmware/arm_scpi.c | 188 +++++++++++++++++++++--------- drivers/mailbox/phytium_mailbox.c | 44 +++++++ 2 files changed, 180 insertions(+), 52 deletions(-)
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c index 435d0e2658a4..e2e90dcc38bd 100644 --- a/drivers/firmware/arm_scpi.c +++ b/drivers/firmware/arm_scpi.c @@ -34,6 +34,7 @@ #include <linux/slab.h> #include <linux/sort.h> #include <linux/spinlock.h> +#include <linux/acpi.h> #define CMD_ID_MASK GENMASK(6, 0) #define CMD_TOKEN_ID_MASK GENMASK(15, 8) @@ -907,6 +908,8 @@ static const struct of_device_id shmem_of_match[] __maybe_unused = { { } }; +extern struct mbox_chan *phytium_mbox_request_channel(struct mbox_client *cl); + static int scpi_probe(struct platform_device *pdev) { int count, idx, ret; @@ -914,18 +917,30 @@ static int scpi_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct scpi_drvinfo *scpi_drvinfo; + const struct acpi_device_id *match; scpi_drvinfo = devm_kzalloc(dev, sizeof(*scpi_drvinfo), GFP_KERNEL); if (!scpi_drvinfo) return -ENOMEM; - if (of_match_device(legacy_scpi_of_match, &pdev->dev)) - scpi_drvinfo->is_legacy = true; + /* Wang Honghui modified to support acpi */ + if (dev->of_node) { + if (of_match_device(legacy_scpi_of_match, &pdev->dev)) + scpi_drvinfo->is_legacy = true; - count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells"); - if (count < 0) { - dev_err(dev, "no mboxes property in '%pOF'\n", np); - return -ENODEV; + count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells"); + if (count < 0) { + dev_err(dev, "no mboxes property in '%pOF'\n", np); + return -ENODEV; + } + } else { + match = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!match) { + dev_err(dev, "scpi: Error ACPI match data is missing\n"); + return -ENODEV; + } + + count = 1; } scpi_drvinfo->channels = @@ -937,55 +952,116 @@ static int scpi_probe(struct platform_device *pdev) if (ret) return ret; - for (; scpi_drvinfo->num_chans < count; scpi_drvinfo->num_chans++) { - resource_size_t size; - int idx = scpi_drvinfo->num_chans; - struct scpi_chan *pchan = scpi_drvinfo->channels + idx; - struct mbox_client *cl = &pchan->cl; - struct device_node *shmem = of_parse_phandle(np, "shmem", idx); - - if (!of_match_node(shmem_of_match, shmem)) - return -ENXIO; + /* Wang Honghui modified to support acpi */ + if (dev->of_node) { + for (; scpi_drvinfo->num_chans < count; scpi_drvinfo->num_chans++) { + resource_size_t size; + int idx = scpi_drvinfo->num_chans; + struct scpi_chan *pchan = scpi_drvinfo->channels + idx; + struct mbox_client *cl = &pchan->cl; + struct device_node *shmem = of_parse_phandle(np, "shmem", idx); + + if (!of_match_node(shmem_of_match, shmem)) + return -ENXIO; + + ret = of_address_to_resource(shmem, 0, &res); + of_node_put(shmem); + if (ret) { + dev_err(dev, "failed to get SCPI payload mem resource\n"); + return ret; + } - ret = of_address_to_resource(shmem, 0, &res); - of_node_put(shmem); - if (ret) { - dev_err(dev, "failed to get SCPI payload mem resource\n"); + size = resource_size(&res); + pchan->rx_payload = devm_ioremap(dev, res.start, size); + if (!pchan->rx_payload) { + dev_err(dev, "failed to ioremap SCPI payload\n"); + return -EADDRNOTAVAIL; + } + pchan->tx_payload = pchan->rx_payload + (size >> 1); + + cl->dev = dev; + cl->rx_callback = scpi_handle_remote_msg; + cl->tx_prepare = scpi_tx_prepare; + cl->tx_block = true; + cl->tx_tout = 20; + cl->knows_txdone = false; /* controller can't ack */ + + INIT_LIST_HEAD(&pchan->rx_pending); + INIT_LIST_HEAD(&pchan->xfers_list); + spin_lock_init(&pchan->rx_lock); + mutex_init(&pchan->xfers_lock); + + ret = scpi_alloc_xfer_list(dev, pchan); + if (!ret) { + pchan->chan = mbox_request_channel(cl, idx); + if (!IS_ERR(pchan->chan)) + continue; + ret = PTR_ERR(pchan->chan); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get channel%d err %d\n", + idx, ret); + } return ret; } - - size = resource_size(&res); - pchan->rx_payload = devm_ioremap(dev, res.start, size); - if (!pchan->rx_payload) { - dev_err(dev, "failed to ioremap SCPI payload\n"); - return -EADDRNOTAVAIL; - } - pchan->tx_payload = pchan->rx_payload + (size >> 1); - - cl->dev = dev; - cl->rx_callback = scpi_handle_remote_msg; - cl->tx_prepare = scpi_tx_prepare; - cl->tx_block = true; - cl->tx_tout = 20; - cl->knows_txdone = false; /* controller can't ack */ - - INIT_LIST_HEAD(&pchan->rx_pending); - INIT_LIST_HEAD(&pchan->xfers_list); - spin_lock_init(&pchan->rx_lock); - mutex_init(&pchan->xfers_lock); - - ret = scpi_alloc_xfer_list(dev, pchan); - if (!ret) { - pchan->chan = mbox_request_channel(cl, idx); - if (!IS_ERR(pchan->chan)) - continue; - ret = PTR_ERR(pchan->chan); - if (ret != -EPROBE_DEFER) - dev_err(dev, "failed to get channel%d err %d\n", - idx, ret); - } - return ret; - } + } else { + for (; scpi_info->num_chans < count; scpi_info->num_chans++) { + u32 size; + u32 addr; + int idx = scpi_info->num_chans; + struct scpi_chan *pchan = scpi_info->channels + idx; + struct mbox_client *cl = &pchan->cl; + struct fwnode_handle *fn; + + fn = dev_fwnode(&(pdev->dev)); + ret = fwnode_property_read_u32(fn, "shmem_start", &addr); + if (ret < 0) { + dev_err(dev, "failed to get SCPI payload mem resource\n"); + return ret; + } + + ret = fwnode_property_read_u32(fn, "shmem_size", &size); + if (ret < 0) { + dev_err(dev, "failed to ioremap SCPI payload\n"); + return -EADDRNOTAVAIL; + } + + pchan->rx_payload = devm_ioremap(dev, (resource_size_t)addr, (resource_size_t)size); + + if (!pchan->rx_payload) { + dev_err(dev, "failed to ioremap SCPI payload\n"); + return -EADDRNOTAVAIL; + } + pchan->tx_payload = pchan->rx_payload + (size >> 1); + + cl->dev = dev; + cl->rx_callback = scpi_handle_remote_msg; + cl->tx_prepare = scpi_tx_prepare; + cl->tx_block = true; + cl->tx_tout = 20; + cl->knows_txdone = false; /* controller can't ack */ + + INIT_LIST_HEAD(&pchan->rx_pending); + INIT_LIST_HEAD(&pchan->xfers_list); + spin_lock_init(&pchan->rx_lock); + mutex_init(&pchan->xfers_lock); + + ret = scpi_alloc_xfer_list(dev, pchan); + + if (!ret) { + pchan->chan = phytium_mbox_request_channel(cl); + + if (!IS_ERR(pchan->chan)) + continue; + + ret = PTR_ERR(pchan->chan); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get channel%d err %d\n", + idx, ret); + } + + return ret; + } + } scpi_drvinfo->commands = scpi_std_commands; @@ -1044,11 +1120,19 @@ static const struct of_device_id scpi_of_match[] = { MODULE_DEVICE_TABLE(of, scpi_of_match); +/* Wang Honghui add to support Phytium FT2000/4 CPU for acpi */ +static const struct acpi_device_id scpi_acpi_match[] = { + { "PHYT0008", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, scpi_acpi_match); + static struct platform_driver scpi_driver = { .driver = { .name = "scpi_protocol", .of_match_table = scpi_of_match, .dev_groups = versions_groups, + .acpi_match_table = ACPI_PTR(scpi_acpi_match), }, .probe = scpi_probe, .remove = scpi_remove, diff --git a/drivers/mailbox/phytium_mailbox.c b/drivers/mailbox/phytium_mailbox.c index c797d4b4769f..e5ee3d4e7d5f 100644 --- a/drivers/mailbox/phytium_mailbox.c +++ b/drivers/mailbox/phytium_mailbox.c @@ -23,6 +23,10 @@ #include <linux/of_device.h> #include <linux/platform_device.h> +/* Wang Honghui add */ +#include <linux/mailbox_client.h> +#include "mailbox.h" + #define INTR_STAT 0x0 #define INTR_SET 0x8 #define INTR_CLR 0x10 @@ -31,6 +35,9 @@ #define NR_CHANS 1 +/* Wang Honghui add */ +static struct mbox_chan *phytium_mbox_chan; + struct phytium_mbox_link { unsigned irq; void __iomem *tx_reg; @@ -183,6 +190,43 @@ static int phytium_mbox_remove(struct platform_device *pdev) return 0; } +/* +** Wang Honghui add for scpi to request mbox chan +*/ +struct mbox_chan *phytium_mbox_request_channel(struct mbox_client *cl) +{ + struct device *dev = cl->dev; + struct mbox_chan *chan = phytium_mbox_chan; + unsigned long flags; + int ret; + + if(!chan) + return ERR_PTR(-EPROBE_DEFER); + + spin_lock_irqsave(&chan->lock, flags); + chan->msg_free = 0; + chan->msg_count = 0; + chan->active_req = NULL; + chan->cl = cl; + init_completion(&chan->tx_complete); + + if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone) + chan->txdone_method = TXDONE_BY_ACK; + + spin_unlock_irqrestore(&chan->lock, flags); + + if (chan->mbox->ops->startup) { + ret = chan->mbox->ops->startup(chan); + + if (ret) { + + dev_err(dev, "Unable to startup the chan (%d)\n", ret); + chan = ERR_PTR(ret); + } + } + return chan; +} + static struct platform_driver phytium_mbox_driver = { .probe = phytium_mbox_probe, .remove = phytium_mbox_remove, -- 2.34.1
| |