Commit 51da6426 authored by Magnus Damm's avatar Magnus Damm Committed by Paul Mundt

sh: intc - add single bitmap register support

This patch adds single bitmap register support to intc. The current
code only handles 16 and 32 bit registers where a set bit means
interrupt enabled, but this is easy to extend in the future.

The INTC_IRQ() macro is also added to provide a way to hook in
interrupt controllers for FPGAs in boards or companion chips.
Signed-off-by: default avatarMagnus Damm <damm@igel.co.jp>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 2635e855
...@@ -87,40 +87,71 @@ static void enable_prio_32(struct intc_desc *desc, unsigned int data) ...@@ -87,40 +87,71 @@ static void enable_prio_32(struct intc_desc *desc, unsigned int data)
ctrl_outl(set_prio_field(desc, ctrl_inl(addr), prio, data), addr); ctrl_outl(set_prio_field(desc, ctrl_inl(addr), prio, data), addr);
} }
static void disable_mask_8(struct intc_desc *desc, unsigned int data) static void write_set_reg_8(struct intc_desc *desc, unsigned int data)
{ {
ctrl_outb(1 << _INTC_BIT(data), ctrl_outb(1 << _INTC_BIT(data),
_INTC_PTR(desc, mask_regs, data)->set_reg); _INTC_PTR(desc, mask_regs, data)->set_reg);
} }
static void enable_mask_8(struct intc_desc *desc, unsigned int data) static void write_clr_reg_8(struct intc_desc *desc, unsigned int data)
{ {
ctrl_outb(1 << _INTC_BIT(data), ctrl_outb(1 << _INTC_BIT(data),
_INTC_PTR(desc, mask_regs, data)->clr_reg); _INTC_PTR(desc, mask_regs, data)->clr_reg);
} }
static void disable_mask_32(struct intc_desc *desc, unsigned int data) static void write_set_reg_32(struct intc_desc *desc, unsigned int data)
{ {
ctrl_outl(1 << _INTC_BIT(data), ctrl_outl(1 << _INTC_BIT(data),
_INTC_PTR(desc, mask_regs, data)->set_reg); _INTC_PTR(desc, mask_regs, data)->set_reg);
} }
static void enable_mask_32(struct intc_desc *desc, unsigned int data) static void write_clr_reg_32(struct intc_desc *desc, unsigned int data)
{ {
ctrl_outl(1 << _INTC_BIT(data), ctrl_outl(1 << _INTC_BIT(data),
_INTC_PTR(desc, mask_regs, data)->clr_reg); _INTC_PTR(desc, mask_regs, data)->clr_reg);
} }
static void or_set_reg_16(struct intc_desc *desc, unsigned int data)
{
unsigned long addr = _INTC_PTR(desc, mask_regs, data)->set_reg;
ctrl_outw(ctrl_inw(addr) | 1 << _INTC_BIT(data), addr);
}
static void and_set_reg_16(struct intc_desc *desc, unsigned int data)
{
unsigned long addr = _INTC_PTR(desc, mask_regs, data)->set_reg;
ctrl_outw(ctrl_inw(addr) & ~(1 << _INTC_BIT(data)), addr);
}
static void or_set_reg_32(struct intc_desc *desc, unsigned int data)
{
unsigned long addr = _INTC_PTR(desc, mask_regs, data)->set_reg;
ctrl_outl(ctrl_inl(addr) | 1 << _INTC_BIT(data), addr);
}
static void and_set_reg_32(struct intc_desc *desc, unsigned int data)
{
unsigned long addr = _INTC_PTR(desc, mask_regs, data)->set_reg;
ctrl_outl(ctrl_inl(addr) & ~(1 << _INTC_BIT(data)), addr);
}
enum { REG_FN_ERROR=0, enum { REG_FN_ERROR=0,
REG_FN_MASK_8, REG_FN_MASK_32, REG_FN_DUAL_8, REG_FN_DUAL_32,
REG_FN_ENA_16, REG_FN_ENA_32,
REG_FN_PRIO_16, REG_FN_PRIO_32 }; REG_FN_PRIO_16, REG_FN_PRIO_32 };
static struct { static struct {
void (*enable)(struct intc_desc *, unsigned int); void (*enable)(struct intc_desc *, unsigned int);
void (*disable)(struct intc_desc *, unsigned int); void (*disable)(struct intc_desc *, unsigned int);
} intc_reg_fns[] = { } intc_reg_fns[] = {
[REG_FN_MASK_8] = { enable_mask_8, disable_mask_8 }, [REG_FN_DUAL_8] = { write_clr_reg_8, write_set_reg_8 },
[REG_FN_MASK_32] = { enable_mask_32, disable_mask_32 }, [REG_FN_DUAL_32] = { write_clr_reg_32, write_set_reg_32 },
[REG_FN_ENA_16] = { or_set_reg_16, and_set_reg_16 },
[REG_FN_ENA_32] = { or_set_reg_32, and_set_reg_32 },
[REG_FN_PRIO_16] = { enable_prio_16, disable_prio_16 }, [REG_FN_PRIO_16] = { enable_prio_16, disable_prio_16 },
[REG_FN_PRIO_32] = { enable_prio_32, disable_prio_32 }, [REG_FN_PRIO_32] = { enable_prio_32, disable_prio_32 },
}; };
...@@ -218,13 +249,13 @@ static int intc_set_sense(unsigned int irq, unsigned int type) ...@@ -218,13 +249,13 @@ static int intc_set_sense(unsigned int irq, unsigned int type)
return -EINVAL; return -EINVAL;
} }
static unsigned int __init intc_find_mask_handler(unsigned int width) static unsigned int __init intc_find_dual_handler(unsigned int width)
{ {
switch (width) { switch (width) {
case 8: case 8:
return REG_FN_MASK_8; return REG_FN_DUAL_8;
case 32: case 32:
return REG_FN_MASK_32; return REG_FN_DUAL_32;
} }
BUG(); BUG();
...@@ -244,6 +275,19 @@ static unsigned int __init intc_find_prio_handler(unsigned int width) ...@@ -244,6 +275,19 @@ static unsigned int __init intc_find_prio_handler(unsigned int width)
return REG_FN_ERROR; return REG_FN_ERROR;
} }
static unsigned int __init intc_find_ena_handler(unsigned int width)
{
switch (width) {
case 16:
return REG_FN_ENA_16;
case 32:
return REG_FN_ENA_32;
}
BUG();
return REG_FN_ERROR;
}
static intc_enum __init intc_grp_id(struct intc_desc *desc, intc_enum enum_id) static intc_enum __init intc_grp_id(struct intc_desc *desc, intc_enum enum_id)
{ {
struct intc_group *g = desc->groups; struct intc_group *g = desc->groups;
...@@ -301,7 +345,14 @@ static unsigned int __init intc_mask_data(struct intc_desc *desc, ...@@ -301,7 +345,14 @@ static unsigned int __init intc_mask_data(struct intc_desc *desc,
if (mr->enum_ids[j] != enum_id) if (mr->enum_ids[j] != enum_id)
continue; continue;
fn = intc_find_mask_handler(mr->reg_width); switch (mr->clr_reg) {
case 1: /* 1 = enabled interrupt - "enable" register */
fn = intc_find_ena_handler(mr->reg_width);
break;
default:
fn = intc_find_dual_handler(mr->reg_width);
}
if (fn == REG_FN_ERROR) if (fn == REG_FN_ERROR)
return 0; return 0;
......
...@@ -49,6 +49,7 @@ struct intc_vect { ...@@ -49,6 +49,7 @@ struct intc_vect {
}; };
#define INTC_VECT(enum_id, vect) { enum_id, vect } #define INTC_VECT(enum_id, vect) { enum_id, vect }
#define INTC_IRQ(enum_id, irq) INTC_VECT(enum_id, irq2evt(irq))
struct intc_prio { struct intc_prio {
intc_enum enum_id; intc_enum enum_id;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment