mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
The APLIC states might be reset when the platform enters a low power state, but the register states are not being preserved and restored, which prevents interrupt delivery after the platform resumes. Solve this by adding a syscore ops and a power management notifier to preserve and restore the APLIC states on suspend and resume. [ tglx: Folded the build fix provided by Geert ] Signed-off-by: Nick Hu <nick.hu@sifive.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Yong-Xuan Wang <yongxuan.wang@sifive.com> Reviewed-by: Cyan Yang <cyan.yang@sifive.com> Reviewed-by: Nutty Liu <liujingqi@lanxincomputing.com> Reviewed-by: Anup Patel <anup@brainfault.org> Link: https://patch.msgid.link/20251202-preserve-aplic-imsic-v3-2-1844fbf1fe92@sifive.com
73 lines
1.7 KiB
C
73 lines
1.7 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (C) 2021 Western Digital Corporation or its affiliates.
|
|
* Copyright (C) 2022 Ventana Micro Systems Inc.
|
|
*/
|
|
|
|
#ifndef _IRQ_RISCV_APLIC_MAIN_H
|
|
#define _IRQ_RISCV_APLIC_MAIN_H
|
|
|
|
#include <linux/device.h>
|
|
#include <linux/io.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/irqdomain.h>
|
|
#include <linux/fwnode.h>
|
|
|
|
#define APLIC_DEFAULT_PRIORITY 1
|
|
|
|
struct aplic_msicfg {
|
|
phys_addr_t base_ppn;
|
|
u32 hhxs;
|
|
u32 hhxw;
|
|
u32 lhxs;
|
|
u32 lhxw;
|
|
};
|
|
|
|
struct aplic_src_ctrl {
|
|
u32 sourcecfg;
|
|
u32 target;
|
|
u32 ie;
|
|
};
|
|
|
|
struct aplic_saved_regs {
|
|
u32 domaincfg;
|
|
#ifdef CONFIG_RISCV_M_MODE
|
|
u32 msiaddr;
|
|
u32 msiaddrh;
|
|
#endif
|
|
struct aplic_src_ctrl *srcs;
|
|
};
|
|
|
|
struct aplic_priv {
|
|
struct list_head head;
|
|
struct notifier_block genpd_nb;
|
|
struct aplic_saved_regs saved_hw_regs;
|
|
struct device *dev;
|
|
u32 gsi_base;
|
|
u32 nr_irqs;
|
|
u32 nr_idcs;
|
|
u32 acpi_aplic_id;
|
|
void __iomem *regs;
|
|
struct aplic_msicfg msicfg;
|
|
};
|
|
|
|
void aplic_irq_unmask(struct irq_data *d);
|
|
void aplic_irq_mask(struct irq_data *d);
|
|
int aplic_irq_set_type(struct irq_data *d, unsigned int type);
|
|
int aplic_irqdomain_translate(struct irq_fwspec *fwspec, u32 gsi_base,
|
|
unsigned long *hwirq, unsigned int *type);
|
|
void aplic_init_hw_global(struct aplic_priv *priv, bool msi_mode);
|
|
int aplic_setup_priv(struct aplic_priv *priv, struct device *dev, void __iomem *regs);
|
|
void aplic_direct_restore_states(struct aplic_priv *priv);
|
|
int aplic_direct_setup(struct device *dev, void __iomem *regs);
|
|
#ifdef CONFIG_RISCV_APLIC_MSI
|
|
int aplic_msi_setup(struct device *dev, void __iomem *regs);
|
|
#else
|
|
static inline int aplic_msi_setup(struct device *dev, void __iomem *regs)
|
|
{
|
|
return -ENODEV;
|
|
}
|
|
#endif
|
|
|
|
#endif
|