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.

soc: qcom: smp2p: Add irqchip state support

A remoteproc booted during earlier boot stages such as UEFI or the
bootloader, may need to be attached to without restarting the remoteproc
hardware. To do this the remoteproc will need to check the ready and
handover states in smp2p without an interrupt notification. Create
qcom_smp2p_start_in() to initialize the shadow state without notifying
clients because these early events happened in the past.

Add support for the .irq_get_irqchip_state callback so remoteproc can
read the current state of the fatal, ready and handover bits.

Signed-off-by: Chris Lew <chris.lew@oss.qualcomm.com>
Signed-off-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260127-smp2pv2-v3-1-4060b859b1e2@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>

authored by

Chris Lew and committed by
Bjorn Andersson
8a9a7b9d 7a7d24a1

+55
+55
drivers/soc/qcom/smp2p.c
··· 222 222 } 223 223 } 224 224 225 + static void qcom_smp2p_start_in(struct qcom_smp2p *smp2p) 226 + { 227 + unsigned int smem_id = smp2p->smem_items[SMP2P_INBOUND]; 228 + unsigned int pid = smp2p->remote_pid; 229 + char buf[SMP2P_MAX_ENTRY_NAME]; 230 + struct smp2p_smem_item *in; 231 + struct smp2p_entry *entry; 232 + size_t size; 233 + int i; 234 + 235 + in = qcom_smem_get(pid, smem_id, &size); 236 + if (IS_ERR(in)) 237 + return; 238 + 239 + smp2p->in = in; 240 + 241 + /* Check if version is initialized by the remote. */ 242 + if (in->version == 0) 243 + return; 244 + 245 + for (i = smp2p->valid_entries; i < in->valid_entries; i++) { 246 + list_for_each_entry(entry, &smp2p->inbound, node) { 247 + memcpy(buf, in->entries[i].name, sizeof(buf)); 248 + if (!strcmp(buf, entry->name)) { 249 + entry->value = &in->entries[i].value; 250 + entry->last_value = readl(entry->value); 251 + break; 252 + } 253 + } 254 + } 255 + smp2p->valid_entries = i; 256 + } 257 + 225 258 static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p) 226 259 { 227 260 struct smp2p_smem_item *in; ··· 401 368 seq_printf(p, "%8s", dev_name(entry->smp2p->dev)); 402 369 } 403 370 371 + static int smp2p_irq_get_irqchip_state(struct irq_data *irqd, enum irqchip_irq_state which, 372 + bool *state) 373 + { 374 + struct smp2p_entry *entry = irq_data_get_irq_chip_data(irqd); 375 + u32 val; 376 + 377 + if (which != IRQCHIP_STATE_LINE_LEVEL) 378 + return -EINVAL; 379 + 380 + if (!entry->value) 381 + return -ENODEV; 382 + 383 + val = readl(entry->value); 384 + *state = !!(val & BIT(irqd_to_hwirq(irqd))); 385 + 386 + return 0; 387 + } 388 + 404 389 static struct irq_chip smp2p_irq_chip = { 405 390 .name = "smp2p", 406 391 .irq_mask = smp2p_mask_irq, 407 392 .irq_unmask = smp2p_unmask_irq, 408 393 .irq_set_type = smp2p_set_irq_type, 409 394 .irq_print_chip = smp2p_irq_print_chip, 395 + .irq_get_irqchip_state = smp2p_irq_get_irqchip_state, 410 396 }; 411 397 412 398 static int smp2p_irq_map(struct irq_domain *d, ··· 669 617 list_add(&entry->node, &smp2p->outbound); 670 618 } 671 619 } 620 + 621 + /* Check inbound entries in the case of early boot processor */ 622 + qcom_smp2p_start_in(smp2p); 672 623 673 624 /* Kick the outgoing edge after allocating entries */ 674 625 qcom_smp2p_kick(smp2p);