aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-11-11 01:24:56 -0500
committerPaul Mackerras <paulus@samba.org>2006-12-04 00:08:41 -0500
commita959ff56bbf07954ea4fa1cf72f99a38795eadb3 (patch)
tree85bd54ccfe77a9508a6cf2763d296ff988b9764f
parentfbf0274e43b7e17ee740fee2d693932be093d56d (diff)
[POWERPC] Improve MPIC driver auto-configuration from DT
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>
-rw-r--r--arch/powerpc/sysdev/mpic.c50
-rw-r--r--include/asm-powerpc/mpic.h4
2 files changed, 39 insertions, 15 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 909306ca04f4..411480d5c626 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -894,7 +894,7 @@ static struct irq_host_ops mpic_host_ops = {
894 */ 894 */
895 895
896struct mpic * __init mpic_alloc(struct device_node *node, 896struct mpic * __init mpic_alloc(struct device_node *node,
897 unsigned long phys_addr, 897 phys_addr_t phys_addr,
898 unsigned int flags, 898 unsigned int flags,
899 unsigned int isu_size, 899 unsigned int isu_size,
900 unsigned int irq_count, 900 unsigned int irq_count,
@@ -904,6 +904,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
904 u32 reg; 904 u32 reg;
905 const char *vers; 905 const char *vers;
906 int i; 906 int i;
907 u64 paddr = phys_addr;
907 908
908 mpic = alloc_bootmem(sizeof(struct mpic)); 909 mpic = alloc_bootmem(sizeof(struct mpic));
909 if (mpic == NULL) 910 if (mpic == NULL)
@@ -943,6 +944,11 @@ struct mpic * __init mpic_alloc(struct device_node *node,
943 mpic->irq_count = irq_count; 944 mpic->irq_count = irq_count;
944 mpic->num_sources = 0; /* so far */ 945 mpic->num_sources = 0; /* so far */
945 946
947 /* Check for "big-endian" in device-tree */
948 if (node && get_property(node, "big-endian", NULL) != NULL)
949 mpic->flags |= MPIC_BIG_ENDIAN;
950
951
946#ifdef CONFIG_MPIC_WEIRD 952#ifdef CONFIG_MPIC_WEIRD
947 mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; 953 mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)];
948#endif 954#endif
@@ -951,11 +957,17 @@ struct mpic * __init mpic_alloc(struct device_node *node,
951 mpic->reg_type = (flags & MPIC_BIG_ENDIAN) ? 957 mpic->reg_type = (flags & MPIC_BIG_ENDIAN) ?
952 mpic_access_mmio_be : mpic_access_mmio_le; 958 mpic_access_mmio_be : mpic_access_mmio_le;
953 959
960 /* If no physical address is passed in, a device-node is mandatory */
961 BUG_ON(paddr == 0 && node == NULL);
962
963 /* If no physical address passed in, check if it's dcr based */
964 if (paddr == 0 && get_property(node, "dcr-reg", NULL) != NULL)
965 mpic->flags |= MPIC_USES_DCR;
966
954#ifdef CONFIG_PPC_DCR 967#ifdef CONFIG_PPC_DCR
955 if (mpic->flags & MPIC_USES_DCR) { 968 if (mpic->flags & MPIC_USES_DCR) {
956 const u32 *dbasep; 969 const u32 *dbasep;
957 BUG_ON(mpic->of_node == NULL); 970 dbasep = get_property(node, "dcr-reg", NULL);
958 dbasep = get_property(mpic->of_node, "dcr-reg", NULL);
959 BUG_ON(dbasep == NULL); 971 BUG_ON(dbasep == NULL);
960 mpic->dcr_base = *dbasep; 972 mpic->dcr_base = *dbasep;
961 mpic->reg_type = mpic_access_dcr; 973 mpic->reg_type = mpic_access_dcr;
@@ -964,9 +976,20 @@ struct mpic * __init mpic_alloc(struct device_node *node,
964 BUG_ON (mpic->flags & MPIC_USES_DCR); 976 BUG_ON (mpic->flags & MPIC_USES_DCR);
965#endif /* CONFIG_PPC_DCR */ 977#endif /* CONFIG_PPC_DCR */
966 978
979 /* If the MPIC is not DCR based, and no physical address was passed
980 * in, try to obtain one
981 */
982 if (paddr == 0 && !(mpic->flags & MPIC_USES_DCR)) {
983 const u32 *reg;
984 reg = get_property(node, "reg", NULL);
985 BUG_ON(reg == NULL);
986 paddr = of_translate_address(node, reg);
987 BUG_ON(paddr == OF_BAD_ADDR);
988 }
989
967 /* Map the global registers */ 990 /* Map the global registers */
968 mpic_map(mpic, phys_addr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); 991 mpic_map(mpic, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000);
969 mpic_map(mpic, phys_addr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); 992 mpic_map(mpic, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
970 993
971 /* Reset */ 994 /* Reset */
972 if (flags & MPIC_WANTS_RESET) { 995 if (flags & MPIC_WANTS_RESET) {
@@ -991,7 +1014,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
991 1014
992 /* Map the per-CPU registers */ 1015 /* Map the per-CPU registers */
993 for (i = 0; i < mpic->num_cpus; i++) { 1016 for (i = 0; i < mpic->num_cpus; i++) {
994 mpic_map(mpic, phys_addr, &mpic->cpuregs[i], 1017 mpic_map(mpic, paddr, &mpic->cpuregs[i],
995 MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE), 1018 MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE),
996 0x1000); 1019 0x1000);
997 } 1020 }
@@ -999,7 +1022,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
999 /* Initialize main ISU if none provided */ 1022 /* Initialize main ISU if none provided */
1000 if (mpic->isu_size == 0) { 1023 if (mpic->isu_size == 0) {
1001 mpic->isu_size = mpic->num_sources; 1024 mpic->isu_size = mpic->num_sources;
1002 mpic_map(mpic, phys_addr, &mpic->isus[0], 1025 mpic_map(mpic, paddr, &mpic->isus[0],
1003 MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); 1026 MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
1004 } 1027 }
1005 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); 1028 mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
@@ -1020,10 +1043,11 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1020 vers = "<unknown>"; 1043 vers = "<unknown>";
1021 break; 1044 break;
1022 } 1045 }
1023 printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %lx, max %d CPUs\n", 1046 printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %llx,"
1024 name, vers, phys_addr, mpic->num_cpus); 1047 " max %d CPUs\n",
1025 printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", mpic->isu_size, 1048 name, vers, (unsigned long long)paddr, mpic->num_cpus);
1026 mpic->isu_shift, mpic->isu_mask); 1049 printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n",
1050 mpic->isu_size, mpic->isu_shift, mpic->isu_mask);
1027 1051
1028 mpic->next = mpics; 1052 mpic->next = mpics;
1029 mpics = mpic; 1053 mpics = mpic;
@@ -1037,13 +1061,13 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1037} 1061}
1038 1062
1039void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, 1063void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
1040 unsigned long phys_addr) 1064 phys_addr_t paddr)
1041{ 1065{
1042 unsigned int isu_first = isu_num * mpic->isu_size; 1066 unsigned int isu_first = isu_num * mpic->isu_size;
1043 1067
1044 BUG_ON(isu_num >= MPIC_MAX_ISU); 1068 BUG_ON(isu_num >= MPIC_MAX_ISU);
1045 1069
1046 mpic_map(mpic, phys_addr, &mpic->isus[isu_num], 0, 1070 mpic_map(mpic, paddr, &mpic->isus[isu_num], 0,
1047 MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); 1071 MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
1048 if ((isu_first + mpic->isu_size) > mpic->num_sources) 1072 if ((isu_first + mpic->isu_size) > mpic->num_sources)
1049 mpic->num_sources = isu_first + mpic->isu_size; 1073 mpic->num_sources = isu_first + mpic->isu_size;
diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h
index ad989d182fb4..b71e7b32a555 100644
--- a/include/asm-powerpc/mpic.h
+++ b/include/asm-powerpc/mpic.h
@@ -364,7 +364,7 @@ struct mpic
364 * that is senses[0] correspond to linux irq "irq_offset". 364 * that is senses[0] correspond to linux irq "irq_offset".
365 */ 365 */
366extern struct mpic *mpic_alloc(struct device_node *node, 366extern struct mpic *mpic_alloc(struct device_node *node,
367 unsigned long phys_addr, 367 phys_addr_t phys_addr,
368 unsigned int flags, 368 unsigned int flags,
369 unsigned int isu_size, 369 unsigned int isu_size,
370 unsigned int irq_count, 370 unsigned int irq_count,
@@ -377,7 +377,7 @@ extern struct mpic *mpic_alloc(struct device_node *node,
377 * @phys_addr: physical address of the ISU 377 * @phys_addr: physical address of the ISU
378 */ 378 */
379extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, 379extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
380 unsigned long phys_addr); 380 phys_addr_t phys_addr);
381 381
382/* Set default sense codes 382/* Set default sense codes
383 * 383 *