Pull sn-features into release branch
[sfrench/cifs-2.6.git] / arch / sparc64 / kernel / pci_schizo.c
index 5753175b94e6c91da7eb7ad91fcf197585bf3c98..331382e1a75d40d80680206b31b1c3eb26f129d3 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/iommu.h>
 #include <asm/irq.h>
 #include <asm/upa.h>
+#include <asm/pstate.h>
 
 #include "pci_impl.h"
 #include "iommu_common.h"
@@ -284,7 +285,7 @@ static unsigned char schizo_pil_table[] = {
 /*0x3f*/0,             /* Reserved for NewLink         */
 };
 
-static int __init schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
+static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
 {
        int ret;
 
@@ -326,6 +327,44 @@ static int __init schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
        return ret;
 }
 
+static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2)
+{
+       unsigned long sync_reg = (unsigned long) _arg2;
+       u64 mask = 1 << (__irq_ino(__irq(bucket)) & IMAP_INO);
+       u64 val;
+       int limit;
+
+       schizo_write(sync_reg, mask);
+
+       limit = 100000;
+       val = 0;
+       while (--limit) {
+               val = schizo_read(sync_reg);
+               if (!(val & mask))
+                       break;
+       }
+       if (limit <= 0) {
+               printk("tomatillo_wsync_handler: DMA won't sync [%lx:%lx]\n",
+                      val, mask);
+       }
+
+       if (_arg1) {
+               static unsigned char cacheline[64]
+                       __attribute__ ((aligned (64)));
+
+               __asm__ __volatile__("rd %%fprs, %0\n\t"
+                                    "or %0, %4, %1\n\t"
+                                    "wr %1, 0x0, %%fprs\n\t"
+                                    "stda %%f0, [%5] %6\n\t"
+                                    "wr %0, 0x0, %%fprs\n\t"
+                                    "membar #Sync"
+                                    : "=&r" (mask), "=&r" (val)
+                                    : "0" (mask), "1" (val),
+                                    "i" (FPRS_FEF), "r" (&cacheline[0]),
+                                    "i" (ASI_BLK_COMMIT_P));
+       }
+}
+
 static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,
                                     struct pci_dev *pdev,
                                     unsigned int ino)
@@ -369,6 +408,15 @@ static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,
        bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap));
        bucket->flags |= IBF_PCI;
 
+       if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
+               struct irq_desc *p = bucket->irq_info;
+
+               p->pre_handler = tomatillo_wsync_handler;
+               p->pre_handler_arg1 = ((pbm->chip_version <= 4) ?
+                                      (void *) 1 : (void *) 0);
+               p->pre_handler_arg2 = (void *) pbm->sync_reg;
+       }
+
        return __irq(bucket);
 }
 
@@ -885,6 +933,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
 
 #define SCHIZO_PCI_CTRL                (0x2000UL)
 #define SCHIZO_PCICTRL_BUS_UNUS        (1UL << 63UL) /* Safari */
+#define SCHIZO_PCICTRL_DTO_INT (1UL << 61UL) /* Tomatillo */
 #define SCHIZO_PCICTRL_ARB_PRIO (0x1ff << 52UL) /* Tomatillo */
 #define SCHIZO_PCICTRL_ESLCK   (1UL << 51UL) /* Safari */
 #define SCHIZO_PCICTRL_ERRSLOT (7UL << 48UL) /* Safari */
@@ -1172,7 +1221,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
  * PCI bus units of the same Tomatillo.  I still have not really
  * figured this out...
  */
-static void __init tomatillo_register_error_handlers(struct pci_controller_info *p)
+static void tomatillo_register_error_handlers(struct pci_controller_info *p)
 {
        struct pci_pbm_info *pbm;
        unsigned int irq;
@@ -1310,7 +1359,7 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
                     (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
 }
 
-static void __init schizo_register_error_handlers(struct pci_controller_info *p)
+static void schizo_register_error_handlers(struct pci_controller_info *p)
 {
        struct pci_pbm_info *pbm;
        unsigned int irq;
@@ -1456,7 +1505,7 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
                     (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)));
 }
 
-static void __init pbm_config_busmastering(struct pci_pbm_info *pbm)
+static void pbm_config_busmastering(struct pci_pbm_info *pbm)
 {
        u8 *addr;
 
@@ -1473,8 +1522,8 @@ static void __init pbm_config_busmastering(struct pci_pbm_info *pbm)
        pci_config_write8(addr, 64);
 }
 
-static void __init pbm_scan_bus(struct pci_controller_info *p,
-                               struct pci_pbm_info *pbm)
+static void pbm_scan_bus(struct pci_controller_info *p,
+                        struct pci_pbm_info *pbm)
 {
        struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);
 
@@ -1501,8 +1550,8 @@ static void __init pbm_scan_bus(struct pci_controller_info *p,
        pci_setup_busmastering(pbm, pbm->pci_bus);
 }
 
-static void __init __schizo_scan_bus(struct pci_controller_info *p,
-                                    int chip_type)
+static void __schizo_scan_bus(struct pci_controller_info *p,
+                             int chip_type)
 {
        if (!p->pbm_B.prom_node || !p->pbm_A.prom_node) {
                printk("PCI: Only one PCI bus module of controller found.\n");
@@ -1528,17 +1577,17 @@ static void __init __schizo_scan_bus(struct pci_controller_info *p,
                schizo_register_error_handlers(p);
 }
 
-static void __init schizo_scan_bus(struct pci_controller_info *p)
+static void schizo_scan_bus(struct pci_controller_info *p)
 {
        __schizo_scan_bus(p, PBM_CHIP_TYPE_SCHIZO);
 }
 
-static void __init tomatillo_scan_bus(struct pci_controller_info *p)
+static void tomatillo_scan_bus(struct pci_controller_info *p)
 {
        __schizo_scan_bus(p, PBM_CHIP_TYPE_TOMATILLO);
 }
 
-static void __init schizo_base_address_update(struct pci_dev *pdev, int resource)
+static void schizo_base_address_update(struct pci_dev *pdev, int resource)
 {
        struct pcidev_cookie *pcp = pdev->sysdata;
        struct pci_pbm_info *pbm = pcp->pbm;
@@ -1583,9 +1632,9 @@ static void __init schizo_base_address_update(struct pci_dev *pdev, int resource
                pci_write_config_dword(pdev, where + 4, 0);
 }
 
-static void __init schizo_resource_adjust(struct pci_dev *pdev,
-                                         struct resource *res,
-                                         struct resource *root)
+static void schizo_resource_adjust(struct pci_dev *pdev,
+                                  struct resource *res,
+                                  struct resource *root)
 {
        res->start += root->start;
        res->end += root->start;
@@ -1653,8 +1702,8 @@ static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm)
               pbm->mem_space.start);
 }
 
-static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,
-                                                  struct pci_pbm_info *pbm)
+static void pbm_register_toplevel_resources(struct pci_controller_info *p,
+                                           struct pci_pbm_info *pbm)
 {
        pbm->io_space.name = pbm->mem_space.name = pbm->name;
 
@@ -1883,41 +1932,31 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
 #define TOMATILLO_PCI_IOC_TDIAG                (0x2250UL)
 #define TOMATILLO_PCI_IOC_DDIAG                (0x2290UL)
 
-static void __init schizo_pbm_hw_init(struct pci_pbm_info *pbm)
+static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
 {
        u64 tmp;
 
-       /* Set IRQ retry to infinity. */
-       schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY,
-                    SCHIZO_IRQ_RETRY_INF);
+       schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5);
 
-       /* Enable arbiter for all PCI slots.  Also, disable PCI interval
-        * timer so that DTO (Discard TimeOuts) are not reported because
-        * some Schizo revisions report them erroneously.
-        */
        tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL);
-       if (pbm->chip_type == PBM_CHIP_TYPE_SCHIZO_PLUS &&
-           pbm->chip_version == 0x5 &&
-           pbm->chip_revision == 0x1)
-               tmp |= 0x0f;
-       else
-               tmp |= 0xff;
 
-       tmp &= ~SCHIZO_PCICTRL_PTO;
+       /* Enable arbiter for all PCI slots.  */
+       tmp |= 0xff;
+
        if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO &&
            pbm->chip_version >= 0x2)
                tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT;
-       else
-               tmp |= 0x1UL << SCHIZO_PCICTRL_PTO_SHIFT;
 
        if (!prom_getbool(pbm->prom_node, "no-bus-parking"))
                tmp |= SCHIZO_PCICTRL_PARK;
+       else
+               tmp &= ~SCHIZO_PCICTRL_PARK;
 
        if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO &&
            pbm->chip_version <= 0x1)
-               tmp |= (1UL << 61);
+               tmp |= SCHIZO_PCICTRL_DTO_INT;
        else
-               tmp &= ~(1UL << 61);
+               tmp &= ~SCHIZO_PCICTRL_DTO_INT;
 
        if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO)
                tmp |= (SCHIZO_PCICTRL_MRM_PREF |
@@ -1947,9 +1986,9 @@ static void __init schizo_pbm_hw_init(struct pci_pbm_info *pbm)
        }
 }
 
-static void __init schizo_pbm_init(struct pci_controller_info *p,
-                                  int prom_node, u32 portid,
-                                  int chip_type)
+static void schizo_pbm_init(struct pci_controller_info *p,
+                           int prom_node, u32 portid,
+                           int chip_type)
 {
        struct linux_prom64_registers pr_regs[4];
        unsigned int busrange[2];
@@ -2015,6 +2054,9 @@ static void __init schizo_pbm_init(struct pci_controller_info *p,
        pbm->pbm_regs = pr_regs[0].phys_addr;
        pbm->controller_regs = pr_regs[1].phys_addr - 0x10000UL;
 
+       if (chip_type == PBM_CHIP_TYPE_TOMATILLO)
+               pbm->sync_reg = pr_regs[3].phys_addr + 0x1a18UL;
+
        sprintf(pbm->name,
                (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
                 "TOMATILLO%d PBM%c" :
@@ -2103,7 +2145,7 @@ static inline int portid_compare(u32 x, u32 y, int chip_type)
        return (x == y);
 }
 
-static void __init __schizo_init(int node, char *model_name, int chip_type)
+static void __schizo_init(int node, char *model_name, int chip_type)
 {
        struct pci_controller_info *p;
        struct pci_iommu *iommu;
@@ -2171,17 +2213,17 @@ static void __init __schizo_init(int node, char *model_name, int chip_type)
        schizo_pbm_init(p, node, portid, chip_type);
 }
 
-void __init schizo_init(int node, char *model_name)
+void schizo_init(int node, char *model_name)
 {
        __schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO);
 }
 
-void __init schizo_plus_init(int node, char *model_name)
+void schizo_plus_init(int node, char *model_name)
 {
        __schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS);
 }
 
-void __init tomatillo_init(int node, char *model_name)
+void tomatillo_init(int node, char *model_name)
 {
        __schizo_init(node, model_name, PBM_CHIP_TYPE_TOMATILLO);
 }