mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:24:47 +01:00
This was done entirely with mindless brute force, using
git grep -l '\<k[vmz]*alloc_objs*(.*, GFP_KERNEL)' |
xargs sed -i 's/\(alloc_objs*(.*\), GFP_KERNEL)/\1)/'
to convert the new alloc_obj() users that had a simple GFP_KERNEL
argument to just drop that argument.
Note that due to the extreme simplicity of the scripting, any slightly
more complex cases spread over multiple lines would not be triggered:
they definitely exist, but this covers the vast bulk of the cases, and
the resulting diff is also then easier to check automatically.
For the same reason the 'flex' versions will be done as a separate
conversion.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
150 lines
3.1 KiB
C
150 lines
3.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (C) 2020, Jiaxun Yang <jiaxun.yang@flygoat.com>
|
|
* Loongson HTPIC IRQ support
|
|
*/
|
|
|
|
#include <linux/init.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/of_irq.h>
|
|
#include <linux/irqchip.h>
|
|
#include <linux/irqchip/chained_irq.h>
|
|
#include <linux/irq.h>
|
|
#include <linux/io.h>
|
|
#include <linux/syscore_ops.h>
|
|
|
|
#include <asm/i8259.h>
|
|
|
|
#define HTPIC_MAX_PARENT_IRQ 4
|
|
#define HTINT_NUM_VECTORS 8
|
|
#define HTINT_EN_OFF 0x20
|
|
|
|
struct loongson_htpic {
|
|
void __iomem *base;
|
|
struct irq_domain *domain;
|
|
};
|
|
|
|
static struct loongson_htpic *htpic;
|
|
|
|
static void htpic_irq_dispatch(struct irq_desc *desc)
|
|
{
|
|
struct loongson_htpic *priv = irq_desc_get_handler_data(desc);
|
|
struct irq_chip *chip = irq_desc_get_chip(desc);
|
|
uint32_t pending;
|
|
|
|
chained_irq_enter(chip, desc);
|
|
pending = readl(priv->base);
|
|
/* Ack all IRQs at once, otherwise IRQ flood might happen */
|
|
writel(pending, priv->base);
|
|
|
|
if (!pending)
|
|
spurious_interrupt();
|
|
|
|
while (pending) {
|
|
int bit = __ffs(pending);
|
|
|
|
if (unlikely(bit > 15)) {
|
|
spurious_interrupt();
|
|
break;
|
|
}
|
|
|
|
generic_handle_domain_irq(priv->domain, bit);
|
|
pending &= ~BIT(bit);
|
|
}
|
|
chained_irq_exit(chip, desc);
|
|
}
|
|
|
|
static void htpic_reg_init(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < HTINT_NUM_VECTORS; i++) {
|
|
/* Disable all HT Vectors */
|
|
writel(0x0, htpic->base + HTINT_EN_OFF + i * 0x4);
|
|
/* Read back to force write */
|
|
(void) readl(htpic->base + i * 0x4);
|
|
/* Ack all possible pending IRQs */
|
|
writel(GENMASK(31, 0), htpic->base + i * 0x4);
|
|
}
|
|
|
|
/* Enable 16 vectors for PIC */
|
|
writel(0xffff, htpic->base + HTINT_EN_OFF);
|
|
}
|
|
|
|
static void htpic_resume(void *data)
|
|
{
|
|
htpic_reg_init();
|
|
}
|
|
|
|
static const struct syscore_ops htpic_syscore_ops = {
|
|
.resume = htpic_resume,
|
|
};
|
|
|
|
static struct syscore htpic_syscore = {
|
|
.ops = &htpic_syscore_ops,
|
|
};
|
|
|
|
static int __init htpic_of_init(struct device_node *node, struct device_node *parent)
|
|
{
|
|
unsigned int parent_irq[4];
|
|
int i, err;
|
|
int num_parents = 0;
|
|
|
|
if (htpic) {
|
|
pr_err("loongson-htpic: Only one HTPIC is allowed in the system\n");
|
|
return -ENODEV;
|
|
}
|
|
|
|
htpic = kzalloc_obj(*htpic);
|
|
if (!htpic)
|
|
return -ENOMEM;
|
|
|
|
htpic->base = of_iomap(node, 0);
|
|
if (!htpic->base) {
|
|
err = -ENODEV;
|
|
goto out_free;
|
|
}
|
|
|
|
htpic->domain = __init_i8259_irqs(node);
|
|
if (!htpic->domain) {
|
|
pr_err("loongson-htpic: Failed to initialize i8259 IRQs\n");
|
|
err = -ENOMEM;
|
|
goto out_iounmap;
|
|
}
|
|
|
|
/* Interrupt may come from any of the 4 interrupt line */
|
|
for (i = 0; i < HTPIC_MAX_PARENT_IRQ; i++) {
|
|
parent_irq[i] = irq_of_parse_and_map(node, i);
|
|
if (parent_irq[i] <= 0)
|
|
break;
|
|
|
|
num_parents++;
|
|
}
|
|
|
|
if (!num_parents) {
|
|
pr_err("loongson-htpic: Failed to get parent irqs\n");
|
|
err = -ENODEV;
|
|
goto out_remove_domain;
|
|
}
|
|
|
|
htpic_reg_init();
|
|
|
|
for (i = 0; i < num_parents; i++) {
|
|
irq_set_chained_handler_and_data(parent_irq[i],
|
|
htpic_irq_dispatch, htpic);
|
|
}
|
|
|
|
register_syscore(&htpic_syscore);
|
|
|
|
return 0;
|
|
|
|
out_remove_domain:
|
|
irq_domain_remove(htpic->domain);
|
|
out_iounmap:
|
|
iounmap(htpic->base);
|
|
out_free:
|
|
kfree(htpic);
|
|
return err;
|
|
}
|
|
|
|
IRQCHIP_DECLARE(loongson_htpic, "loongson,htpic-1.0", htpic_of_init);
|