JJJ-3 gic_of_init 和 imx_gpc_init

1、gic_of_init

static int __init gic_of_init(struct device_node *node, struct device_node *parent)
{
    void __iomem *dist_base;
    struct redist_region *rdist_regs;
    u64 redist_stride;
    u32 nr_redist_regions;
    u32 typer;
    u32 reg;
    int gic_irqs;
    int err;
    int i;

    dist_base = of_iomap(node, 0);
    if (!dist_base) {
        pr_err("%s: unable to map gic dist registers\n",
            node->full_name);
        return -ENXIO;
    }

    reg = readl_relaxed(dist_base + GICD_PIDR2) & GIC_PIDR2_ARCH_MASK;
    if (reg != GIC_PIDR2_ARCH_GICv3 && reg != GIC_PIDR2_ARCH_GICv4) {
        pr_err("%s: no distributor detected, giving up\n",
            node->full_name);
        err = -ENODEV;
        goto out_unmap_dist;
    }

    if (of_property_read_u32(node, "#redistributor-regions", &nr_redist_regions)) {
        pr_err("irq_test:%s:%d:nr_redist_regions=%d\n", __func__, __LINE__, nr_redist_regions);
	}

	rdist_regs = kzalloc(sizeof(*rdist_regs) * nr_redist_regions, GFP_KERNEL);
    if (!rdist_regs) {
        err = -ENOMEM;
        goto out_unmap_dist;
    }

    for (i = 0; i < nr_redist_regions; i++) {
        struct resource res;
        int ret;

        ret = of_address_to_resource(node, 1 + i, &res);
        rdist_regs[i].redist_base = of_iomap(node, 1 + i);
        if (ret || !rdist_regs[i].redist_base) {
            pr_err("%s: couldn't map region %d\n",
                   node->full_name, i);
            err = -ENODEV;
            goto out_unmap_rdist;
        }
        rdist_regs[i].phys_base = res.start;
    }

    if (of_property_read_u64(node, "redistributor-stride", &redist_stride))
        redist_stride = 0;

    gic_data.dist_base = dist_base;
    gic_data.redist_regions = rdist_regs;
    gic_data.nr_redist_regions = nr_redist_regions;

	/*
     * Find out how many interrupts are supported.
     * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
     */
    typer = readl_relaxed(gic_data.dist_base + GICD_TYPER);
    gic_data.rdists.id_bits = GICD_TYPER_ID_BITS(typer);
    gic_irqs = GICD_TYPER_IRQS(typer);
    if (gic_irqs > 1020)
        gic_irqs = 1020;
    gic_data.irq_nr = gic_irqs;

    gic_data.domain = irq_domain_add_tree(node, &gic_irq_domain_ops,
                          &gic_data);
    gic_data.rdists.rdist = alloc_percpu(typeof(*gic_data.rdists.rdist));

    if (WARN_ON(!gic_data.domain) || WARN_ON(!gic_data.rdists.rdist)) {
        err = -ENOMEM;
        goto out_free;
    }

    set_handle_irq(gic_handle_irq);

	// 这个if不会走到
    if (IS_ENABLED(CONFIG_ARM_GIC_V3_ITS) && gic_dist_supports_lpis())
        its_init(node, &gic_data.rdists, gic_data.domain);

    gic_smp_init();
    gic_dist_init();
    gic_cpu_init();
	gic_cpu_pm_init();

    return 0;

out_free:
    if (gic_data.domain)
        irq_domain_remove(gic_data.domain);
    free_percpu(gic_data.rdists.rdist);
out_unmap_rdist:
    for (i = 0; i < nr_redist_regions; i++)
        if (rdist_regs[i].redist_base)
            iounmap(rdist_regs[i].redist_base);
    kfree(rdist_regs);
out_unmap_dist:
    iounmap(dist_base);
    return err;
}

关于asmlinkage:
看一下/usr/include/asm/linkage.h里面的定义:
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
__attribute__ 是关键字,是gcc的C语言扩展,regparm(0)表示不从寄存器传递参数

如果是 __attribute__((regparm(3))),那么调用函数的时候参数不是通过栈传递,而是直接放到寄存器里,被调用函数直接从寄存器取参数

还有一种是:

#define fastcall __attribute__((regparm(3)))
#define asmlinkage __attribute__((regparm(0)))
函数定义前加宏asmlinkage ,表示这些函数通过堆栈而不是通过寄存器传递参数。
gcc编译器在汇编过程中调用c语言函数时传递参数有两种方法:一种是通过堆栈,另一种是通过寄存器。缺省时采用寄存器,假如你要在你的汇编过程中调用c语言函数,并且想通过堆栈传递参数,你定义的c函数时要在函数前加上宏asmlinkage

看 set_handle_irq

完成一个函数指针赋值的操作
void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
{
    if (handle_arch_irq)
        return;

    handle_arch_irq = handle_irq;
}

看gic_smp_init

static void gic_smp_init(void)
{
	// 设置__smp_cross_call这个函数指针
    set_smp_cross_call(gic_raise_softirq);
    register_cpu_notifier(&gic_cpu_notifier);
}

看gic_dist_init
在gic初始化的gic_dist_init这个函数中,
要让上送cpu的中断负载均衡,可以将cpumask改为想上送的cpu的bit位,
比如cpu有四个核,可以奖cpumask改为oxf;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值