⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 intc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
static intc_enum __init intc_grp_id(struct intc_desc *desc,				    intc_enum enum_id){	struct intc_group *g = desc->groups;	unsigned int i, j;	for (i = 0; g && enum_id && i < desc->nr_groups; i++) {		g = desc->groups + i;		for (j = 0; g->enum_ids[j]; j++) {			if (g->enum_ids[j] != enum_id)				continue;			return g->enum_id;		}	}	return 0;}static unsigned int __init intc_prio_value(struct intc_desc *desc,					   intc_enum enum_id, int do_grps){	struct intc_prio *p = desc->priorities;	unsigned int i;	for (i = 0; p && enum_id && i < desc->nr_priorities; i++) {		p = desc->priorities + i;		if (p->enum_id != enum_id)			continue;		return p->priority;	}	if (do_grps)		return intc_prio_value(desc, intc_grp_id(desc, enum_id), 0);	/* default to the lowest priority possible if no priority is set	 * - this needs to be at least 2 for 5-bit priorities on 7780	 */	return 2;}static unsigned int __init intc_mask_data(struct intc_desc *desc,					  struct intc_desc_int *d,					  intc_enum enum_id, int do_grps){	struct intc_mask_reg *mr = desc->mask_regs;	unsigned int i, j, fn, mode;	unsigned long reg_e, reg_d;	for (i = 0; mr && enum_id && i < desc->nr_mask_regs; i++) {		mr = desc->mask_regs + i;		for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {			if (mr->enum_ids[j] != enum_id)				continue;			if (mr->set_reg && mr->clr_reg) {				fn = REG_FN_WRITE_BASE;				mode = MODE_DUAL_REG;				reg_e = mr->clr_reg;				reg_d = mr->set_reg;			} else {				fn = REG_FN_MODIFY_BASE;				if (mr->set_reg) {					mode = MODE_ENABLE_REG;					reg_e = mr->set_reg;					reg_d = mr->set_reg;				} else {					mode = MODE_MASK_REG;					reg_e = mr->clr_reg;					reg_d = mr->clr_reg;				}			}			fn += (mr->reg_width >> 3) - 1;			return _INTC_MK(fn, mode,					intc_get_reg(d, reg_e),					intc_get_reg(d, reg_d),					1,					(mr->reg_width - 1) - j);		}	}	if (do_grps)		return intc_mask_data(desc, d, intc_grp_id(desc, enum_id), 0);	return 0;}static unsigned int __init intc_prio_data(struct intc_desc *desc,					  struct intc_desc_int *d,					  intc_enum enum_id, int do_grps){	struct intc_prio_reg *pr = desc->prio_regs;	unsigned int i, j, fn, mode, bit;	unsigned long reg_e, reg_d;	for (i = 0; pr && enum_id && i < desc->nr_prio_regs; i++) {		pr = desc->prio_regs + i;		for (j = 0; j < ARRAY_SIZE(pr->enum_ids); j++) {			if (pr->enum_ids[j] != enum_id)				continue;			if (pr->set_reg && pr->clr_reg) {				fn = REG_FN_WRITE_BASE;				mode = MODE_PCLR_REG;				reg_e = pr->set_reg;				reg_d = pr->clr_reg;			} else {				fn = REG_FN_MODIFY_BASE;				mode = MODE_PRIO_REG;				if (!pr->set_reg)					BUG();				reg_e = pr->set_reg;				reg_d = pr->set_reg;			}			fn += (pr->reg_width >> 3) - 1;			bit = pr->reg_width - ((j + 1) * pr->field_width);			BUG_ON(bit < 0);			return _INTC_MK(fn, mode,					intc_get_reg(d, reg_e),					intc_get_reg(d, reg_d),					pr->field_width, bit);		}	}	if (do_grps)		return intc_prio_data(desc, d, intc_grp_id(desc, enum_id), 0);	return 0;}static unsigned int __init intc_sense_data(struct intc_desc *desc,					   struct intc_desc_int *d,					   intc_enum enum_id){	struct intc_sense_reg *sr = desc->sense_regs;	unsigned int i, j, fn, bit;	for (i = 0; sr && enum_id && i < desc->nr_sense_regs; i++) {		sr = desc->sense_regs + i;		for (j = 0; j < ARRAY_SIZE(sr->enum_ids); j++) {			if (sr->enum_ids[j] != enum_id)				continue;			fn = REG_FN_MODIFY_BASE;			fn += (sr->reg_width >> 3) - 1;			bit = sr->reg_width - ((j + 1) * sr->field_width);			BUG_ON(bit < 0);			return _INTC_MK(fn, 0, intc_get_reg(d, sr->reg),					0, sr->field_width, bit);		}	}	return 0;}static void __init intc_register_irq(struct intc_desc *desc,				     struct intc_desc_int *d,				     intc_enum enum_id,				     unsigned int irq){	struct intc_handle_int *hp;	unsigned int data[2], primary;	/* Prefer single interrupt source bitmap over other combinations:	 * 1. bitmap, single interrupt source	 * 2. priority, single interrupt source	 * 3. bitmap, multiple interrupt sources (groups)	 * 4. priority, multiple interrupt sources (groups)	 */	data[0] = intc_mask_data(desc, d, enum_id, 0);	data[1] = intc_prio_data(desc, d, enum_id, 0);	primary = 0;	if (!data[0] && data[1])		primary = 1;	data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1);	data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1);	if (!data[primary])		primary ^= 1;	BUG_ON(!data[primary]); /* must have primary masking method */	disable_irq_nosync(irq);	set_irq_chip_and_handler_name(irq, &d->chip,				      handle_level_irq, "level");	set_irq_chip_data(irq, (void *)data[primary]);	/* record the desired priority level */	intc_prio_level[irq] = intc_prio_value(desc, enum_id, 1);	/* enable secondary masking method if present */	if (data[!primary])		_intc_enable(irq, data[!primary]);	/* add irq to d->prio list if priority is available */	if (data[1]) {		hp = d->prio + d->nr_prio;		hp->irq = irq;		hp->handle = data[1];		if (primary) {			/*			 * only secondary priority should access registers, so			 * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority()			 */			hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0);			hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0);		}		d->nr_prio++;	}	/* add irq to d->sense list if sense is available */	data[0] = intc_sense_data(desc, d, enum_id);	if (data[0]) {		(d->sense + d->nr_sense)->irq = irq;		(d->sense + d->nr_sense)->handle = data[0];		d->nr_sense++;	}	/* irq should be disabled by default */	d->chip.mask(irq);}static unsigned int __init save_reg(struct intc_desc_int *d,				    unsigned int cnt,				    unsigned long value,				    unsigned int smp){	if (value) {		d->reg[cnt] = value;#ifdef CONFIG_SMP		d->smp[cnt] = smp;#endif		return 1;	}	return 0;}void __init register_intc_controller(struct intc_desc *desc){	unsigned int i, k, smp;	struct intc_desc_int *d;	d = alloc_bootmem(sizeof(*d));	d->nr_reg = desc->mask_regs ? desc->nr_mask_regs * 2 : 0;	d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0;	d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0;	d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg));#ifdef CONFIG_SMP	d->smp = alloc_bootmem(d->nr_reg * sizeof(*d->smp));#endif	k = 0;	if (desc->mask_regs) {		for (i = 0; i < desc->nr_mask_regs; i++) {			smp = IS_SMP(desc->mask_regs[i]);			k += save_reg(d, k, desc->mask_regs[i].set_reg, smp);			k += save_reg(d, k, desc->mask_regs[i].clr_reg, smp);		}	}	if (desc->prio_regs) {		d->prio = alloc_bootmem(desc->nr_vectors * sizeof(*d->prio));		for (i = 0; i < desc->nr_prio_regs; i++) {			smp = IS_SMP(desc->prio_regs[i]);			k += save_reg(d, k, desc->prio_regs[i].set_reg, smp);			k += save_reg(d, k, desc->prio_regs[i].clr_reg, smp);		}	}	if (desc->sense_regs) {		d->sense = alloc_bootmem(desc->nr_vectors * sizeof(*d->sense));		for (i = 0; i < desc->nr_sense_regs; i++) {			k += save_reg(d, k, desc->sense_regs[i].reg, 0);		}	}	BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */	d->chip.name = desc->name;	d->chip.mask = intc_disable;	d->chip.unmask = intc_enable;	d->chip.mask_ack = intc_disable;	d->chip.set_type = intc_set_sense;	for (i = 0; i < desc->nr_vectors; i++) {		struct intc_vect *vect = desc->vectors + i;		intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect));	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -