On 13-05-27 12:56 PM, Paul Butler wrote:
From: Jiang Lu <lu.ji...@windriver.com>

Extracted from lsi.patch in lsi_acp_linux_6.8.1.18 tarball.

This is typically an acceptable "upstream reference", but I have to ask.
Is there a public location that we can point to for this tgz ?

Bruce


The Nuevo CPU Adapter (NCA) is the hardware engine that connects the
powerpc complex with the ACP3400 data patch accellerator engines.
This driver provides the CPU with read/write access to configuration
ring resources via NCA configuration commands.

[Jiang:
        * Get the nca register virtual address by using ioremap instead
        of using a fixed virtual address bolted in tlb entry.
        * Move from driver/lsi/acp.c to arch/powerpc/sysdev/lsi_acp_ncr.c]

Signed-off-by: Jiang Lu <lu.ji...@windriver.com>
---
  arch/powerpc/include/asm/lsi/acp_ncr.h |  42 ++++
  arch/powerpc/sysdev/Makefile           |   2 +
  arch/powerpc/sysdev/lsi_acp_ncr.c      | 375 +++++++++++++++++++++++++++++++++
  3 files changed, 419 insertions(+)
  create mode 100644 arch/powerpc/include/asm/lsi/acp_ncr.h
  create mode 100644 arch/powerpc/sysdev/lsi_acp_ncr.c

diff --git a/arch/powerpc/include/asm/lsi/acp_ncr.h 
b/arch/powerpc/include/asm/lsi/acp_ncr.h
new file mode 100644
index 0000000..a7399e7
--- /dev/null
+++ b/arch/powerpc/include/asm/lsi/acp_ncr.h
@@ -0,0 +1,42 @@
+/*
+ * asm/lsi/acp_ncr.h
+ *
+ * Copyright (C) 2010 LSI
+ *
+ * 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
+ */
+
+#ifndef __DRIVERS_LSI_ACP_NCR_H
+#define __DRIVERS_LSI_ACP_NCR_H
+
+#ifndef NCP_REGION_ID
+#define NCP_REGION_ID(node, target) \
+(unsigned long)((((node) & 0xffff) << 16) | ((target) & 0xffff))
+#endif
+
+#ifndef NCP_NODE_ID
+#define NCP_NODE_ID(region) (((region) >> 16) & 0xffff)
+#endif
+
+#ifndef NCP_TARGET_ID
+#define NCP_TARGET_ID(region) ((region) & 0xffff)
+#endif
+
+int ncr_read(unsigned long, unsigned long, int, void *);
+int ncr_write(unsigned long, unsigned long, int, void *);
+
+int is_asic(void);
+
+#endif /*  __DRIVERS_LSI_ACP_NCR_H */
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 1bd7ecb..af96e92 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -69,3 +69,5 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
  obj-$(CONFIG_PPC_XICS)                += xics/

  obj-$(CONFIG_GE_FPGA)         += ge/
+
+obj-$(CONFIG_ACP)              += lsi_acp_ncr.o
diff --git a/arch/powerpc/sysdev/lsi_acp_ncr.c 
b/arch/powerpc/sysdev/lsi_acp_ncr.c
new file mode 100644
index 0000000..9802110
--- /dev/null
+++ b/arch/powerpc/sysdev/lsi_acp_ncr.c
@@ -0,0 +1,375 @@
+/*
+ *  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/io.h>
+#include <linux/module.h>
+
+#include <include/asm/lsi/acp_ncr.h>
+
+static void __iomem *nca_address;
+
+#define WFC_TIMEOUT (400000)
+
+#define LOCK_DOMAIN 0
+
+union command_data_register_0 {
+       unsigned long raw;
+       struct {
+               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;
+       } __packed bits;
+} __packed;
+
+union command_data_register_1 {
+       unsigned long raw;
+       struct {
+               unsigned long target_address:32;
+       } __packed bits;
+} __packed;
+
+union command_data_register_2 {
+       unsigned long raw;
+       struct {
+               unsigned long unused:16;
+               unsigned long target_node_id:8;
+               unsigned long target_id_address_upper:8;
+       } __packed bits;
+} __packed;
+
+/*
+  ----------------------------------------------------------------------
+  ncr_register_read
+*/
+
+static inline unsigned long
+ncr_register_read(unsigned *address)
+{
+       unsigned long value;
+
+       value = in_be32(address);
+
+       return value;
+}
+
+/*
+  ----------------------------------------------------------------------
+  ncr_register_write
+*/
+
+static inline void
+ncr_register_write(const unsigned value, unsigned *address)
+{
+       out_be32(address, value);
+}
+
+/*
+  
------------------------------------------------------------------------------
+  ncr_lock
+*/
+
+static int
+ncr_lock(int domain)
+{
+       unsigned long offset;
+       unsigned long value;
+       int loops = 10000;
+
+       offset = (0xff80 + (domain * 4));
+
+       do {
+               value = ncr_register_read((unsigned *)(nca_address + offset));
+       } while ((0 != value) && (0 < --loops));
+
+       if (0 == loops)
+               return -1;
+
+       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));
+
+       return;
+}
+
+/*
+  ======================================================================
+  ======================================================================
+  Public Interface
+  ======================================================================
+  ======================================================================
+*/
+
+/*
+  ----------------------------------------------------------------------
+  ncr_read
+*/
+
+int
+ncr_read(unsigned long region, unsigned long address, int number, void *buffer)
+{
+       union command_data_register_0 cdr0;
+       union command_data_register_1 cdr1;
+       union command_data_register_2 cdr2;
+       int wfc_timeout = WFC_TIMEOUT;
+
+       if (NULL == nca_address)
+               nca_address = ioremap(0x002000520000ULL, 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.
+       */
+
+       do {
+               --wfc_timeout;
+       } while ((0x80000000UL ==
+                 ncr_register_read((unsigned *)(nca_address + 0xf0))) &&
+                0 < wfc_timeout);
+
+       if (0 == wfc_timeout) {
+               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);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(ncr_read);
+/*
+  
------------------------------------------------------------------------------
+  is_asic
+*/
+
+int
+is_asic(void)
+{
+#ifdef CONFIG_ACPISS
+       return 0;
+#else
+       unsigned long nca_config;
+
+       if (0 == ncr_read(NCP_REGION_ID(0x16, 0xff), 0x10, 4, &nca_config))
+               return (0 == (nca_config & 0x80000000));
+
+       return -1;
+#endif
+}
+EXPORT_SYMBOL(is_asic);
+
+/*
+  ----------------------------------------------------------------------
+  ncr_write
+*/
+
+int
+ncr_write(unsigned long region, unsigned long address, int number, void 
*buffer)
+{
+       union command_data_register_0 cdr0;
+       union command_data_register_1 cdr1;
+       union command_data_register_2 cdr2;
+       unsigned long data_word_base;
+       int dbs = (number - 1);
+       int wfc_timeout = WFC_TIMEOUT;
+
+       if (NULL == nca_address)
+               nca_address = ioremap(0x002000520000ULL, 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);
+               return -1;
+       }
+
+       /*
+         Check status.
+       */
+
+       if (0x3 !=
+           ((ncr_register_read((unsigned *) (nca_address + 0xf0)) &
+               0x00c00000) >> 22)) {
+               unsigned long status;
+
+               status = ncr_register_read((unsigned *)(nca_address + 0xe4));
+               ncr_unlock(LOCK_DOMAIN);
+
+               return status;
+       }
+
+       ncr_unlock(LOCK_DOMAIN);
+
+       return 0;
+}
+EXPORT_SYMBOL(ncr_write);
+
+/*
+  ----------------------------------------------------------------------
+  ncr_init
+*/
+
+int
+ncr_init(void)
+{
+       /* We need this to be a module so that the functions can be exported
+        * as module symbols.
+        */
+       return 0;
+}
+
+postcore_initcall(ncr_init);
+
+/*
+  ----------------------------------------------------------------------
+  ncr_exit
+*/
+
+void __exit
+ncr_exit(void)
+{
+       /* Unmap the NCA. */
+       iounmap(nca_address);
+}
+
+module_exit(ncr_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Register Ring access for LSI's ACP board");


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

Reply via email to