Update the QCOM_IPCC driver with below main features:
Dynamic alloc for channel arrangement instead of static alloced
array.
Multiple instance can be supported.
IPCC interrupt wake up support from suspend.
More protocol and client ID support added.
Huang Yiwei (4):
mailbox: qcom-ipcc: Dynamic alloc for channel arrangement
mailbox: qcom-ipcc: Support more IPCC instance
mailbox: qcom-ipcc: Support interrupt wake up from suspend
dt-bindings: mailbox: Add more protocol and client ID
drivers/mailbox/qcom-ipcc.c | 99 +++++++++++++++++++------
include/dt-bindings/mailbox/qcom-ipcc.h | 2 +
2 files changed, 78 insertions(+), 23 deletions(-)
--
2.17.1
Dynamic alloc for channel arrangement instead of static alloced
array, it is more flexible and can reduce memory usage.
Signed-off-by: Huang Yiwei <[email protected]>
---
drivers/mailbox/qcom-ipcc.c | 90 ++++++++++++++++++++++++++++---------
1 file changed, 69 insertions(+), 21 deletions(-)
diff --git a/drivers/mailbox/qcom-ipcc.c b/drivers/mailbox/qcom-ipcc.c
index f1d4f4679b17..10cb0b546109 100644
--- a/drivers/mailbox/qcom-ipcc.c
+++ b/drivers/mailbox/qcom-ipcc.c
@@ -13,8 +13,6 @@
#include <dt-bindings/mailbox/qcom-ipcc.h>
-#define IPCC_MBOX_MAX_CHAN 48
-
/* IPCC Register offsets */
#define IPCC_REG_SEND_ID 0x0c
#define IPCC_REG_RECV_ID 0x10
@@ -52,9 +50,10 @@ struct qcom_ipcc {
struct device *dev;
void __iomem *base;
struct irq_domain *irq_domain;
- struct mbox_chan chan[IPCC_MBOX_MAX_CHAN];
- struct qcom_ipcc_chan_info mchan[IPCC_MBOX_MAX_CHAN];
+ struct mbox_chan *chans;
+ struct qcom_ipcc_chan_info *mchan;
struct mbox_controller mbox;
+ int num_chans;
int irq;
};
@@ -166,25 +165,37 @@ static struct mbox_chan *qcom_ipcc_mbox_xlate(struct mbox_controller *mbox,
struct qcom_ipcc *ipcc = to_qcom_ipcc(mbox);
struct qcom_ipcc_chan_info *mchan;
struct mbox_chan *chan;
- unsigned int i;
+ struct device *dev;
+ int chan_id;
+
+ dev = ipcc->dev;
if (ph->args_count != 2)
return ERR_PTR(-EINVAL);
- for (i = 0; i < IPCC_MBOX_MAX_CHAN; i++) {
- chan = &ipcc->chan[i];
- if (!chan->con_priv) {
- mchan = &ipcc->mchan[i];
- mchan->client_id = ph->args[0];
- mchan->signal_id = ph->args[1];
- chan->con_priv = mchan;
- break;
- }
+ for (chan_id = 0; chan_id < mbox->num_chans; chan_id++) {
+ chan = &ipcc->chans[chan_id];
+ mchan = chan->con_priv;
- chan = NULL;
+ if (!mchan)
+ break;
+ else if (mchan->client_id == ph->args[0] &&
+ mchan->signal_id == ph->args[1])
+ return ERR_PTR(-EBUSY);
}
- return chan ?: ERR_PTR(-EBUSY);
+ if (chan_id >= mbox->num_chans)
+ return ERR_PTR(-EBUSY);
+
+ mchan = devm_kzalloc(dev, sizeof(*mchan), GFP_KERNEL);
+ if (!mchan)
+ return ERR_PTR(-ENOMEM);
+
+ mchan->client_id = ph->args[0];
+ mchan->signal_id = ph->args[1];
+ chan->con_priv = mchan;
+
+ return chan;
}
static const struct mbox_chan_ops ipcc_mbox_chan_ops = {
@@ -192,15 +203,49 @@ static const struct mbox_chan_ops ipcc_mbox_chan_ops = {
.shutdown = qcom_ipcc_mbox_shutdown,
};
-static int qcom_ipcc_setup_mbox(struct qcom_ipcc *ipcc)
+static int qcom_ipcc_setup_mbox(struct qcom_ipcc *ipcc,
+ struct device_node *controller_dn)
{
+ struct of_phandle_args curr_ph;
+ struct device_node *client_dn;
struct mbox_controller *mbox;
struct device *dev = ipcc->dev;
+ int i, j, ret;
+
+ /*
+ * Find out the number of clients interested in this mailbox
+ * and create channels accordingly.
+ */
+ ipcc->num_chans = 0;
+ for_each_node_with_property(client_dn, "mboxes") {
+ if (!of_device_is_available(client_dn))
+ continue;
+ i = of_count_phandle_with_args(client_dn,
+ "mboxes", "#mbox-cells");
+ for (j = 0; j < i; j++) {
+ ret = of_parse_phandle_with_args(client_dn, "mboxes",
+ "#mbox-cells", j, &curr_ph);
+ of_node_put(curr_ph.np);
+ if (!ret && curr_ph.np == controller_dn) {
+ ipcc->num_chans++;
+ break;
+ }
+ }
+ }
+
+ /* If no clients are found, skip registering as a mbox controller */
+ if (!ipcc->num_chans)
+ return 0;
+
+ ipcc->chans = devm_kcalloc(dev, ipcc->num_chans,
+ sizeof(struct mbox_chan), GFP_KERNEL);
+ if (!ipcc->chans)
+ return -ENOMEM;
mbox = &ipcc->mbox;
mbox->dev = dev;
- mbox->num_chans = IPCC_MBOX_MAX_CHAN;
- mbox->chans = ipcc->chan;
+ mbox->num_chans = ipcc->num_chans;
+ mbox->chans = ipcc->chans;
mbox->ops = &ipcc_mbox_chan_ops;
mbox->of_xlate = qcom_ipcc_mbox_xlate;
mbox->txdone_irq = false;
@@ -233,7 +278,7 @@ static int qcom_ipcc_probe(struct platform_device *pdev)
if (!ipcc->irq_domain)
return -ENOMEM;
- ret = qcom_ipcc_setup_mbox(ipcc);
+ ret = qcom_ipcc_setup_mbox(ipcc, pdev->dev.of_node);
if (ret)
goto err_mbox;
@@ -241,7 +286,7 @@ static int qcom_ipcc_probe(struct platform_device *pdev)
IRQF_TRIGGER_HIGH, "ipcc", ipcc);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register the irq: %d\n", ret);
- goto err_mbox;
+ goto err_req_irq;
}
enable_irq_wake(ipcc->irq);
@@ -249,6 +294,9 @@ static int qcom_ipcc_probe(struct platform_device *pdev)
return 0;
+err_req_irq:
+ if (ipcc->num_chans)
+ mbox_controller_unregister(&ipcc->mbox);
err_mbox:
irq_domain_remove(ipcc->irq_domain);
--
2.17.1
Since hardware is supporting multiple IPCC instance,
use ipcc_%d instead of ipcc as the irq name to support
in driver.
Signed-off-by: Huang Yiwei <[email protected]>
---
drivers/mailbox/qcom-ipcc.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/mailbox/qcom-ipcc.c b/drivers/mailbox/qcom-ipcc.c
index 10cb0b546109..e80aaf83a089 100644
--- a/drivers/mailbox/qcom-ipcc.c
+++ b/drivers/mailbox/qcom-ipcc.c
@@ -257,6 +257,8 @@ static int qcom_ipcc_setup_mbox(struct qcom_ipcc *ipcc,
static int qcom_ipcc_probe(struct platform_device *pdev)
{
struct qcom_ipcc *ipcc;
+ static int id;
+ char *name;
int ret;
ipcc = devm_kzalloc(&pdev->dev, sizeof(*ipcc), GFP_KERNEL);
@@ -273,6 +275,10 @@ static int qcom_ipcc_probe(struct platform_device *pdev)
if (ipcc->irq < 0)
return ipcc->irq;
+ name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "ipcc_%d", id++);
+ if (!name)
+ return -ENOMEM;
+
ipcc->irq_domain = irq_domain_add_tree(pdev->dev.of_node,
&qcom_ipcc_irq_ops, ipcc);
if (!ipcc->irq_domain)
@@ -283,7 +289,7 @@ static int qcom_ipcc_probe(struct platform_device *pdev)
goto err_mbox;
ret = devm_request_irq(&pdev->dev, ipcc->irq, qcom_ipcc_irq_fn,
- IRQF_TRIGGER_HIGH, "ipcc", ipcc);
+ IRQF_TRIGGER_HIGH, name, ipcc);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register the irq: %d\n", ret);
goto err_req_irq;
--
2.17.1
Use IRQF_NO_SUSPEND flag instead of enable_irq_wake to
support interrupt wake up from suspend.
Signed-off-by: Huang Yiwei <[email protected]>
---
drivers/mailbox/qcom-ipcc.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/mailbox/qcom-ipcc.c b/drivers/mailbox/qcom-ipcc.c
index e80aaf83a089..c5d963222014 100644
--- a/drivers/mailbox/qcom-ipcc.c
+++ b/drivers/mailbox/qcom-ipcc.c
@@ -289,13 +289,12 @@ static int qcom_ipcc_probe(struct platform_device *pdev)
goto err_mbox;
ret = devm_request_irq(&pdev->dev, ipcc->irq, qcom_ipcc_irq_fn,
- IRQF_TRIGGER_HIGH, name, ipcc);
+ IRQF_TRIGGER_HIGH | IRQF_NO_SUSPEND, name, ipcc);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register the irq: %d\n", ret);
goto err_req_irq;
}
- enable_irq_wake(ipcc->irq);
platform_set_drvdata(pdev, ipcc);
return 0;
--
2.17.1
Add more protocol and client ID which can be used in device
tree properties.
Signed-off-by: Huang Yiwei <[email protected]>
---
include/dt-bindings/mailbox/qcom-ipcc.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/dt-bindings/mailbox/qcom-ipcc.h b/include/dt-bindings/mailbox/qcom-ipcc.h
index eb91a6c05b71..9296d0bb5f34 100644
--- a/include/dt-bindings/mailbox/qcom-ipcc.h
+++ b/include/dt-bindings/mailbox/qcom-ipcc.h
@@ -8,6 +8,7 @@
/* Signal IDs for MPROC protocol */
#define IPCC_MPROC_SIGNAL_GLINK_QMP 0
+#define IPCC_MPROC_SIGNAL_TZ 1
#define IPCC_MPROC_SIGNAL_SMP2P 2
#define IPCC_MPROC_SIGNAL_PING 3
@@ -29,6 +30,7 @@
#define IPCC_CLIENT_PCIE1 14
#define IPCC_CLIENT_PCIE2 15
#define IPCC_CLIENT_SPSS 16
+#define IPCC_CLIENT_TME 23
#define IPCC_CLIENT_WPSS 24
#endif
--
2.17.1
On Sun, Nov 21, 2021 at 11:06 PM Huang Yiwei <[email protected]> wrote:
>
> Dynamic alloc for channel arrangement instead of static alloced
> array, it is more flexible and can reduce memory usage.
>
Since this is a popular platform, can we arrange for some Tested-by
and Reviewed-by ?
-Jassi