mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2026-05-23 14:21:32 +01:00
lib: sbi_irqchip: Add support for registering MSI handlers
Some of the drivers (such as APLIC) require capability to registers MSI handlers from the parent interrupt controller (such as IMSIC) so add sbi_irqchip_register_msi_handler() for this purpose. Link: https://lore.kernel.org/r/20260423052339.356900-7-anup.patel@oss.qualcomm.com Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
@@ -16,6 +16,13 @@
|
||||
|
||||
struct sbi_scratch;
|
||||
|
||||
/** irqchip message signalled interrupt (MSI) */
|
||||
struct sbi_irqchip_msi_msg {
|
||||
u32 address_lo;
|
||||
u32 address_hi;
|
||||
u32 data;
|
||||
};
|
||||
|
||||
/** irqchip hardware device */
|
||||
struct sbi_irqchip_device {
|
||||
/** Node in the list of irqchip devices (private) */
|
||||
@@ -109,6 +116,18 @@ int sbi_irqchip_get_affinity(struct sbi_irqchip_device *chip, u32 hwirq,
|
||||
/** Set hardware interrupt affinity */
|
||||
int sbi_irqchip_set_affinity(struct sbi_irqchip_device *chip, u32 hwirq, u32 hart_index);
|
||||
|
||||
/** Write MSI message to the hardware interrupt handler */
|
||||
int sbi_irqchip_write_msi(struct sbi_irqchip_device *chip, u32 hwirq,
|
||||
const struct sbi_irqchip_msi_msg *msg);
|
||||
|
||||
/** Register a hardware MSI handler */
|
||||
int sbi_irqchip_register_msi(struct sbi_irqchip_device *chip, u32 num_hwirq,
|
||||
void (*write_msi)(u32 hwirq,
|
||||
const struct sbi_irqchip_msi_msg *msg,
|
||||
void *priv),
|
||||
int (*callback)(u32 hwirq, void *priv), void *priv,
|
||||
u32 *out_first_hwirq);
|
||||
|
||||
/** Register a hardware interrupt handler */
|
||||
int sbi_irqchip_register_handler(struct sbi_irqchip_device *chip,
|
||||
u32 first_hwirq, u32 num_hwirq, u32 hwirq_flags,
|
||||
|
||||
+69
-2
@@ -35,6 +35,9 @@ struct sbi_irqchip_handler {
|
||||
/** Number of consecutive hardware IRQs handled by this handler */
|
||||
u32 num_hwirq;
|
||||
|
||||
/** Write MSI function of this handler */
|
||||
void (*write_msi)(u32 hwirq, const struct sbi_irqchip_msi_msg *msg, void *priv);
|
||||
|
||||
/** Callback function of this handler */
|
||||
int (*callback)(u32 hwirq, void *priv);
|
||||
|
||||
@@ -141,6 +144,24 @@ int sbi_irqchip_set_raw_handler(struct sbi_irqchip_device *chip, u32 hwirq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sbi_irqchip_write_msi(struct sbi_irqchip_device *chip, u32 hwirq,
|
||||
const struct sbi_irqchip_msi_msg *msg)
|
||||
{
|
||||
struct sbi_irqchip_handler *h;
|
||||
|
||||
if (!chip || chip->num_hwirq <= hwirq || !msg)
|
||||
return SBI_EINVAL;
|
||||
|
||||
h = sbi_irqchip_find_handler(chip, hwirq);
|
||||
if (!h)
|
||||
return SBI_EFAIL;
|
||||
if (!h->write_msi)
|
||||
return SBI_ENOTSUPP;
|
||||
|
||||
h->write_msi(hwirq, msg, h->priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sbi_irqchip_get_affinity(struct sbi_irqchip_device *chip, u32 hwirq,
|
||||
u32 *out_hart_index)
|
||||
{
|
||||
@@ -215,6 +236,9 @@ static int __sbi_irqchip_handler_set_affinity(struct sbi_irqchip_device *chip,
|
||||
|
||||
static int __sbi_irqchip_register_handler(struct sbi_irqchip_device *chip,
|
||||
u32 first_hwirq, u32 num_hwirq, u32 hwirq_flags,
|
||||
void (*write_msi)(u32 hwirq,
|
||||
const struct sbi_irqchip_msi_msg *msg,
|
||||
void *priv),
|
||||
int (*callback)(u32 hwirq, void *priv), void *priv)
|
||||
{
|
||||
struct sbi_irqchip_handler *h, *th, *nh;
|
||||
@@ -232,6 +256,7 @@ static int __sbi_irqchip_register_handler(struct sbi_irqchip_device *chip,
|
||||
return SBI_ENOMEM;
|
||||
h->first_hwirq = first_hwirq;
|
||||
h->num_hwirq = num_hwirq;
|
||||
h->write_msi = write_msi;
|
||||
h->callback = callback;
|
||||
h->priv = priv;
|
||||
|
||||
@@ -281,6 +306,48 @@ static int __sbi_irqchip_register_handler(struct sbi_irqchip_device *chip,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sbi_irqchip_register_msi(struct sbi_irqchip_device *chip, u32 num_hwirq,
|
||||
void (*write_msi)(u32 hwirq,
|
||||
const struct sbi_irqchip_msi_msg *msg,
|
||||
void *priv),
|
||||
int (*callback)(u32 hwirq, void *priv), void *priv,
|
||||
u32 *out_first_hwirq)
|
||||
{
|
||||
struct sbi_irqchip_handler *h;
|
||||
bool found;
|
||||
u32 hwirq;
|
||||
|
||||
if (!chip || !chip->hwirq_set_affinity || !num_hwirq ||
|
||||
!write_msi || !callback || !out_first_hwirq)
|
||||
return SBI_EINVAL;
|
||||
if (chip->num_hwirq < num_hwirq)
|
||||
return SBI_EBAD_RANGE;
|
||||
|
||||
hwirq = 0;
|
||||
found = false;
|
||||
sbi_list_for_each_entry(h, &chip->handler_list, node) {
|
||||
if (h->first_hwirq <= hwirq && hwirq < (h->first_hwirq + h->num_hwirq)) {
|
||||
hwirq = h->first_hwirq + h->num_hwirq;
|
||||
} else if (hwirq < h->first_hwirq) {
|
||||
if (h->first_hwirq - hwirq < num_hwirq) {
|
||||
found = true;
|
||||
break;
|
||||
} else {
|
||||
hwirq = h->first_hwirq + h->num_hwirq;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found && !hwirq)
|
||||
found = true;
|
||||
if (!found)
|
||||
return SBI_ENOSPC;
|
||||
*out_first_hwirq = hwirq;
|
||||
|
||||
return __sbi_irqchip_register_handler(chip, *out_first_hwirq,
|
||||
num_hwirq, SBI_HWIRQ_FLAGS_NONE,
|
||||
write_msi, callback, priv);
|
||||
}
|
||||
|
||||
int sbi_irqchip_register_handler(struct sbi_irqchip_device *chip,
|
||||
u32 first_hwirq, u32 num_hwirq, u32 hwirq_flags,
|
||||
int (*callback)(u32 hwirq, void *priv), void *priv)
|
||||
@@ -292,7 +359,7 @@ int sbi_irqchip_register_handler(struct sbi_irqchip_device *chip,
|
||||
return SBI_EBAD_RANGE;
|
||||
|
||||
return __sbi_irqchip_register_handler(chip, first_hwirq, num_hwirq, hwirq_flags,
|
||||
callback, priv);
|
||||
NULL, callback, priv);
|
||||
}
|
||||
|
||||
int sbi_irqchip_register_reserved(struct sbi_irqchip_device *chip,
|
||||
@@ -305,7 +372,7 @@ int sbi_irqchip_register_reserved(struct sbi_irqchip_device *chip,
|
||||
return SBI_EBAD_RANGE;
|
||||
|
||||
return __sbi_irqchip_register_handler(chip, first_hwirq, num_hwirq,
|
||||
SBI_HWIRQ_FLAGS_NONE, NULL, NULL);
|
||||
SBI_HWIRQ_FLAGS_NONE, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
int sbi_irqchip_unregister_handler(struct sbi_irqchip_device *chip,
|
||||
|
||||
Reference in New Issue
Block a user