From: SangeethaRao <sangeetha....@lsi.com>

Updated LSI NCR driver to use CPU jiffies for ncr_lock() timeout. Also,
LSI NCR driver under drivers/misc/lsi-ncr.c is integrated as the common
driver for ARM/PPC platforms.

Signed-off-by: SangeethaRao <sangeetha....@lsi.com>
---
 arch/arm/mach-axxia/Makefile |   2 +-
 arch/arm/mach-axxia/ncr.c    | 660 -------------------------------------------
 drivers/misc/Kconfig         |   2 +-
 drivers/misc/lsi-ncr.c       | 523 ++++++++++++++++++++++++----------
 4 files changed, 382 insertions(+), 805 deletions(-)
 delete mode 100644 arch/arm/mach-axxia/ncr.c

diff --git a/arch/arm/mach-axxia/Makefile b/arch/arm/mach-axxia/Makefile
index 5b4c6f9..de95182 100644
--- a/arch/arm/mach-axxia/Makefile
+++ b/arch/arm/mach-axxia/Makefile
@@ -5,7 +5,7 @@ obj-y                                   += axxia.o
 obj-y                                  += clock.o
 obj-y                                  += io.o
 obj-y                                  += ssp-gpio.o
-obj-y                                  += ncr.o
+#obj-y                                 += ncr.o
 obj-y                                  += timers.o
 obj-y                                  += pci.o
 obj-y                                  += ddr_retention.o ddr_shutdown.o
diff --git a/arch/arm/mach-axxia/ncr.c b/arch/arm/mach-axxia/ncr.c
deleted file mode 100644
index 995e8a0..0000000
--- a/arch/arm/mach-axxia/ncr.c
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- *  Copyright (C) 2009 LSI Corporation
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-#include <linux/module.h>
-
-#include <asm/io.h>
-
-#include <mach/ncr.h>
-
-#ifdef CONFIG_ARCH_AXXIA
-#define NCA_PHYS_ADDRESS         0x002020100000ULL
-#define APB2SER_PHY_PHYS_ADDRESS 0x002010000000ULL
-#else
-#define NCA_PHYS_ADDRESS         0x002000520000ULL
-#endif
-
-static void __iomem *nca_address;
-#ifdef APB2SER_PHY_PHYS_ADDRESS
-static void __iomem *apb2ser0_address;
-#endif /* APB2SER_PHY_PHYS_ADDRESS */
-
-#define WFC_TIMEOUT (400000)
-
-static DEFINE_RAW_SPINLOCK(ncr_spin_lock);
-static unsigned long flags;
-
-#define LOCK_DOMAIN 0
-
-typedef union {
-       unsigned long raw;
-       struct {
-#ifdef __BIG_ENDIAN
-               unsigned long start_done:1;
-               unsigned long unused:6;
-               unsigned long local_bit:1;
-               unsigned long status:2;
-               unsigned long byte_swap_enable:1;
-               unsigned long cfg_cmpl_int_enable:1;
-               unsigned long cmd_type:4;
-               unsigned long dbs:16;
-#else
-       unsigned long dbs:16;
-       unsigned long cmd_type:4;
-       unsigned long cfg_cmpl_int_enable:1;
-       unsigned long byte_swap_enable:1;
-       unsigned long status:2;
-       unsigned long local_bit:1;
-       unsigned long unused:6;
-       unsigned long start_done:1;
-#endif
-} __attribute__ ((packed)) bits;
-} __attribute__ ((packed)) command_data_register_0_t;
-
-typedef union {
-       unsigned long raw;
-       struct {
-               unsigned long target_address:32;
-       } __attribute__ ((packed)) bits;
-} __attribute__ ((packed)) command_data_register_1_t;
-
-typedef union {
-       unsigned long raw;
-       struct {
-#ifdef __BIG_ENDIAN
-               unsigned long unused:16;
-               unsigned long target_node_id:8;
-               unsigned long target_id_address_upper:8;
-#else
-               unsigned long target_id_address_upper:8;
-               unsigned long target_node_id:8;
-               unsigned long unused:16;
-#endif
-       } __attribute__ ((packed)) bits;
-} __attribute__ ((packed)) command_data_register_2_t;
-
-#ifdef CONFIG_ARM
-
-/*
- * like iowrite32be but without the barrier.
- * The iowmb barrier in the standard macro includes a outer_cache_sync
- * which we don't want for Axxia register IO.
- */
-#define axxia_write32be(v,p) ({  __raw_writel((__force __u32)cpu_to_be32(v), 
p); })
-
-/*
-  ----------------------------------------------------------------------
-  ncr_register_read
-*/
-
-inline unsigned long
-ncr_register_read(unsigned *address)
-{
-       unsigned long value;
-
-       value = ioread32be(address);
-
-       return value;
-}
-
-/*
-  ----------------------------------------------------------------------
-  ncr_register_write
-*/
-
-void
-inline ncr_register_write(const unsigned value, unsigned *address)
-{
-       axxia_write32be(value, address);
-    asm volatile ("mcr p15,0,%0,c7,c5,4" : : "r" (0));  /* isb */
-
-       return;
-}
-
-#else
-
-/*
-  ----------------------------------------------------------------------
-  ncr_register_read
-*/
-
-inline unsigned long
-ncr_register_read(unsigned *address)
-{
-       unsigned long value;
-
-       value = in_be32((unsigned *)address);
-
-       return value;
-}
-
-/*
-  ----------------------------------------------------------------------
-  ncr_register_write
-*/
-
-inline void
-ncr_register_write(const unsigned value, unsigned *address)
-{
-       out_be32(address, value);
-
-       return;
-}
-
-#endif
-
-/*
-  
------------------------------------------------------------------------------
-  ncr_lock
-*/
-
-static int
-ncr_lock(int domain)
-{
-       unsigned long offset;
-       unsigned long value;
-       int loops = 10000;
-       command_data_register_0_t cdr0;
-
-       raw_spin_lock_irqsave(&ncr_spin_lock, flags);
-       offset = (0xff80 + (domain * 4));
-
-       do {
-               value = ncr_register_read((unsigned *)(nca_address + offset));
-       } while ((0 != value) && (0 < --loops));
-
-       if (0 == loops) {
-               raw_spin_unlock_irqrestore(&ncr_spin_lock, flags);
-               printk(KERN_ERR "ncr_lock() Timeout!\n");
-               BUG();
-
-               return -1;
-       }
-
-       /*
-         Make sure any previous commands completed, and check for errors.
-       */
-
-       loops = 10000;
-
-       do {
-               --loops;
-               cdr0.raw =
-                       ncr_register_read((unsigned *)(nca_address + 0xf0));
-       } while ((0x1 == cdr0.bits.status) &&
-                (0 < loops));
-
-       if (0 == loops) {
-               raw_spin_unlock_irqrestore(&ncr_spin_lock, flags);
-               printk(KERN_ERR
-                      "ncr_lock() Previous command didn't complete!\n");
-               BUG();
-
-               return -1;
-       }
-
-       if (0x2 == cdr0.bits.status) {
-               printk(KERN_ERR "Previous ncr access failed!\n");
-       }
-
-       return 0;
-}
-
-/*
-  
------------------------------------------------------------------------------
-  ncr_unlock
-*/
-
-static void
-ncr_unlock(int domain)
-{
-       unsigned long offset;
-
-       offset = (0xff80 + (domain * 4));
-       ncr_register_write(0, (unsigned *)(nca_address + offset));
-       raw_spin_unlock_irqrestore(&ncr_spin_lock, flags);
-
-       return;
-}
-
-/*
-  ======================================================================
-  ======================================================================
-  Public Interface
-  ======================================================================
-  ======================================================================
-*/
-
-/*
-  ----------------------------------------------------------------------
-  ncr_read
-*/
-
-int
-ncr_read(unsigned long region, unsigned long address, int number,
-        void *buffer)
-{
-       command_data_register_0_t cdr0;
-       command_data_register_1_t cdr1;
-       command_data_register_2_t cdr2;
-       int wfc_timeout = WFC_TIMEOUT;
-
-       if (NULL == nca_address)
-               return -1;
-
-#ifdef APB2SER_PHY_PHYS_ADDRESS
-       if (NULL == apb2ser0_address)
-               return -1;
-#endif /* APB2SER_PHY_PHYS_ADDRESS */
-
-       if (0 != ncr_lock(LOCK_DOMAIN))
-               return -1;
-
-       if ((NCP_NODE_ID(region) != 0x0153) && (NCP_NODE_ID(region) != 0x115)) {
-               /*
-               Set up the read command.
-               */
-
-               cdr2.raw = 0;
-               cdr2.bits.target_node_id = NCP_NODE_ID(region);
-               cdr2.bits.target_id_address_upper = NCP_TARGET_ID(region);
-               ncr_register_write(cdr2.raw, (unsigned *) (nca_address + 0xf8));
-
-               cdr1.raw = 0;
-               cdr1.bits.target_address = (address >> 2);
-               ncr_register_write(cdr1.raw, (unsigned *) (nca_address + 0xf4));
-
-               cdr0.raw = 0;
-               cdr0.bits.start_done = 1;
-
-               if (0xff == cdr2.bits.target_id_address_upper)
-                       cdr0.bits.local_bit = 1;
-
-               cdr0.bits.cmd_type = 4;
-               /* TODO: Verify number... */
-               cdr0.bits.dbs = (number - 1);
-               ncr_register_write(cdr0.raw, (unsigned *) (nca_address + 0xf0));
-               mb();
-
-               /*
-               Wait for completion.
-               */
-
-               do {
-                       --wfc_timeout;
-                       cdr0.raw =
-                               ncr_register_read((unsigned *)
-                                                 (nca_address + 0xf0));
-               } while (1 == cdr0.bits.start_done && 0 < wfc_timeout);
-
-               if (0 == wfc_timeout) {
-                       ncr_unlock(LOCK_DOMAIN);
-                       printk(KERN_ERR "ncr_read() Timeout!\n");
-                       BUG();
-
-                       return -1;
-               }
-
-               if (0x3 != cdr0.bits.status) {
-                       ncr_unlock(LOCK_DOMAIN);
-                       printk(KERN_ERR "ncr_write() failed: 0x%x\n",
-                              cdr0.bits.status);
-
-                       return -1;
-               }
-
-               /*
-               Copy data words to the buffer.
-               */
-
-               address = (unsigned long)(nca_address + 0x1000);
-               while (4 <= number) {
-                       *((unsigned long *) buffer) =
-                               ncr_register_read((unsigned *) address);
-                       address += 4;
-                       buffer += 4;
-                       number -= 4;
-               }
-
-               if (0 < number) {
-                       unsigned long temp =
-                               ncr_register_read((unsigned *) address);
-                       memcpy((void *) buffer, &temp, number);
-               }
-       } else {
-#ifdef APB2SER_PHY_PHYS_ADDRESS
-               if (NCP_NODE_ID(region) != 0x115) {
-                       void __iomem *targ_address = apb2ser0_address +
-                               (address & (~0x3));
-                       /*
-                       * Copy data words to the buffer.
-                       */
-
-                       while (4 <= number) {
-                               *((unsigned long *) buffer) =
-                                       *((unsigned long *) targ_address);
-                               targ_address += 4;
-                               number -= 4;
-                       }
-               } else {
-                       void __iomem *base;
-                       if (0xffff < address) {
-                               ncr_unlock(LOCK_DOMAIN);
-                               return -1;
-                       }
-
-                       switch (NCP_TARGET_ID(region)) {
-                       case 0:
-                               base = (apb2ser0_address + 0x1e0);
-                               break;
-                       case 1:
-                               base = (apb2ser0_address + 0x1f0);
-                               break;
-                       case 2:
-                               base = (apb2ser0_address + 0x200);
-                               break;
-                       case 3:
-                               base = (apb2ser0_address + 0x210);
-                               break;
-                       case 4:
-                               base = (apb2ser0_address + 0x220);
-                               break;
-                       case 5:
-                               base = (apb2ser0_address + 0x230);
-                               break;
-                       default:
-                               ncr_unlock(LOCK_DOMAIN);
-                               return -1;
-                       }
-                       if ((NCP_TARGET_ID(region) == 0x1) ||
-                               (NCP_TARGET_ID(region) == 0x4)) {
-                               writel((0x84c00000 + address), (base + 4));
-                       } else {
-                               writel((0x85400000 + address), (base + 4));
-                       }
-                       do {
-                               --wfc_timeout;
-                               *((unsigned long *) buffer) =
-                                       readl(base + 4);
-                       } while (0 != (*((unsigned long *) buffer) & 0x80000000)
-                                       && 0 < wfc_timeout);
-
-                       if (0 == wfc_timeout) {
-                               ncr_unlock(LOCK_DOMAIN);
-                               return -1;
-                       }
-
-                       if ((NCP_TARGET_ID(region) == 0x1) ||
-                               (NCP_TARGET_ID(region) == 0x4)) {
-                               *((unsigned short *) buffer) =
-                                       readl(base + 8);
-                       } else {
-                               *((unsigned long *) buffer) =
-                                       readl(base + 8);
-                       }
-
-               }
-#else
-               ncr_unlock(LOCK_DOMAIN);
-               return -1;
-#endif /* APB2SER_PHY_PHYS_ADDRESS */
-       }
-
-       ncr_unlock(LOCK_DOMAIN);
-
-       return 0;
-}
-EXPORT_SYMBOL(ncr_read);
-
-/*
-  ----------------------------------------------------------------------
-  ncr_write
-*/
-
-int
-ncr_write(unsigned long region, unsigned long address, int number,
-         void *buffer)
-{
-       command_data_register_0_t cdr0;
-       command_data_register_1_t cdr1;
-       command_data_register_2_t cdr2;
-       unsigned long data_word_base;
-       int dbs = (number - 1);
-       int wfc_timeout = WFC_TIMEOUT;
-
-       if (NULL == nca_address)
-               return -1;
-
-#ifdef APB2SER_PHY_PHYS_ADDRESS
-       if (NULL == apb2ser0_address)
-               return -1;
-#endif /* APB2SER_PHY_PHYS_ADDRESS */
-
-       if (0 != ncr_lock(LOCK_DOMAIN))
-               return -1;
-
-       if ((NCP_NODE_ID(region) != 0x0153) && (NCP_NODE_ID(region) != 0x115)) {
-               /*
-                 Set up the write.
-               */
-
-               cdr2.raw = 0;
-               cdr2.bits.target_node_id = NCP_NODE_ID(region);
-               cdr2.bits.target_id_address_upper = NCP_TARGET_ID(region);
-               ncr_register_write(cdr2.raw, (unsigned *) (nca_address + 0xf8));
-
-               cdr1.raw = 0;
-               cdr1.bits.target_address = (address >> 2);
-               ncr_register_write(cdr1.raw, (unsigned *) (nca_address + 0xf4));
-
-               /*
-                 Copy from buffer to the data words.
-               */
-
-               data_word_base = (unsigned long)(nca_address + 0x1000);
-
-               while (4 <= number) {
-                       ncr_register_write(*((unsigned long *) buffer),
-                                       (unsigned *) data_word_base);
-                       data_word_base += 4;
-                       buffer += 4;
-                       number -= 4;
-               }
-
-               if (0 < number) {
-                       unsigned long temp = 0;
-
-                       memcpy((void *) &temp, (void *) buffer, number);
-                       ncr_register_write(temp, (unsigned *) data_word_base);
-                       data_word_base += number;
-                       buffer += number;
-                       number = 0;
-               }
-
-               cdr0.raw = 0;
-               cdr0.bits.start_done = 1;
-
-               if (0xff == cdr2.bits.target_id_address_upper)
-                       cdr0.bits.local_bit = 1;
-
-               cdr0.bits.cmd_type = 5;
-               /* TODO: Verify number... */
-               cdr0.bits.dbs = dbs;
-               ncr_register_write(cdr0.raw, (unsigned *) (nca_address + 0xf0));
-               mb();
-
-               /*
-               Wait for completion.
-               */
-
-               do {
-                       --wfc_timeout;
-                       cdr0.raw =
-                               ncr_register_read((unsigned *)
-                                                 (nca_address + 0xf0));
-               } while (1 == cdr0.bits.start_done && 0 < wfc_timeout);
-
-               if (0 == wfc_timeout) {
-                       ncr_unlock(LOCK_DOMAIN);
-                       printk(KERN_ERR "ncr_write() Timeout!\n");
-                       BUG();
-
-                       return -1;
-               }
-
-               /*
-               Check status.
-               */
-
-               if ((0x3 != cdr0.bits.status) && (0x00c00000) >> 22) {
-                       unsigned long status;
-
-                       status = ncr_register_read((unsigned *)(nca_address +
-                                                               0xe4));
-                       ncr_unlock(LOCK_DOMAIN);
-                       printk(KERN_ERR
-                              "ncr_write() Error: 0x%x 0x%lx\n",
-                              cdr0.bits.status, status);
-
-                       return status;
-               }
-       } else {
-#ifdef APB2SER_PHY_PHYS_ADDRESS
-       if (NCP_NODE_ID(region) != 0x115) {
-               void __iomem *targ_address = apb2ser0_address +
-                                            (address & (~0x3));
-               /*
-                 Copy from buffer to the data words.
-               */
-
-               while (4 <= number) {
-                       *((unsigned long *) targ_address) =
-                               *((unsigned long *) buffer);
-                       targ_address += 4;
-                       number -= 4;
-               }
-       } else {
-               void __iomem *base;
-               if (0xffff < address) {
-                       ncr_unlock(LOCK_DOMAIN);
-                       return -1;
-               }
-
-               switch (NCP_TARGET_ID(region)) {
-                       case 0:
-                               base = (apb2ser0_address + 0x1e0);
-                               break;
-                       case 1:
-                               base = (apb2ser0_address + 0x1f0);
-                               break;
-                       case 2:
-                               base = (apb2ser0_address + 0x200);
-                               break;
-                       case 3:
-                               base = (apb2ser0_address + 0x210);
-                               break;
-                       case 4:
-                               base = (apb2ser0_address + 0x220);
-                               break;
-                       case 5:
-                               base = (apb2ser0_address + 0x230);
-                               break;
-                       default:
-                               ncr_unlock(LOCK_DOMAIN);
-                               return -1;
-               }
-               if ((NCP_TARGET_ID(region) == 0x1) ||
-                               (NCP_TARGET_ID(region) == 0x4)) {
-                       writel(*((unsigned short *) buffer), base);
-                       writel((0xc4c00000 + address), (base + 4));
-               } else {
-                       writel(*((unsigned long *) buffer), base);
-                       writel((0xc5400000 + address), (base + 4));
-               }
-                       do {
-                               --wfc_timeout;
-                               *((unsigned long *) buffer) =
-                                       readl(base + 4);
-                       } while (0 != (*((unsigned long *) buffer) & 0x80000000)
-                               && 0 < wfc_timeout);
-
-                       if (0 == wfc_timeout) {
-                               ncr_unlock(LOCK_DOMAIN);
-                               return -1;
-                       }
-               }
-#else
-               ncr_unlock(LOCK_DOMAIN);
-               return -1;
-#endif /* APB2SER_PHY_PHYS_ADDRESS */
-       }
-
-       ncr_unlock(LOCK_DOMAIN);
-
-       return 0;
-}
-EXPORT_SYMBOL(ncr_write);
-
-/*
-  ----------------------------------------------------------------------
-  ncr_init
-*/
-
-int
-ncr_init(void)
-{
-       nca_address = ioremap(NCA_PHYS_ADDRESS, 0x20000);
-
-#ifdef APB2SER_PHY_PHYS_ADDRESS
-       apb2ser0_address = ioremap(APB2SER_PHY_PHYS_ADDRESS, 0x10000);
-#endif /* APB2SER_PHY_PHYS_ADDRESS */
-
-       pr_info("ncr: available\n");
-
-       return 0;
-}
-EXPORT_SYMBOL(ncr_init);
-
-/*
-  ----------------------------------------------------------------------
-  ncr_exit
-*/
-
-void __exit
-ncr_exit(void)
-{
-       /* Unmap the NCA. */
-       if (NULL != nca_address)
-               iounmap(nca_address);
-
-#ifdef APB2SER_PHY_PHYS_ADDRESS
-       /* Unmap the APB2SER0 PHY. */
-       if (NULL != apb2ser0_address)
-               iounmap(apb2ser0_address);
-#endif /* APB2SER_PHY_PHYS_ADDRESS */
-
-       return;
-}
-EXPORT_SYMBOL(ncr_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Register Ring access for LSI's ACP board");
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index c6fa981..02a3210 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -547,7 +547,7 @@ config LSI_MTC
 
 config LSI_NCR
        tristate "LSI NCR Access"
-       depends on ACP
+       depends on ARCH_AXXIA || ACP
        help
          Provides access to the LSI Axxia NCR bus.
 
diff --git a/drivers/misc/lsi-ncr.c b/drivers/misc/lsi-ncr.c
index 23bcbe6..9bd185b 100644
--- a/drivers/misc/lsi-ncr.c
+++ b/drivers/misc/lsi-ncr.c
@@ -21,21 +21,29 @@
  */
 
 #include <linux/module.h>
+#include <linux/jiffies.h>
 
 #include <asm/io.h>
 
 #include "lsi-ncr.h"
 
-static void __iomem *nca_address;
-
 #ifdef CONFIG_ARCH_AXXIA
 #define NCA_PHYS_ADDRESS 0x002020100000ULL
+#define APB2SER_PHY_PHYS_ADDRESS 0x002010000000ULL
 #else
 #define NCA_PHYS_ADDRESS 0x002000520000ULL
 #endif
 
+static void __iomem *nca_address;
+#ifdef APB2SER_PHY_PHYS_ADDRESS
+static void __iomem *apb2ser0_address;
+#endif /* APB2SER_PHY_PHYS_ADDRESS */
+
 #define WFC_TIMEOUT (400000)
 
+static DEFINE_RAW_SPINLOCK(ncr_spin_lock);
+static unsigned long flags;
+
 #define LOCK_DOMAIN 0
 
 typedef union {
@@ -88,11 +96,19 @@ typedef union {
 #ifdef CONFIG_ARM
 
 /*
+ * like iowrite32be but without the barrier.
+ * The iowmb barrier in the standard macro includes a outer_cache_sync
+ * which we don't want for Axxia register IO.
+ */
+#define axxia_write32be(v, p) \
+       ({  __raw_writel((__force __u32)cpu_to_be32(v), p); })
+
+/*
   ----------------------------------------------------------------------
   ncr_register_read
 */
 
-unsigned long
+inline unsigned long
 ncr_register_read(unsigned *address)
 {
        unsigned long value;
@@ -108,9 +124,10 @@ ncr_register_read(unsigned *address)
 */
 
 void
-ncr_register_write(const unsigned value, unsigned *address)
+inline ncr_register_write(const unsigned value, unsigned *address)
 {
-       iowrite32be(value, address);
+       axxia_write32be(value, address);
+       asm volatile ("mcr p15,0,%0,c7,c5,4" : : "r" (0));  /* isb */
 
        return;
 }
@@ -122,7 +139,7 @@ ncr_register_write(const unsigned value, unsigned *address)
   ncr_register_read
 */
 
-unsigned long
+inline unsigned long
 ncr_register_read(unsigned *address)
 {
        unsigned long value;
@@ -137,7 +154,7 @@ ncr_register_read(unsigned *address)
   ncr_register_write
 */
 
-void
+inline void
 ncr_register_write(const unsigned value, unsigned *address)
 {
        out_be32(address, value);
@@ -157,16 +174,43 @@ ncr_lock(int domain)
 {
        unsigned long offset;
        unsigned long value;
-       int loops = 10000;
+       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+       command_data_register_0_t cdr0;
 
+       raw_spin_lock_irqsave(&ncr_spin_lock, flags);
        offset = (0xff80 + (domain * 4));
 
        do {
                value = ncr_register_read((unsigned *)(nca_address + offset));
-       } while ((0 != value) && (0 < --loops));
+       } while ((0 != value) && (time_before(jiffies, timeout)));
+
+       if (!(time_before(jiffies, timeout))) {
+               raw_spin_unlock_irqrestore(&ncr_spin_lock, flags);
+               pr_err("ncr_lock() Timeout!\n");
+               BUG();
 
-       if (0 == loops)
                return -1;
+       }
+       /*
+         Make sure any previous commands completed, and check for errors.
+       */
+       timeout = jiffies + msecs_to_jiffies(1000);
+
+       do {
+               cdr0.raw =
+                       ncr_register_read((unsigned *)(nca_address + 0xf0));
+       } while ((0x1 == cdr0.bits.status) &&
+               (time_before(jiffies, timeout)));
+
+       if (!(time_before(jiffies, timeout))) {
+               raw_spin_unlock_irqrestore(&ncr_spin_lock, flags);
+               pr_err("ncr_lock() Previous command didn't complete!\n");
+               BUG();
+
+               return -1;
+       }
+       if (0x2 == cdr0.bits.status)
+               pr_err("Previous ncr access failed!\n");
 
        return 0;
 }
@@ -183,6 +227,7 @@ ncr_unlock(int domain)
 
        offset = (0xff80 + (domain * 4));
        ncr_register_write(0, (unsigned *)(nca_address + offset));
+       raw_spin_unlock_irqrestore(&ncr_spin_lock, flags);
 
        return;
 }
@@ -210,73 +255,171 @@ ncr_read(unsigned long region, unsigned long address, 
int number,
        int wfc_timeout = WFC_TIMEOUT;
 
        if (NULL == nca_address)
-               nca_address = ioremap(NCA_PHYS_ADDRESS, 0x20000);
-
-       if (0 != ncr_lock(LOCK_DOMAIN))
                return -1;
 
-       /*
-         Set up the read command.
-       */
-
-       cdr2.raw = 0;
-       cdr2.bits.target_node_id = NCP_NODE_ID(region);
-       cdr2.bits.target_id_address_upper = NCP_TARGET_ID(region);
-       ncr_register_write(cdr2.raw, (unsigned *) (nca_address + 0xf8));
-
-       cdr1.raw = 0;
-       cdr1.bits.target_address = (address >> 2);
-       ncr_register_write(cdr1.raw, (unsigned *) (nca_address + 0xf4));
-
-       cdr0.raw = 0;
-       cdr0.bits.start_done = 1;
-
-       if (0xff == cdr2.bits.target_id_address_upper)
-               cdr0.bits.local_bit = 1;
-
-       cdr0.bits.cmd_type = 4;
-       /* TODO: Verify number... */
-       cdr0.bits.dbs = (number - 1);
-       ncr_register_write(cdr0.raw, (unsigned *) (nca_address + 0xf0));
-       mb();
-
-       /*
-         Wait for completion.
-       */
+#ifdef APB2SER_PHY_PHYS_ADDRESS
+       if (NULL == apb2ser0_address)
+               return -1;
+#endif /* APB2SER_PHY_PHYS_ADDRESS */
 
-       do {
-               --wfc_timeout;
-       } while ((0x80000000UL ==
-                 ncr_register_read((unsigned *)(nca_address + 0xf0))) &&
-                0 < wfc_timeout);
+       if (0 != ncr_lock(LOCK_DOMAIN))
+               return -1;
 
-       if (0 == wfc_timeout) {
+       if ((NCP_NODE_ID(region) != 0x0153) && (NCP_NODE_ID(region) != 0x115)) {
+               /*
+               Set up the read command.
+               */
+
+               cdr2.raw = 0;
+               cdr2.bits.target_node_id = NCP_NODE_ID(region);
+               cdr2.bits.target_id_address_upper = NCP_TARGET_ID(region);
+               ncr_register_write(cdr2.raw, (unsigned *) (nca_address + 0xf8));
+
+               cdr1.raw = 0;
+               cdr1.bits.target_address = (address >> 2);
+               ncr_register_write(cdr1.raw, (unsigned *) (nca_address + 0xf4));
+
+               cdr0.raw = 0;
+               cdr0.bits.start_done = 1;
+
+               if (0xff == cdr2.bits.target_id_address_upper)
+                       cdr0.bits.local_bit = 1;
+
+               cdr0.bits.cmd_type = 4;
+               /* TODO: Verify number... */
+               cdr0.bits.dbs = (number - 1);
+               ncr_register_write(cdr0.raw, (unsigned *) (nca_address + 0xf0));
+               mb();
+
+               /*
+               Wait for completion.
+               */
+
+               do {
+                       --wfc_timeout;
+                       cdr0.raw =
+                               ncr_register_read((unsigned *)
+                                                 (nca_address + 0xf0));
+               } while (1 == cdr0.bits.start_done && 0 < wfc_timeout);
+
+               if (0 == wfc_timeout) {
+                       ncr_unlock(LOCK_DOMAIN);
+                       pr_err("ncr_read() Timeout!\n");
+                       BUG();
+
+                       return -1;
+               }
+
+               if (0x3 != cdr0.bits.status) {
+                       ncr_unlock(LOCK_DOMAIN);
+                       pr_err("ncr_write() failed: 0x%x\n",
+                              cdr0.bits.status);
+
+                       return -1;
+               }
+
+               /*
+               Copy data words to the buffer.
+               */
+
+               address = (unsigned long)(nca_address + 0x1000);
+               while (4 <= number) {
+                       *((unsigned long *) buffer) =
+                               ncr_register_read((unsigned *) address);
+                       address += 4;
+                       buffer += 4;
+                       number -= 4;
+               }
+
+               if (0 < number) {
+                       unsigned long temp =
+                               ncr_register_read((unsigned *) address);
+                       memcpy((void *) buffer, &temp, number);
+               }
+       } else {
+#ifdef APB2SER_PHY_PHYS_ADDRESS
+               if (NCP_NODE_ID(region) != 0x115) {
+                       void __iomem *targ_address = apb2ser0_address +
+                               (address & (~0x3));
+                       /*
+                       * Copy data words to the buffer.
+                       */
+
+                       while (4 <= number) {
+                               *((unsigned long *) buffer) =
+                                       *((unsigned long *) targ_address);
+                               targ_address += 4;
+                               number -= 4;
+                       }
+               } else {
+                       void __iomem *base;
+                       if (0xffff < address) {
+                               ncr_unlock(LOCK_DOMAIN);
+                               return -1;
+                       }
+
+                       switch (NCP_TARGET_ID(region)) {
+                       case 0:
+                               base = (apb2ser0_address + 0x1e0);
+                               break;
+                       case 1:
+                               base = (apb2ser0_address + 0x1f0);
+                               break;
+                       case 2:
+                               base = (apb2ser0_address + 0x200);
+                               break;
+                       case 3:
+                               base = (apb2ser0_address + 0x210);
+                               break;
+                       case 4:
+                               base = (apb2ser0_address + 0x220);
+                               break;
+                       case 5:
+                               base = (apb2ser0_address + 0x230);
+                               break;
+                       default:
+                               ncr_unlock(LOCK_DOMAIN);
+                               return -1;
+                       }
+                       if ((NCP_TARGET_ID(region) == 0x1) ||
+                               (NCP_TARGET_ID(region) == 0x4)) {
+                               writel((0x84c00000 + address), (base + 4));
+                       } else {
+                               writel((0x85400000 + address), (base + 4));
+                       }
+                       do {
+                               --wfc_timeout;
+                               *((unsigned long *) buffer) =
+                                       readl(base + 4);
+                       } while (0 != (*((unsigned long *) buffer) & 0x80000000)
+                                       && 0 < wfc_timeout);
+
+                       if (0 == wfc_timeout) {
+                               ncr_unlock(LOCK_DOMAIN);
+                               return -1;
+                       }
+
+                       if ((NCP_TARGET_ID(region) == 0x1) ||
+                               (NCP_TARGET_ID(region) == 0x4)) {
+                               *((unsigned short *) buffer) =
+                                       readl(base + 8);
+                       } else {
+                               *((unsigned long *) buffer) =
+                                       readl(base + 8);
+                       }
+
+               }
+#else
                ncr_unlock(LOCK_DOMAIN);
                return -1;
-       }
-
-       /*
-         Copy data words to the buffer.
-       */
-
-       address = (unsigned long)(nca_address + 0x1000);
-       while (4 <= number) {
-               *((unsigned long *) buffer) =
-                       ncr_register_read((unsigned *) address);
-               address += 4;
-               number -= 4;
-       }
-
-       if (0 < number) {
-               unsigned long temp =
-                       ncr_register_read((unsigned *) address);
-               memcpy((void *) buffer, &temp, number);
+#endif /* APB2SER_PHY_PHYS_ADDRESS */
        }
 
        ncr_unlock(LOCK_DOMAIN);
 
        return 0;
 }
+EXPORT_SYMBOL(ncr_read);
 
 /*
   ----------------------------------------------------------------------
@@ -295,94 +438,176 @@ ncr_write(unsigned long region, unsigned long address, 
int number,
        int wfc_timeout = WFC_TIMEOUT;
 
        if (NULL == nca_address)
-               nca_address = ioremap(NCA_PHYS_ADDRESS, 0x20000);
-
-       if (0 != ncr_lock(LOCK_DOMAIN))
                return -1;
 
-       /*
-         Set up the write.
-       */
-
-       cdr2.raw = 0;
-       cdr2.bits.target_node_id = NCP_NODE_ID(region);
-       cdr2.bits.target_id_address_upper = NCP_TARGET_ID(region);
-       ncr_register_write(cdr2.raw, (unsigned *) (nca_address + 0xf8));
-
-       cdr1.raw = 0;
-       cdr1.bits.target_address = (address >> 2);
-       ncr_register_write(cdr1.raw, (unsigned *) (nca_address + 0xf4));
-
-       /*
-         Copy from buffer to the data words.
-       */
-
-       data_word_base = (unsigned long)(nca_address + 0x1000);
-
-       while (4 <= number) {
-               ncr_register_write(*((unsigned long *) buffer),
-                                  (unsigned *) data_word_base);
-               data_word_base += 4;
-               buffer += 4;
-               number -= 4;
-       }
-
-       if (0 < number) {
-               unsigned long temp = 0;
-
-               memcpy((void *) &temp, (void *) buffer, number);
-               ncr_register_write(temp, (unsigned *) data_word_base);
-               data_word_base += number;
-               buffer += number;
-               number = 0;
-       }
-
-       cdr0.raw = 0;
-       cdr0.bits.start_done = 1;
-
-       if (0xff == cdr2.bits.target_id_address_upper)
-               cdr0.bits.local_bit = 1;
-
-       cdr0.bits.cmd_type = 5;
-       /* TODO: Verify number... */
-       cdr0.bits.dbs = dbs;
-       ncr_register_write(cdr0.raw, (unsigned *) (nca_address + 0xf0));
-       mb();
-
-       /*
-         Wait for completion.
-       */
-
-       do {
-               --wfc_timeout;
-       } while ((0x80000000UL ==
-                 ncr_register_read((unsigned *)(nca_address + 0xf0))) &&
-                0 < wfc_timeout);
-
-       if (0 == wfc_timeout) {
-               ncr_unlock(LOCK_DOMAIN);
+#ifdef APB2SER_PHY_PHYS_ADDRESS
+       if (NULL == apb2ser0_address)
                return -1;
-       }
+#endif /* APB2SER_PHY_PHYS_ADDRESS */
 
-       /*
-         Check status.
-       */
-
-       if (0x3 !=
-           ((ncr_register_read((unsigned *) (nca_address + 0xf0)) &
-               0x00c00000) >> 22)) {
-               unsigned long status;
+       if (0 != ncr_lock(LOCK_DOMAIN))
+               return -1;
 
-               status = ncr_register_read((unsigned *)(nca_address + 0xe4));
+       if ((NCP_NODE_ID(region) != 0x0153) && (NCP_NODE_ID(region) != 0x115)) {
+               /*
+                 Set up the write.
+               */
+
+               cdr2.raw = 0;
+               cdr2.bits.target_node_id = NCP_NODE_ID(region);
+               cdr2.bits.target_id_address_upper = NCP_TARGET_ID(region);
+               ncr_register_write(cdr2.raw, (unsigned *) (nca_address + 0xf8));
+
+               cdr1.raw = 0;
+               cdr1.bits.target_address = (address >> 2);
+               ncr_register_write(cdr1.raw, (unsigned *) (nca_address + 0xf4));
+
+               /*
+                 Copy from buffer to the data words.
+               */
+
+               data_word_base = (unsigned long)(nca_address + 0x1000);
+
+               while (4 <= number) {
+                       ncr_register_write(*((unsigned long *) buffer),
+                                       (unsigned *) data_word_base);
+                       data_word_base += 4;
+                       buffer += 4;
+                       number -= 4;
+               }
+
+               if (0 < number) {
+                       unsigned long temp = 0;
+
+                       memcpy((void *) &temp, (void *) buffer, number);
+                       ncr_register_write(temp, (unsigned *) data_word_base);
+                       data_word_base += number;
+                       buffer += number;
+                       number = 0;
+               }
+
+               cdr0.raw = 0;
+               cdr0.bits.start_done = 1;
+
+               if (0xff == cdr2.bits.target_id_address_upper)
+                       cdr0.bits.local_bit = 1;
+
+               cdr0.bits.cmd_type = 5;
+               /* TODO: Verify number... */
+               cdr0.bits.dbs = dbs;
+               ncr_register_write(cdr0.raw, (unsigned *) (nca_address + 0xf0));
+               mb();
+
+               /*
+               Wait for completion.
+               */
+
+               do {
+                       --wfc_timeout;
+                       cdr0.raw =
+                               ncr_register_read((unsigned *)
+                                                 (nca_address + 0xf0));
+               } while (1 == cdr0.bits.start_done && 0 < wfc_timeout);
+
+               if (0 == wfc_timeout) {
+                       ncr_unlock(LOCK_DOMAIN);
+                       pr_err("ncr_write() Timeout!\n");
+                       BUG();
+
+                       return -1;
+               }
+
+               /*
+               Check status.
+               */
+
+               if ((0x3 != cdr0.bits.status) && (0x00c00000) >> 22) {
+                       unsigned long status;
+
+                       status = ncr_register_read((unsigned *)(nca_address +
+                                                               0xe4));
+                       ncr_unlock(LOCK_DOMAIN);
+                       pr_err("ncr_write() Error: 0x%x 0x%lx\n",
+                              cdr0.bits.status, status);
+
+                       return status;
+               }
+       } else {
+#ifdef APB2SER_PHY_PHYS_ADDRESS
+       if (NCP_NODE_ID(region) != 0x115) {
+               void __iomem *targ_address = apb2ser0_address +
+                                            (address & (~0x3));
+               /*
+                 Copy from buffer to the data words.
+               */
+
+               while (4 <= number) {
+                       *((unsigned long *) targ_address) =
+                               *((unsigned long *) buffer);
+                       targ_address += 4;
+                       number -= 4;
+               }
+       } else {
+               void __iomem *base;
+               if (0xffff < address) {
+                       ncr_unlock(LOCK_DOMAIN);
+                       return -1;
+               }
+
+               switch (NCP_TARGET_ID(region)) {
+               case 0:
+                       base = (apb2ser0_address + 0x1e0);
+                       break;
+               case 1:
+                       base = (apb2ser0_address + 0x1f0);
+                       break;
+               case 2:
+                       base = (apb2ser0_address + 0x200);
+                       break;
+               case 3:
+                       base = (apb2ser0_address + 0x210);
+                       break;
+               case 4:
+                       base = (apb2ser0_address + 0x220);
+                       break;
+               case 5:
+                       base = (apb2ser0_address + 0x230);
+                       break;
+               default:
+                       ncr_unlock(LOCK_DOMAIN);
+                       return -1;
+               }
+               if ((NCP_TARGET_ID(region) == 0x1) ||
+                               (NCP_TARGET_ID(region) == 0x4)) {
+                       writel(*((unsigned short *) buffer), base);
+                       writel((0xc4c00000 + address), (base + 4));
+               } else {
+                       writel(*((unsigned long *) buffer), base);
+                       writel((0xc5400000 + address), (base + 4));
+               }
+                       do {
+                               --wfc_timeout;
+                               *((unsigned long *) buffer) =
+                                       readl(base + 4);
+                       } while (0 != (*((unsigned long *) buffer) & 0x80000000)
+                               && 0 < wfc_timeout);
+
+                       if (0 == wfc_timeout) {
+                               ncr_unlock(LOCK_DOMAIN);
+                               return -1;
+                       }
+               }
+#else
                ncr_unlock(LOCK_DOMAIN);
-
-               return status;
+               return -1;
+#endif /* APB2SER_PHY_PHYS_ADDRESS */
        }
 
        ncr_unlock(LOCK_DOMAIN);
 
        return 0;
 }
+EXPORT_SYMBOL(ncr_write);
 
 /*
   ----------------------------------------------------------------------
@@ -394,9 +619,16 @@ ncr_init(void)
 {
        nca_address = ioremap(NCA_PHYS_ADDRESS, 0x20000);
 
+#ifdef APB2SER_PHY_PHYS_ADDRESS
+       apb2ser0_address = ioremap(APB2SER_PHY_PHYS_ADDRESS, 0x10000);
+#endif /* APB2SER_PHY_PHYS_ADDRESS */
+
+       pr_info("ncr: available\n");
+
        return 0;
 }
 
+
 module_init(ncr_init);
 
 /*
@@ -411,13 +643,18 @@ ncr_exit(void)
        if (NULL != nca_address)
                iounmap(nca_address);
 
+#ifdef APB2SER_PHY_PHYS_ADDRESS
+       /* Unmap the APB2SER0 PHY. */
+       if (NULL != apb2ser0_address)
+               iounmap(apb2ser0_address);
+#endif /* APB2SER_PHY_PHYS_ADDRESS */
+
        return;
 }
 
+
 module_exit(ncr_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Register Ring access for LSI's ACP board");
 
-EXPORT_SYMBOL(ncr_read);
-EXPORT_SYMBOL(ncr_write);
-- 
1.8.1.4

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to