[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