]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 21 Mar 2011 16:52:27 +0000 (09:52 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 21 Mar 2011 16:52:27 +0000 (09:52 -0700)
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
  powerpc/ptrace: Remove BUG_ON when full register set not available
  powerpc: Factoring mpic cpu id fetching into a function
  powerpc: Make MPIC honor the "pic-no-reset" device tree property
  powerpc: Document the Open PIC device tree binding
  powerpc/pci: Fix crash in PCI code on ppc64 when matching device nodes

Documentation/devicetree/bindings/open-pic.txt [new file with mode: 0644]
arch/powerpc/include/asm/mpic.h
arch/powerpc/include/asm/ptrace.h
arch/powerpc/kernel/pci_dn.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/sysdev/mpic.c

diff --git a/Documentation/devicetree/bindings/open-pic.txt b/Documentation/devicetree/bindings/open-pic.txt
new file mode 100644 (file)
index 0000000..909a902
--- /dev/null
@@ -0,0 +1,98 @@
+* Open PIC Binding
+
+This binding specifies what properties must be available in the device tree
+representation of an Open PIC compliant interrupt controller.  This binding is
+based on the binding defined for Open PIC in [1] and is a superset of that
+binding.
+
+Required properties:
+
+  NOTE: Many of these descriptions were paraphrased here from [1] to aid
+        readability.
+
+    - compatible: Specifies the compatibility list for the PIC.  The type
+      shall be <string> and the value shall include "open-pic".
+
+    - reg: Specifies the base physical address(s) and size(s) of this
+      PIC's addressable register space.  The type shall be <prop-encoded-array>.
+
+    - interrupt-controller: The presence of this property identifies the node
+      as an Open PIC.  No property value shall be defined.
+
+    - #interrupt-cells: Specifies the number of cells needed to encode an
+      interrupt source.  The type shall be a <u32> and the value shall be 2.
+
+    - #address-cells: Specifies the number of cells needed to encode an
+      address.  The type shall be <u32> and the value shall be 0.  As such,
+      'interrupt-map' nodes do not have to specify a parent unit address.
+
+Optional properties:
+
+    - pic-no-reset: The presence of this property indicates that the PIC
+      shall not be reset during runtime initialization.  No property value shall
+      be defined.  The presence of this property also mandates that any
+      initialization related to interrupt sources shall be limited to sources
+      explicitly referenced in the device tree.
+
+* Interrupt Specifier Definition
+
+  Interrupt specifiers consists of 2 cells encoded as
+  follows:
+
+    - <1st-cell>: The interrupt-number that identifies the interrupt source.
+
+    - <2nd-cell>: The level-sense information, encoded as follows:
+                    0 = low-to-high edge triggered
+                    1 = active low level-sensitive
+                    2 = active high level-sensitive
+                    3 = high-to-low edge triggered
+
+* Examples
+
+Example 1:
+
+       /*
+        * An Open PIC interrupt controller
+        */
+       mpic: pic@40000 {
+               // This is an interrupt controller node.
+               interrupt-controller;
+
+               // No address cells so that 'interrupt-map' nodes which reference
+               // this Open PIC node do not need a parent address specifier.
+               #address-cells = <0>;
+
+               // Two cells to encode interrupt sources.
+               #interrupt-cells = <2>;
+
+               // Offset address of 0x40000 and size of 0x40000.
+               reg = <0x40000 0x40000>;
+
+               // Compatible with Open PIC.
+               compatible = "open-pic";
+
+               // The PIC shall not be reset.
+               pic-no-reset;
+       };
+
+Example 2:
+
+       /*
+        * An interrupt generating device that is wired to an Open PIC.
+        */
+       serial0: serial@4500 {
+               // Interrupt source '42' that is active high level-sensitive.
+               // Note that there are only two cells as specified in the interrupt
+               // parent's '#interrupt-cells' property.
+               interrupts = <42 2>;
+
+               // The interrupt controller that this device is wired to.
+               interrupt-parent = <&mpic>;
+       };
+
+* References
+
+[1] Power.org (TM) Standard for Embedded Power Architecture (TM) Platform
+    Requirements (ePAPR), Version 1.0, July 2008.
+    (http://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf)
+
index 946ec4947da282e90589a3012c8fb92653ecc5f2..7005ee0b074d744e6905fd8e0c6dfc144a3a4cb3 100644 (file)
@@ -367,6 +367,10 @@ struct mpic
 #define MPIC_SINGLE_DEST_CPU           0x00001000
 /* Enable CoreInt delivery of interrupts */
 #define MPIC_ENABLE_COREINT            0x00002000
+/* Disable resetting of the MPIC.
+ * NOTE: This flag trumps MPIC_WANTS_RESET.
+ */
+#define MPIC_NO_RESET                  0x00004000
 
 /* MPIC HW modification ID */
 #define MPIC_REGSET_MASK               0xf0000000
index 0175a676b34b5e577c4e52107bfd1f3e99c6e8d2..48223f9b8728d5e1433c6d13ab9c1c583780d2cb 100644 (file)
@@ -125,8 +125,10 @@ extern int ptrace_put_reg(struct task_struct *task, int regno,
 #endif /* ! __powerpc64__ */
 #define TRAP(regs)             ((regs)->trap & ~0xF)
 #ifdef __powerpc64__
+#define NV_REG_POISON          0xdeadbeefdeadbeefUL
 #define CHECK_FULL_REGS(regs)  BUG_ON(regs->trap & 1)
 #else
+#define NV_REG_POISON          0xdeadbeef
 #define CHECK_FULL_REGS(regs)                                                \
 do {                                                                         \
        if ((regs)->trap & 1)                                                 \
index 29852688ceaaae7f6f9c09cbc7e3f6350ee8170f..d225d99fe39d8f076ee637377a43692024c39232 100644 (file)
@@ -176,11 +176,14 @@ static void *is_devfn_node(struct device_node *dn, void *data)
  */
 struct device_node *fetch_dev_dn(struct pci_dev *dev)
 {
-       struct device_node *orig_dn = dev->dev.of_node;
+       struct pci_controller *phb = dev->sysdata;
        struct device_node *dn;
        unsigned long searchval = (dev->bus->number << 8) | dev->devfn;
 
-       dn = traverse_pci_devices(orig_dn, is_devfn_node, (void *)searchval);
+       if (WARN_ON(!phb))
+               return NULL;
+
+       dn = traverse_pci_devices(phb->dn, is_devfn_node, (void *)searchval);
        if (dn)
                dev->dev.of_node = dn;
        return dn;
index 9065369982911f19eab7ee34fa88209597cfbdeb..895b082f1e48bafe5c7826de6950edf14cff6d23 100644 (file)
@@ -229,12 +229,16 @@ static int gpr_get(struct task_struct *target, const struct user_regset *regset,
                   unsigned int pos, unsigned int count,
                   void *kbuf, void __user *ubuf)
 {
-       int ret;
+       int i, ret;
 
        if (target->thread.regs == NULL)
                return -EIO;
 
-       CHECK_FULL_REGS(target->thread.regs);
+       if (!FULL_REGS(target->thread.regs)) {
+               /* We have a partial register set.  Fill 14-31 with bogus values */
+               for (i = 14; i < 32; i++)
+                       target->thread.regs->gpr[i] = NV_REG_POISON;
+       }
 
        ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
                                  target->thread.regs,
@@ -641,11 +645,16 @@ static int gpr32_get(struct task_struct *target,
        compat_ulong_t *k = kbuf;
        compat_ulong_t __user *u = ubuf;
        compat_ulong_t reg;
+       int i;
 
        if (target->thread.regs == NULL)
                return -EIO;
 
-       CHECK_FULL_REGS(target->thread.regs);
+       if (!FULL_REGS(target->thread.regs)) {
+               /* We have a partial register set.  Fill 14-31 with bogus values */
+               for (i = 14; i < 32; i++)
+                       target->thread.regs->gpr[i] = NV_REG_POISON; 
+       }
 
        pos /= sizeof(reg);
        count /= sizeof(reg);
index eb7021815e2da0c28e6bdc85be746e7135acd415..0f7c6718d26107c37e819be52d9794bbe7b9e883 100644 (file)
@@ -147,6 +147,16 @@ static u32 mpic_infos[][MPIC_IDX_END] = {
 
 #endif /* CONFIG_MPIC_WEIRD */
 
+static inline unsigned int mpic_processor_id(struct mpic *mpic)
+{
+       unsigned int cpu = 0;
+
+       if (mpic->flags & MPIC_PRIMARY)
+               cpu = hard_smp_processor_id();
+
+       return cpu;
+}
+
 /*
  * Register accessor functions
  */
@@ -210,19 +220,14 @@ static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 valu
 
 static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
 {
-       unsigned int cpu = 0;
+       unsigned int cpu = mpic_processor_id(mpic);
 
-       if (mpic->flags & MPIC_PRIMARY)
-               cpu = hard_smp_processor_id();
        return _mpic_read(mpic->reg_type, &mpic->cpuregs[cpu], reg);
 }
 
 static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
 {
-       unsigned int cpu = 0;
-
-       if (mpic->flags & MPIC_PRIMARY)
-               cpu = hard_smp_processor_id();
+       unsigned int cpu = mpic_processor_id(mpic);
 
        _mpic_write(mpic->reg_type, &mpic->cpuregs[cpu], reg, value);
 }
@@ -913,6 +918,20 @@ void mpic_set_vector(unsigned int virq, unsigned int vector)
        mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
 }
 
+void mpic_set_destination(unsigned int virq, unsigned int cpuid)
+{
+       struct mpic *mpic = mpic_from_irq(virq);
+       unsigned int src = mpic_irq_to_hw(virq);
+
+       DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n",
+           mpic, virq, src, cpuid);
+
+       if (src >= mpic->irq_count)
+               return;
+
+       mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
+}
+
 static struct irq_chip mpic_irq_chip = {
        .irq_mask       = mpic_mask_irq,
        .irq_unmask     = mpic_unmask_irq,
@@ -993,6 +1012,16 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
        /* Set default irq type */
        set_irq_type(virq, IRQ_TYPE_NONE);
 
+       /* If the MPIC was reset, then all vectors have already been
+        * initialized.  Otherwise, a per source lazy initialization
+        * is done here.
+        */
+       if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) {
+               mpic_set_vector(virq, hw);
+               mpic_set_destination(virq, mpic_processor_id(mpic));
+               mpic_irq_set_priority(virq, 8);
+       }
+
        return 0;
 }
 
@@ -1040,6 +1069,11 @@ static struct irq_host_ops mpic_host_ops = {
        .xlate = mpic_host_xlate,
 };
 
+static int mpic_reset_prohibited(struct device_node *node)
+{
+       return node && of_get_property(node, "pic-no-reset", NULL);
+}
+
 /*
  * Exported functions
  */
@@ -1160,7 +1194,15 @@ struct mpic * __init mpic_alloc(struct device_node *node,
        mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
 
        /* Reset */
-       if (flags & MPIC_WANTS_RESET) {
+
+       /* When using a device-node, reset requests are only honored if the MPIC
+        * is allowed to reset.
+        */
+       if (mpic_reset_prohibited(node))
+               mpic->flags |= MPIC_NO_RESET;
+
+       if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) {
+               printk(KERN_DEBUG "mpic: Resetting\n");
                mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
                           mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
                           | MPIC_GREG_GCONF_RESET);
@@ -1320,22 +1362,21 @@ void __init mpic_init(struct mpic *mpic)
 
        mpic_pasemi_msi_init(mpic);
 
-       if (mpic->flags & MPIC_PRIMARY)
-               cpu = hard_smp_processor_id();
-       else
-               cpu = 0;
+       cpu = mpic_processor_id(mpic);
 
-       for (i = 0; i < mpic->num_sources; i++) {
-               /* start with vector = source number, and masked */
-               u32 vecpri = MPIC_VECPRI_MASK | i |
-                       (8 << MPIC_VECPRI_PRIORITY_SHIFT);
+       if (!(mpic->flags & MPIC_NO_RESET)) {
+               for (i = 0; i < mpic->num_sources; i++) {
+                       /* start with vector = source number, and masked */
+                       u32 vecpri = MPIC_VECPRI_MASK | i |
+                               (8 << MPIC_VECPRI_PRIORITY_SHIFT);
                
-               /* check if protected */
-               if (mpic->protected && test_bit(i, mpic->protected))
-                       continue;
-               /* init hw */
-               mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
-               mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
+                       /* check if protected */
+                       if (mpic->protected && test_bit(i, mpic->protected))
+                               continue;
+                       /* init hw */
+                       mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
+                       mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
+               }
        }
        
        /* Init spurious vector */