Skip to content

Commit 16274d7

Browse files
mukeshojha-linuxJassi Brar
authored andcommitted
mailbox: qcom-ipcc: Reset CLEAR_ON_RECV_RD if set from boot firmware
For some SoCs, boot firmware is using the same IPCC instance used by Linux and it has kept CLEAR_ON_RECV_RD set which basically means interrupt pending registers are cleared when RECV_ID is read and the register automatically updates to the next pending interrupt/client status based on priority. Clear the CLEAR_ON_RECV_RD if it is set from the boot firmware. Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com> Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
1 parent e4b1d67 commit 16274d7

File tree

1 file changed

+16
-0
lines changed

1 file changed

+16
-0
lines changed

drivers/mailbox/qcom-ipcc.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
#include <dt-bindings/mailbox/qcom-ipcc.h>
1515

1616
/* IPCC Register offsets */
17+
#define IPCC_REG_CONFIG 0x08
1718
#define IPCC_REG_SEND_ID 0x0c
1819
#define IPCC_REG_RECV_ID 0x10
1920
#define IPCC_REG_RECV_SIGNAL_ENABLE 0x14
2021
#define IPCC_REG_RECV_SIGNAL_DISABLE 0x18
2122
#define IPCC_REG_RECV_SIGNAL_CLEAR 0x1c
2223
#define IPCC_REG_CLIENT_CLEAR 0x38
2324

25+
#define IPCC_CLEAR_ON_RECV_RD BIT(0)
2426
#define IPCC_SIGNAL_ID_MASK GENMASK(15, 0)
2527
#define IPCC_CLIENT_ID_MASK GENMASK(31, 16)
2628

@@ -274,6 +276,7 @@ static int qcom_ipcc_pm_resume(struct device *dev)
274276
static int qcom_ipcc_probe(struct platform_device *pdev)
275277
{
276278
struct qcom_ipcc *ipcc;
279+
u32 config_value;
277280
static int id;
278281
char *name;
279282
int ret;
@@ -288,6 +291,19 @@ static int qcom_ipcc_probe(struct platform_device *pdev)
288291
if (IS_ERR(ipcc->base))
289292
return PTR_ERR(ipcc->base);
290293

294+
/*
295+
* It is possible that boot firmware is using the same IPCC instance
296+
* as of the HLOS and it has kept CLEAR_ON_RECV_RD set which basically
297+
* means Interrupt pending registers are cleared when RECV_ID is read.
298+
* The register automatically updates to the next pending interrupt/client
299+
* status based on priority.
300+
*/
301+
config_value = readl(ipcc->base + IPCC_REG_CONFIG);
302+
if (config_value & IPCC_CLEAR_ON_RECV_RD) {
303+
config_value &= ~(IPCC_CLEAR_ON_RECV_RD);
304+
writel(config_value, ipcc->base + IPCC_REG_CONFIG);
305+
}
306+
291307
ipcc->irq = platform_get_irq(pdev, 0);
292308
if (ipcc->irq < 0)
293309
return ipcc->irq;

0 commit comments

Comments
 (0)