Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1911829
  • 博文数量: 376
  • 博客积分: 2147
  • 博客等级: 大尉
  • 技术积分: 3642
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-06 10:47
文章分类

全部博文(376)

文章存档

2019年(3)

2017年(28)

2016年(15)

2015年(17)

2014年(182)

2013年(16)

2012年(115)

我的朋友

分类: 嵌入式

2013-03-20 11:08:16

//arch/powerpc/platforms/85xx/p1010rdb.c
void __init p1010_rdb_pic_init(void)
{
    struct mpic *mpic;
    struct resource r;
    struct device_node *np;

    np = of_find_node_by_type(NULL, "open-pic");//查找pic设备节点
    if (np == NULL) {
        printk(KERN_ERR "Could not find open-pic node\n");
        return;
    }

    if (of_address_to_resource(np, 0, &r)) {//把设备节点信息保存到r中
        printk(KERN_ERR "Failed to map mpic register space\n");
        of_node_put(np);
        return;
    }

    mpic = mpic_alloc(np, r.start, MPIC_PRIMARY | MPIC_WANTS_RESET |
      MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS | MPIC_SINGLE_DEST_CPU,
      0, 256, " OpenPIC  ");

    BUG_ON(mpic == NULL);
    of_node_put(np);

    mpic_init(mpic);

}
//arch/powerpc/sysdev/mpic.c
struct mpic * __init mpic_alloc(struct device_node *node,
                phys_addr_t phys_addr,
                unsigned int flags,
                unsigned int isu_size,
                unsigned int irq_count,
                const char *name)
{
    struct mpic    *mpic;
    u32        greg_feature;
    const char    *vers;
    int        i;
    int        intvec_top;
    u64        paddr = phys_addr;

    mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL);//分配mpic结构
    if (mpic == NULL)
        return NULL;

    mpic->name = name;

    mpic->hc_irq = mpic_irq_chip;//指向具体的芯片irq结构体
    mpic->hc_irq.name = name;
    if (flags & MPIC_PRIMARY)
        mpic->hc_irq.set_affinity = mpic_set_affinity;
#ifdef CONFIG_MPIC_U3_HT_IRQS
    mpic->hc_ht_irq = mpic_irq_ht_chip;
    mpic->hc_ht_irq.name = name;
    if (flags & MPIC_PRIMARY)
        mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
#endif /* CONFIG_MPIC_U3_HT_IRQS */

#ifdef CONFIG_SMP
    mpic->hc_ipi = mpic_ipi_chip;
    mpic->hc_ipi.name = name;
#endif /* CONFIG_SMP */

    mpic->hc_tm = mpic_tm_chip;
    mpic->hc_tm.typename = name;

    mpic->flags = flags;
    mpic->isu_size = isu_size;
    mpic->irq_count = irq_count;//256个中断向量
    mpic->num_sources = 0; /* so far */

    if (flags & MPIC_LARGE_VECTORS)//无MPIC_LARGE_VECTORS标志
        intvec_top = 2047;
    else
        intvec_top = 255;

    mpic->timer_vecs[0] = intvec_top - 8;//247
    mpic->timer_vecs[1] = intvec_top - 7;
    mpic->timer_vecs[2] = intvec_top - 6;
    mpic->timer_vecs[3] = intvec_top - 5;
    mpic->ipi_vecs[0]   = intvec_top - 4;
    mpic->ipi_vecs[1]   = intvec_top - 3;
    mpic->ipi_vecs[2]   = intvec_top - 2;
    mpic->ipi_vecs[3]   = intvec_top - 1;
    mpic->spurious_vec  = intvec_top;//255

    /* Check for "big-endian" in device-tree */
    if (node && of_get_property(node, "big-endian", NULL) != NULL)
        mpic->flags |= MPIC_BIG_ENDIAN;

    /* Look for protected sources */
    if (node) {
        int psize;
        unsigned int bits, mapsize;
        const u32 *psrc =
            of_get_property(node, "protected-sources", &psize);//dts文件没有protected-sources属性
        if (psrc) {
            psize /= 4;
            bits = intvec_top + 1;
            mapsize = BITS_TO_LONGS(bits) * sizeof(unsigned long);
            mpic->protected = kzalloc(mapsize, GFP_KERNEL);
            BUG_ON(mpic->protected == NULL);
            for (i = 0; i < psize; i++) {
                if (psrc[i] > intvec_top)
                    continue;
                __set_bit(psrc[i], mpic->protected);
            }
        }
    }

#ifdef CONFIG_MPIC_WEIRD
    mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)];
#endif

    /* default register type */
    mpic->reg_type = (flags & MPIC_BIG_ENDIAN) ?
        mpic_access_mmio_be : mpic_access_mmio_le;//大端

    /* If no physical address is passed in, a device-node is mandatory */
    BUG_ON(paddr == 0 && node == NULL);

    /* If no physical address passed in, check if it's dcr based */
    if (paddr == 0 && of_get_property(node, "dcr-reg", NULL) != NULL) {
#ifdef CONFIG_PPC_DCR
        mpic->flags |= MPIC_USES_DCR;
        mpic->reg_type = mpic_access_dcr;
#else
        BUG();
#endif /* CONFIG_PPC_DCR */
    }

    /* If the MPIC is not DCR based, and no physical address was passed
     * in, try to obtain one
     */
    if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) {
        const u32 *reg = of_get_property(node, "reg", NULL);
        BUG_ON(reg == NULL);
        paddr = of_translate_address(node, reg);
        BUG_ON(paddr == OF_BAD_ADDR);
    }

    /* Map the global registers */
    mpic_map(mpic, node, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000);//MPIC_GREG_BASE为0x01000,所以从偏移量映射MPIC_GREG_BASE映射4K空间,其实就是从PIC_FRR开始
    mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);//MPIC_TIMER_BASE为 0x01100,所以从偏移量映射MPIC_TIMER_BASE映射4K空间,其实就是从PIC_GTCCRAN开始

    /* Reset */
    if (flags & MPIC_WANTS_RESET) {
        mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
               mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
               | MPIC_GREG_GCONF_RESET);//对PIC进行软复位
        while( mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
               & MPIC_GREG_GCONF_RESET)
            mb();
    }

    /* CoreInt */
    if (flags & MPIC_ENABLE_COREINT)//没定义
        mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
               mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
               | MPIC_GREG_GCONF_COREINT);

    if (flags & MPIC_ENABLE_MCK)//没定义
        mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
               mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
               | MPIC_GREG_GCONF_MCK);

    /* Read feature register, calculate num CPUs and, for non-ISU
     * MPICs, num sources as well. On ISU MPICs, sources are counted
     * as ISUs are added
     */
    greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
    mpic->num_cpus = ((greg_feature & MPIC_GREG_FEATURE_LAST_CPU_MASK)
              >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;//p1010一个CPU
    if (isu_size == 0) {
        if (flags & MPIC_BROKEN_FRR_NIRQS)//条件为真
            mpic->num_sources = mpic->irq_count;//256个中断源
        else
            mpic->num_sources =
                ((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
                 >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
    }

    /* Map the per-CPU registers */
    for (i = 0; i < mpic->num_cpus; i++) {
        mpic_map(mpic, node, paddr, &mpic->cpuregs[i],
             MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE),
             0x1000);//MPIC_CPU_BASE为0x20000,所以从偏移量映射MPIC_CPU_BASE映射4K空间

    }

    /* Initialize main ISU if none provided */
    if (mpic->isu_size == 0) {
        mpic->isu_size = mpic->num_sources;//设置size为256
        mpic_map(mpic, node, paddr, &mpic->isus[0],
             MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);//MPIC_IRQ_BASE为0x10000,所以从偏移量映射MPIC_IRQ_BASE映射MPIC_INFO(IRQ_STRIDE) * mpic->isu_size (0x20*256)空间,其实就是从PIC_EIVPRn开始
    }
    mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);//isu_shift为8
    mpic->isu_mask = (1 << mpic->isu_shift) - 1;//isu_mask为0xff

    mpic->irqhost = irq_alloc_host(node, IRQ_HOST_MAP_LINEAR,
                       isu_size ? isu_size : mpic->num_sources,
                       &mpic_host_ops,
                       flags & MPIC_LARGE_VECTORS ? 2048 : 256);
    if (mpic->irqhost == NULL)
        return NULL;

    mpic->irqhost->host_data = mpic;

    /* Display version */
    switch (greg_feature & MPIC_GREG_FEATURE_VERSION_MASK) {
    case 1:
        vers = "1.0";
        break;
    case 2:
        vers = "1.2";
        break;
    case 3:
        vers = "1.3";
        break;
    default:
        vers = "";
        break;
    }
    printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx,"
           " max %d CPUs\n",
           name, vers, (unsigned long long)paddr, mpic->num_cpus);
    printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n",
           mpic->isu_size, mpic->isu_shift, mpic->isu_mask);

    mpic->next = mpics;//mpic 挂入全局链表
    mpics = mpic;

    if (flags & MPIC_PRIMARY) {
        mpic_primary = mpic;
        irq_set_default_host(mpic->irqhost);
    }

    return mpic;
}

//arch/powerpc/sysdev/mpic.c
void __init mpic_init(struct mpic *mpic)
{
    int i;
    int cpu;

    BUG_ON(mpic->num_sources == 0);

    printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources);

    /* Set current processor priority to max */
    mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf);//MPIC_CPU_CURRENT_TASK_PRI为0x00080,基地址为0x20000,所以其实就是PIC_CTPR_CPU寄存器,既设置当前任务优先级寄存器的优先级最高0x0f

    /* Initialize timers to our reserved vectors and mask them for now */
    for (i = 0; i < 4; i++) {
        mpic_write(mpic->tmregs,
               i * MPIC_INFO(TIMER_STRIDE) +
               MPIC_INFO(TIMER_DESTINATION),
               1 << hard_smp_processor_id());//设置PIC_GTDRAn寄存器,让TIMER中断递交给CPU CORE
        mpic_write(mpic->tmregs,
               i * MPIC_INFO(TIMER_STRIDE) +
               MPIC_INFO(TIMER_VECTOR_PRI),
               MPIC_VECPRI_MASK |
               (9 << MPIC_VECPRI_PRIORITY_SHIFT) |
               (mpic->timer_vecs[0] + i));//设置TIMER中断优先级以及中断向量
    }

    /* Initialize IPIs to our reserved vectors and mark them disabled for now */
    mpic_test_broken_ipi(mpic);
    for (i = 0; i < 4; i++) {
        mpic_ipi_write(i,
                   MPIC_VECPRI_MASK |
                   (10 << MPIC_VECPRI_PRIORITY_SHIFT) |
                   (mpic->ipi_vecs[0] + i));
    }

    /* Initialize interrupt sources */
    if (mpic->irq_count == 0)
        mpic->irq_count = mpic->num_sources;//256

    /* Do the HT PIC fixups on U3 broken mpic */
    DBG("MPIC flags: %x\n", mpic->flags);
    if ((mpic->flags & MPIC_U3_HT_IRQS) && (mpic->flags & MPIC_PRIMARY)) {//假
        mpic_scan_ht_pics(mpic);
        mpic_u3msi_init(mpic);
    }

    mpic_pasemi_msi_init(mpic);

    if (mpic->flags & MPIC_PRIMARY)
        cpu = hard_smp_processor_id();
    else
        cpu = 0;

    for (i = 0; i < mpic->num_sources; i++) {
        /* start with vector = source number, and masked */
        u32 vecpri = MPIC_VECPRI_MASK | i |
            (8 << MPIC_VECPRI_PRIORITY_SHIFT);//设置中断优先级和中断向量
        
        /* check if protected */
        if (mpic->protected && test_bit(i, mpic->protected))//假
            continue;
        /* init hw */
        mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);//设置外部和内部中断的向量和优先级
        mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
    }
    
    /* Init spurious vector */
    mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), mpic->spurious_vec);//初始化伪中断向量为255

    /* Disable 8259 passthrough, if supported */
    if (!(mpic->flags & MPIC_NO_PTHROU_DIS))//假
        mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
               mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
               | MPIC_GREG_GCONF_8259_PTHROU_DIS);

    if (mpic->flags & MPIC_NO_BIAS)//假
        mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
            mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
            | MPIC_GREG_GCONF_NO_BIAS);

    /* Set current processor priority to 0 */
    mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);//设置当前任务优先级为最低值0

#ifdef CONFIG_PM
    /* allocate memory to save mpic state */
    mpic->save_data = kmalloc(mpic->num_sources * sizeof(*mpic->save_data),
                  GFP_KERNEL);
    BUG_ON(mpic->save_data == NULL);
#endif
}

阅读(1172) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~