Skip to content

Commit

Permalink
[POWERPC] Improve MPIC driver auto-configuration from DT
Browse files Browse the repository at this point in the history
This patch applies on top of the MPIC DCR support. It makes the MPIC
driver capable of a lot more auto-configuration based on the device-tree,
for example, it can retreive it's own physical address if not passed as
an argument, find out if it's DCR or MMIO mapped, and set the BIG_ENDIAN
flag automatically in the presence of a "big-endian" property in the
device-tree node.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
  • Loading branch information
Benjamin Herrenschmidt authored and Paul Mackerras committed Dec 4, 2006
1 parent fbf0274 commit a959ff5
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 15 deletions.
50 changes: 37 additions & 13 deletions arch/powerpc/sysdev/mpic.c
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,7 @@ static struct irq_host_ops mpic_host_ops = {
*/

struct mpic * __init mpic_alloc(struct device_node *node,
unsigned long phys_addr,
phys_addr_t phys_addr,
unsigned int flags,
unsigned int isu_size,
unsigned int irq_count,
Expand All @@ -904,6 +904,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
u32 reg;
const char *vers;
int i;
u64 paddr = phys_addr;

mpic = alloc_bootmem(sizeof(struct mpic));
if (mpic == NULL)
Expand Down Expand Up @@ -943,6 +944,11 @@ struct mpic * __init mpic_alloc(struct device_node *node,
mpic->irq_count = irq_count;
mpic->num_sources = 0; /* so far */

/* Check for "big-endian" in device-tree */
if (node && get_property(node, "big-endian", NULL) != NULL)
mpic->flags |= MPIC_BIG_ENDIAN;


#ifdef CONFIG_MPIC_WEIRD
mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)];
#endif
Expand All @@ -951,11 +957,17 @@ struct mpic * __init mpic_alloc(struct device_node *node,
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 && get_property(node, "dcr-reg", NULL) != NULL)
mpic->flags |= MPIC_USES_DCR;

#ifdef CONFIG_PPC_DCR
if (mpic->flags & MPIC_USES_DCR) {
const u32 *dbasep;
BUG_ON(mpic->of_node == NULL);
dbasep = get_property(mpic->of_node, "dcr-reg", NULL);
dbasep = get_property(node, "dcr-reg", NULL);
BUG_ON(dbasep == NULL);
mpic->dcr_base = *dbasep;
mpic->reg_type = mpic_access_dcr;
Expand All @@ -964,9 +976,20 @@ struct mpic * __init mpic_alloc(struct device_node *node,
BUG_ON (mpic->flags & MPIC_USES_DCR);
#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;
reg = 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, phys_addr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000);
mpic_map(mpic, phys_addr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
mpic_map(mpic, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000);
mpic_map(mpic, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);

/* Reset */
if (flags & MPIC_WANTS_RESET) {
Expand All @@ -991,15 +1014,15 @@ struct mpic * __init mpic_alloc(struct device_node *node,

/* Map the per-CPU registers */
for (i = 0; i < mpic->num_cpus; i++) {
mpic_map(mpic, phys_addr, &mpic->cpuregs[i],
mpic_map(mpic, paddr, &mpic->cpuregs[i],
MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE),
0x1000);
}

/* Initialize main ISU if none provided */
if (mpic->isu_size == 0) {
mpic->isu_size = mpic->num_sources;
mpic_map(mpic, phys_addr, &mpic->isus[0],
mpic_map(mpic, paddr, &mpic->isus[0],
MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
}
mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
Expand All @@ -1020,10 +1043,11 @@ struct mpic * __init mpic_alloc(struct device_node *node,
vers = "<unknown>";
break;
}
printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %lx, max %d CPUs\n",
name, vers, phys_addr, mpic->num_cpus);
printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", mpic->isu_size,
mpic->isu_shift, mpic->isu_mask);
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;
mpics = mpic;
Expand All @@ -1037,13 +1061,13 @@ struct mpic * __init mpic_alloc(struct device_node *node,
}

void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
unsigned long phys_addr)
phys_addr_t paddr)
{
unsigned int isu_first = isu_num * mpic->isu_size;

BUG_ON(isu_num >= MPIC_MAX_ISU);

mpic_map(mpic, phys_addr, &mpic->isus[isu_num], 0,
mpic_map(mpic, paddr, &mpic->isus[isu_num], 0,
MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
if ((isu_first + mpic->isu_size) > mpic->num_sources)
mpic->num_sources = isu_first + mpic->isu_size;
Expand Down
4 changes: 2 additions & 2 deletions include/asm-powerpc/mpic.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ struct mpic
* that is senses[0] correspond to linux irq "irq_offset".
*/
extern struct mpic *mpic_alloc(struct device_node *node,
unsigned long phys_addr,
phys_addr_t phys_addr,
unsigned int flags,
unsigned int isu_size,
unsigned int irq_count,
Expand All @@ -377,7 +377,7 @@ extern struct mpic *mpic_alloc(struct device_node *node,
* @phys_addr: physical address of the ISU
*/
extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
unsigned long phys_addr);
phys_addr_t phys_addr);

/* Set default sense codes
*
Expand Down

0 comments on commit a959ff5

Please sign in to comment.