aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVishnu Banavath <vishnu.banavath@arm.com>2019-08-14 18:02:11 +0100
committerTushar Khandelwal <tushar.khandelwal@arm.com>2019-09-04 12:00:11 +0100
commit23c61a1305d3c97218feb480eb453c7f9ae7af1b (patch)
treed504c5aba8d0db47efaab9d31afcd464776205f1
parent5cd524aebea3b630c2ec8e7897659a3d5f1dc49d (diff)
mailbox: arm_mhu_v2: dynamic allocation of channelsCORSTONE-700-2019.09.23
Typically, hardware reports number of channels it supports. Software should read the appropriate registers to determine the number of channels support and should make the allocations accordingly. This change is to achieve it by removing static allocation and making dynamic allocations. Change-Id: I7dd413bffa2bb218cda6e0e73ae1a021b2afb6e1
-rw-r--r--drivers/mailbox/arm_mhu_v2.c47
1 files changed, 35 insertions, 12 deletions
diff --git a/drivers/mailbox/arm_mhu_v2.c b/drivers/mailbox/arm_mhu_v2.c
index fe43348db5e3..56fb31eeaa87 100644
--- a/drivers/mailbox/arm_mhu_v2.c
+++ b/drivers/mailbox/arm_mhu_v2.c
@@ -30,7 +30,7 @@
#define MHU_V2_CHCOMB BIT(2)
#define MHU_V2_AIDR_MINOR(_reg) ((_reg) & 0xF)
-#define MHU_V2_CHANS 2
+#define MHU_V2_EACH_CHANNEL_SIZE 0x20
#define mbox_to_arm_mhuv2(c) container_of(c, struct arm_mhuv2, mbox)
@@ -42,8 +42,8 @@ struct mhuv2_link {
struct arm_mhuv2 {
void __iomem *base;
- struct mhuv2_link mlink[MHU_V2_CHANS];
- struct mbox_chan chan[MHU_V2_CHANS];
+ struct mhuv2_link *mlink;
+ struct mbox_chan *chan;
struct mbox_controller mbox;
};
@@ -140,6 +140,9 @@ static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id)
void __iomem *rx_base, *tx_base;
const struct device_node *np = dev->of_node;
unsigned int pchans;
+ struct mhuv2_link *mlink;
+ struct mbox_chan *chan;
+
/* Allocate memory for device */
mhuv2 = devm_kzalloc(dev, sizeof(*mhuv2), GFP_KERNEL);
@@ -159,25 +162,43 @@ static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id)
return -ENOMEM;
}
-
pchans = readl_relaxed(tx_base + MHU_V2_REG_MSG_NO_CAP_OFS);
- if (pchans == 0 || pchans > MHU_V2_CHANS || pchans % 2) {
+ if (pchans == 0 || pchans % 2) {
dev_err(dev, "invalid number of channels %d\n", pchans);
iounmap(rx_base);
iounmap(tx_base);
return -EINVAL;
}
- for (i = 0; i < pchans/2; i++) {
- mhuv2->chan[i].con_priv = &mhuv2->mlink[i];
- mhuv2->mlink[i].irq = adev->irq[i];
- mhuv2->mlink[i].rx_reg = rx_base + i*0x4;
- mhuv2->mlink[i].tx_reg = tx_base + i*0x4;
- mhuv2_check_enable_cmbint(&mhuv2->mlink[i]);
+
+ mhuv2->mlink = devm_kcalloc(dev, pchans, sizeof(*mlink), GFP_KERNEL);
+ if (!mhuv2->mlink) {
+ iounmap(rx_base);
+ iounmap(tx_base);
+ return -ENOMEM;
+ }
+
+ mhuv2->chan = devm_kcalloc(dev, pchans, sizeof(*chan), GFP_KERNEL);
+ if (!mhuv2->chan) {
+ iounmap(rx_base);
+ iounmap(tx_base);
+ kfree(mhuv2->mlink);
+ return -ENOMEM;
}
+ for (i = 0; i < pchans; i++) {
+ mlink = mhuv2->mlink + i;
+ chan = mhuv2->chan + i;
+ chan->con_priv = mlink;
+ mlink->rx_reg = rx_base + (i * MHU_V2_EACH_CHANNEL_SIZE);
+ mlink->tx_reg = tx_base + (i * MHU_V2_EACH_CHANNEL_SIZE);
+ }
+
+ mhuv2->mlink->irq = adev->irq[0];
+ mhuv2_check_enable_cmbint(mhuv2->mlink);
+
mhuv2->base = tx_base;
mhuv2->mbox.dev = dev;
- mhuv2->mbox.chans = &mhuv2->chan[0];
+ mhuv2->mbox.chans = mhuv2->chan;
mhuv2->mbox.num_chans = pchans;
mhuv2->mbox.ops = &mhuv2_ops;
mhuv2->mbox.txdone_irq = false;
@@ -191,6 +212,8 @@ static int mhuv2_probe(struct amba_device *adev, const struct amba_id *id)
dev_err(dev, "failed to register mailboxes %d\n", err);
iounmap(rx_base);
iounmap(tx_base);
+ kfree(mhuv2->mlink);
+ kfree(mhuv2->chan);
return err;
}