[linux-yocto] [PATCH 45/52] misc: Updated lsi-ncr driver for ARM support
Daniel Dragomir
daniel.dragomir at windriver.com
Wed Jan 28 09:18:59 PST 2015
From: SangeethaRao <sangeetha.rao at 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.rao at 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
More information about the linux-yocto
mailing list