Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 96292
b: refs/heads/master
c: d58876e
h: refs/heads/master
v: v3
  • Loading branch information
Magnus Damm authored and Paul Mundt committed May 8, 2008
1 parent b81c6a8 commit acb6d99
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 8 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a276e588a92737889c21e736f2bbed8aecda25fb
refs/heads/master: d58876e289b0153bf86162aa1a43249e0f0aa03d
79 changes: 76 additions & 3 deletions trunk/arch/sh/kernel/cpu/irq/intc.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Shared interrupt handling code for IPR and INTC2 types of IRQs.
*
* Copyright (C) 2007 Magnus Damm
* Copyright (C) 2007, 2008 Magnus Damm
*
* Based on intc2.c and ipr.c
*
Expand Down Expand Up @@ -62,6 +62,9 @@ struct intc_desc_int {
#endif

static unsigned int intc_prio_level[NR_IRQS]; /* for now */
#ifdef CONFIG_CPU_SH3
static unsigned long ack_handle[NR_IRQS];
#endif

static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
{
Expand Down Expand Up @@ -219,6 +222,25 @@ static void intc_disable(unsigned int irq)
}
}

#ifdef CONFIG_CPU_SH3
static void intc_mask_ack(unsigned int irq)
{
struct intc_desc_int *d = get_intc_desc(irq);
unsigned long handle = ack_handle[irq];
unsigned long addr;

intc_disable(irq);

/* read register and write zero only to the assocaited bit */

if (handle) {
addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
ctrl_inb(addr);
ctrl_outb(0x3f ^ set_field(0, 1, handle), addr);
}
}
#endif

static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
unsigned int nr_hp,
unsigned int irq)
Expand Down Expand Up @@ -430,6 +452,40 @@ static unsigned int __init intc_prio_data(struct intc_desc *desc,
return 0;
}

#ifdef CONFIG_CPU_SH3
static unsigned int __init intc_ack_data(struct intc_desc *desc,
struct intc_desc_int *d,
intc_enum enum_id)
{
struct intc_mask_reg *mr = desc->ack_regs;
unsigned int i, j, fn, mode;
unsigned long reg_e, reg_d;

for (i = 0; mr && enum_id && i < desc->nr_ack_regs; i++) {
mr = desc->ack_regs + i;

for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
if (mr->enum_ids[j] != enum_id)
continue;

fn = REG_FN_MODIFY_BASE;
mode = MODE_ENABLE_REG;
reg_e = mr->set_reg;
reg_d = mr->set_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);
}
}

return 0;
}
#endif

static unsigned int __init intc_sense_data(struct intc_desc *desc,
struct intc_desc_int *d,
intc_enum enum_id)
Expand Down Expand Up @@ -530,6 +586,11 @@ static void __init intc_register_irq(struct intc_desc *desc,

/* irq should be disabled by default */
d->chip.mask(irq);

#ifdef CONFIG_CPU_SH3
if (desc->ack_regs)
ack_handle[irq] = intc_ack_data(desc, d, enum_id);
#endif
}

static unsigned int __init save_reg(struct intc_desc_int *d,
Expand Down Expand Up @@ -560,6 +621,9 @@ void __init register_intc_controller(struct intc_desc *desc)
d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0;
d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0;

#ifdef CONFIG_CPU_SH3
d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0;
#endif
d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg));
#ifdef CONFIG_SMP
d->smp = alloc_bootmem(d->nr_reg * sizeof(*d->smp));
Expand Down Expand Up @@ -592,14 +656,23 @@ void __init register_intc_controller(struct intc_desc *desc)
}
}

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;

#ifdef CONFIG_CPU_SH3
if (desc->ack_regs) {
for (i = 0; i < desc->nr_ack_regs; i++)
k += save_reg(d, k, desc->ack_regs[i].set_reg, 0);

d->chip.mask_ack = intc_mask_ack;
}
#endif

BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */

for (i = 0; i < desc->nr_vectors; i++) {
struct intc_vect *vect = desc->vectors + i;

Expand Down
15 changes: 11 additions & 4 deletions trunk/arch/sh/kernel/cpu/sh3/setup-sh3.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,22 @@ static struct intc_prio_reg prio_registers[] __initdata = {
{ 0xa4000018, 0, 16, 4, /* IPRD */ { 0, 0, IRQ5, IRQ4 } },
};

static struct intc_mask_reg ack_registers[] __initdata = {
{ 0xa4000004, 0, 8, /* IRR0 */
{ 0, 0, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 } },
};

static struct intc_sense_reg sense_registers[] __initdata = {
{ 0xa4000010, 16, 2, { 0, 0, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 } },
};

static DECLARE_INTC_DESC(intc_desc_irq0123, "sh3-irq0123", vectors_irq0123,
NULL, NULL, prio_registers, sense_registers);
static DECLARE_INTC_DESC_ACK(intc_desc_irq0123, "sh3-irq0123",
vectors_irq0123, NULL, NULL,
prio_registers, sense_registers, ack_registers);

static DECLARE_INTC_DESC(intc_desc_irq45, "sh3-irq45", vectors_irq45,
NULL, NULL, prio_registers, sense_registers);
static DECLARE_INTC_DESC_ACK(intc_desc_irq45, "sh3-irq45",
vectors_irq45, NULL, NULL,
prio_registers, sense_registers, ack_registers);

#define INTC_ICR1 0xa4000010UL
#define INTC_ICR1_IRQLVL (1<<14)
Expand Down
16 changes: 16 additions & 0 deletions trunk/include/asm-sh/hw_irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ struct intc_desc {
struct intc_sense_reg *sense_regs;
unsigned int nr_sense_regs;
char *name;
#ifdef CONFIG_CPU_SH3
struct intc_mask_reg *ack_regs;
unsigned int nr_ack_regs;
#endif
};

#define _INTC_ARRAY(a) a, sizeof(a)/sizeof(*a)
Expand All @@ -91,6 +95,18 @@ struct intc_desc symbol __initdata = { \
chipname, \
}

#ifdef CONFIG_CPU_SH3
#define DECLARE_INTC_DESC_ACK(symbol, chipname, vectors, groups, \
mask_regs, prio_regs, sense_regs, ack_regs) \
struct intc_desc symbol __initdata = { \
_INTC_ARRAY(vectors), _INTC_ARRAY(groups), \
_INTC_ARRAY(mask_regs), _INTC_ARRAY(prio_regs), \
_INTC_ARRAY(sense_regs), \
chipname, \
_INTC_ARRAY(ack_regs), \
}
#endif

void __init register_intc_controller(struct intc_desc *desc);
int intc_set_priority(unsigned int irq, unsigned int prio);

Expand Down

0 comments on commit acb6d99

Please sign in to comment.