Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 62143
b: refs/heads/master
c: 680c459
h: refs/heads/master
i:
  62141: 0f9e6ec
  62139: 05ac103
  62135: 0ad6fcd
  62127: 1e61b91
  62111: 290f12c
  62079: 94a2951
v: v3
  • Loading branch information
Magnus Damm authored and Paul Mundt committed Jul 20, 2007
1 parent 8b4f482 commit 38b0304
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 21 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: d0afa579698f33a65bc5c21d3d667dbb46f9e440
refs/heads/master: 680c45981ae2b4029878806d76aa17bb62d3c674
93 changes: 73 additions & 20 deletions trunk/arch/sh/kernel/cpu/irq/intc.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,30 +244,58 @@ static unsigned int __init intc_find_prio_handler(unsigned int width)
return REG_FN_ERROR;
}

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)
intc_enum enum_id, int do_grps)
{
struct intc_prio *p = desc->priorities;
unsigned int i;

for (i = 0; i < desc->nr_priorities; i++) {
struct intc_prio *p = desc->priorities + 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;
}

return 1; /* default to the lowest priority if no priority is set */
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,
intc_enum enum_id)
intc_enum enum_id, int do_grps)
{
struct intc_mask_reg *mr = desc->mask_regs;
unsigned int i, j, fn;

for (i = 0; i < desc->nr_mask_regs; i++) {
struct intc_mask_reg *mr = desc->mask_regs + i;
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)
Expand All @@ -281,16 +309,20 @@ static unsigned int __init intc_mask_data(struct intc_desc *desc,
}
}

if (do_grps)
return intc_mask_data(desc, intc_grp_id(desc, enum_id), 0);

return 0;
}

static unsigned int __init intc_prio_data(struct intc_desc *desc,
intc_enum enum_id)
intc_enum enum_id, int do_grps)
{
struct intc_prio_reg *pr = desc->prio_regs;
unsigned int i, j, fn, bit, prio;

for (i = 0; i < desc->nr_prio_regs; i++) {
struct intc_prio_reg *pr = desc->prio_regs + i;
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)
Expand All @@ -300,7 +332,7 @@ static unsigned int __init intc_prio_data(struct intc_desc *desc,
if (fn == REG_FN_ERROR)
return 0;

prio = intc_prio_value(desc, enum_id);
prio = intc_prio_value(desc, enum_id, 1);
bit = pr->reg_width - ((j + 1) * pr->field_width);

BUG_ON(bit < 0);
Expand All @@ -309,27 +341,48 @@ static unsigned int __init intc_prio_data(struct intc_desc *desc,
}
}

if (do_grps)
return intc_prio_data(desc, intc_grp_id(desc, enum_id), 0);

return 0;
}

static void __init intc_register_irq(struct intc_desc *desc, intc_enum enum_id,
unsigned int irq)
{
unsigned int mask_data = intc_mask_data(desc, enum_id);
unsigned int prio_data = intc_prio_data(desc, enum_id);
unsigned int data = mask_data ? mask_data : prio_data;
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)
*/

BUG_ON(!data);
data[0] = intc_mask_data(desc, enum_id, 0);
data[1] = intc_prio_data(desc, enum_id, 0);

primary = 0;
if (!data[0] && data[1])
primary = 1;

data[0] = data[0] ? data[0] : intc_mask_data(desc, enum_id, 1);
data[1] = data[1] ? data[1] : intc_prio_data(desc, 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, &desc->chip,
handle_level_irq, "level");
set_irq_chip_data(irq, (void *)data);

/* set priority */
set_irq_chip_data(irq, (void *)data[primary]);

if (prio_data)
intc_reg_fns[_INTC_FN(prio_data)].enable(desc, prio_data);
/* enable secondary masking method if present */
if (data[!primary])
intc_reg_fns[_INTC_FN(data[!primary])].enable(desc,
data[!primary]);

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

0 comments on commit 38b0304

Please sign in to comment.