Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Mukesh Ojha and committed by
Jassi Brar
16274d7e e4b1d67e

+16
+16
drivers/mailbox/qcom-ipcc.c
··· 14 14 #include <dt-bindings/mailbox/qcom-ipcc.h> 15 15 16 16 /* IPCC Register offsets */ 17 + #define IPCC_REG_CONFIG 0x08 17 18 #define IPCC_REG_SEND_ID 0x0c 18 19 #define IPCC_REG_RECV_ID 0x10 19 20 #define IPCC_REG_RECV_SIGNAL_ENABLE 0x14 ··· 22 21 #define IPCC_REG_RECV_SIGNAL_CLEAR 0x1c 23 22 #define IPCC_REG_CLIENT_CLEAR 0x38 24 23 24 + #define IPCC_CLEAR_ON_RECV_RD BIT(0) 25 25 #define IPCC_SIGNAL_ID_MASK GENMASK(15, 0) 26 26 #define IPCC_CLIENT_ID_MASK GENMASK(31, 16) 27 27 ··· 276 274 static int qcom_ipcc_probe(struct platform_device *pdev) 277 275 { 278 276 struct qcom_ipcc *ipcc; 277 + u32 config_value; 279 278 static int id; 280 279 char *name; 281 280 int ret; ··· 290 287 ipcc->base = devm_platform_ioremap_resource(pdev, 0); 291 288 if (IS_ERR(ipcc->base)) 292 289 return PTR_ERR(ipcc->base); 290 + 291 + /* 292 + * It is possible that boot firmware is using the same IPCC instance 293 + * as of the HLOS and it has kept CLEAR_ON_RECV_RD set which basically 294 + * means Interrupt pending registers are cleared when RECV_ID is read. 295 + * The register automatically updates to the next pending interrupt/client 296 + * status based on priority. 297 + */ 298 + config_value = readl(ipcc->base + IPCC_REG_CONFIG); 299 + if (config_value & IPCC_CLEAR_ON_RECV_RD) { 300 + config_value &= ~(IPCC_CLEAR_ON_RECV_RD); 301 + writel(config_value, ipcc->base + IPCC_REG_CONFIG); 302 + } 293 303 294 304 ipcc->irq = platform_get_irq(pdev, 0); 295 305 if (ipcc->irq < 0)