[linux-yocto] [PATCH 54/87] lsi/ncr: add support to read/write access to configuration ring resources
Bruce Ashfield
bruce.ashfield at windriver.com
Mon May 27 12:12:19 PDT 2013
On 13-05-27 12:56 PM, Paul Butler wrote:
> From: Jiang Lu <lu.jiang at 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.jiang at 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");
>
More information about the linux-yocto
mailing list