//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) |