From 2c20b5b7c68a45e70a56df7a9c197c06e5a81290 Mon Sep 17 00:00:00 2001 From: Zhao Qiang Date: Wed, 13 Aug 2014 17:29:18 +0800 Subject: qe_common: add qe common functions to qe_common.c qe need to call some common functions, move them into public directory, add a new file drivers/soc/qe/qe_common.c for them. Signed-off-by: Zhao Qiang --- upstream link: http://patchwork.ozlabs.org/patch/393169/ it is under discussion. Change-Id: Ib2b252f355921291b596d8ddc6bbe17aa53384b2 Reviewed-on: http://git.am.freescale.net:8181/16840 Tested-by: Review Code-CDREVIEW Reviewed-by: Xiaobo Xie Reviewed-by: Zhengxiong Jin diff --git a/drivers/soc/qe/Makefile b/drivers/soc/qe/Makefile index f1855c1..77f6fd9 100644 --- a/drivers/soc/qe/Makefile +++ b/drivers/soc/qe/Makefile @@ -1,7 +1,7 @@ # # Makefile for the linux ppc-specific parts of QE # -obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_ic.o qe_io.o +obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_ic.o qe_io.o qe_common.o obj-$(CONFIG_UCC) += ucc.o obj-$(CONFIG_UCC_SLOW) += ucc_slow.o diff --git a/drivers/soc/qe/qe_common.c b/drivers/soc/qe/qe_common.c new file mode 100644 index 0000000..c82ddcc --- /dev/null +++ b/drivers/soc/qe/qe_common.c @@ -0,0 +1,185 @@ +/* + * Common QE code + * + * Author: Scott Wood + * + * Copyright 2007-2008,2010 Freescale Semiconductor, Inc. + * + * Some parts derived from commproc.c/cpm2_common.c, which is: + * Copyright (c) 1997 Dan error_act (dmalek@jlc.net) + * Copyright (c) 1999-2001 Dan Malek + * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com) + * 2006 (c) MontaVista Software, Inc. + * Vitaly Bordug + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static spinlock_t qe_muram_lock; +static rh_block_t qe_boot_muram_rh_block[16]; +static rh_info_t qe_muram_info; +static u8 __iomem *muram_vbase; +static phys_addr_t muram_pbase; + +/* Max address size we deal with */ +#define OF_MAX_ADDR_CELLS 4 + +int qe_muram_init(void) +{ + struct device_node *np; + struct resource r; + u32 zero[OF_MAX_ADDR_CELLS] = {}; + resource_size_t max = 0; + int i = 0; + int ret = 0; + + if (muram_pbase) + return 0; + + spin_lock_init(&qe_muram_lock); + /* initialize the info header */ + rh_init(&qe_muram_info, 1, + sizeof(qe_boot_muram_rh_block) / + sizeof(qe_boot_muram_rh_block[0]), + qe_boot_muram_rh_block); + + np = of_find_compatible_node(NULL, NULL, "fsl,qe-muram-data"); + if (!np) { + /* try legacy bindings */ + np = of_find_node_by_name(NULL, "data-only"); + if (!np) { + pr_err("Cannot find CPM muram data node"); + ret = -ENODEV; + goto out; + } + } + + muram_pbase = of_translate_address(np, zero); + if (muram_pbase == (phys_addr_t)OF_BAD_ADDR) { + pr_err("Cannot translate zero through CPM muram node"); + ret = -ENODEV; + goto out; + } + + while (of_address_to_resource(np, i++, &r) == 0) { + if (r.end > max) + max = r.end; + + rh_attach_region(&qe_muram_info, r.start - muram_pbase, + resource_size(&r)); + } + + muram_vbase = ioremap(muram_pbase, max - muram_pbase + 1); + if (!muram_vbase) { + pr_err("Cannot map CPM muram"); + ret = -ENOMEM; + } + +out: + of_node_put(np); + return ret; +} + +/** + * qe_muram_alloc - allocate the requested size worth of multi-user ram + * @size: number of bytes to allocate + * @align: requested alignment, in bytes + * + * This function returns an offset into the muram area. + * Use qe_dpram_addr() to get the virtual address of the area. + * Use qe_muram_free() to free the allocation. + */ +unsigned long qe_muram_alloc(unsigned long size, unsigned long align) +{ + unsigned long start; + unsigned long flags; + + spin_lock_irqsave(&qe_muram_lock, flags); + qe_muram_info.alignment = align; + start = rh_alloc(&qe_muram_info, size, "commproc"); + memset(qe_muram_addr(start), 0, size); + spin_unlock_irqrestore(&qe_muram_lock, flags); + + return start; +} +EXPORT_SYMBOL(qe_muram_alloc); + +/** + * qe_muram_free - free a chunk of multi-user ram + * @offset: The beginning of the chunk as returned by qe_muram_alloc(). + */ +int qe_muram_free(unsigned long offset) +{ + int ret; + unsigned long flags; + + spin_lock_irqsave(&qe_muram_lock, flags); + ret = rh_free(&qe_muram_info, offset); + spin_unlock_irqrestore(&qe_muram_lock, flags); + + return ret; +} +EXPORT_SYMBOL(qe_muram_free); + +/** + * qe_muram_alloc_fixed - reserve a specific region of multi-user ram + * @offset: the offset into the muram area to reserve + * @size: the number of bytes to reserve + * + * This function returns "start" on success, -ENOMEM on failure. + * Use qe_dpram_addr() to get the virtual address of the area. + * Use qe_muram_free() to free the allocation. + */ +unsigned long qe_muram_alloc_fixed(unsigned long offset, unsigned long size) +{ + unsigned long start; + unsigned long flags; + + spin_lock_irqsave(&qe_muram_lock, flags); + qe_muram_info.alignment = 1; + start = rh_alloc_fixed(&qe_muram_info, offset, size, "commproc"); + spin_unlock_irqrestore(&qe_muram_lock, flags); + + return start; +} +EXPORT_SYMBOL(qe_muram_alloc_fixed); + +/** + * qe_muram_addr - turn a muram offset into a virtual address + * @offset: muram offset to convert + */ +void __iomem *qe_muram_addr(unsigned long offset) +{ + return muram_vbase + offset; +} +EXPORT_SYMBOL(qe_muram_addr); + +unsigned long qe_muram_offset(void __iomem *addr) +{ + return addr - (void __iomem *)muram_vbase; +} +EXPORT_SYMBOL(qe_muram_offset); + +/** + * qe_muram_dma - turn a muram virtual address into a DMA address + * @offset: virtual address from qe_muram_addr() to convert + */ +dma_addr_t qe_muram_dma(void __iomem *addr) +{ + return muram_pbase + ((u8 __iomem *)addr - muram_vbase); +} +EXPORT_SYMBOL(qe_muram_dma); diff --git a/include/linux/fsl/qe.h b/include/linux/fsl/qe.h index c96ff9e..5a6a647 100644 --- a/include/linux/fsl/qe.h +++ b/include/linux/fsl/qe.h @@ -19,7 +19,8 @@ #include #include #include -#include +#include +#include #include #define QE_NUM_OF_SNUM 256 /* There are 256 serial number in QE */ @@ -190,13 +191,48 @@ static inline int qe_alive_during_sleep(void) #endif } -/* we actually use cpm_muram implementation, define this for convenience */ -#define qe_muram_init cpm_muram_init -#define qe_muram_alloc cpm_muram_alloc -#define qe_muram_alloc_fixed cpm_muram_alloc_fixed -#define qe_muram_free cpm_muram_free -#define qe_muram_addr cpm_muram_addr -#define qe_muram_offset cpm_muram_offset +int qe_muram_init(void); + +#if defined(CONFIG_QUICC_ENGINE) +unsigned long qe_muram_alloc(unsigned long size, unsigned long align); +int qe_muram_free(unsigned long offset); +unsigned long qe_muram_alloc_fixed(unsigned long offset, unsigned long size); +void __iomem *qe_muram_addr(unsigned long offset); +unsigned long qe_muram_offset(void __iomem *addr); +dma_addr_t qe_muram_dma(void __iomem *addr); +#else +static inline unsigned long qe_muram_alloc(unsigned long size, + unsigned long align) +{ + return -ENOSYS; +} + +static inline int qe_muram_free(unsigned long offset) +{ + return -ENOSYS; +} + +static inline unsigned long qe_muram_alloc_fixed(unsigned long offset, + unsigned long size) +{ + return -ENOSYS; +} + +static inline void __iomem *qe_muram_addr(unsigned long offset) +{ + return NULL; +} + +static inline unsigned long qe_muram_offset(void __iomem *addr) +{ + return -ENOSYS; +} + +static inline dma_addr_t qe_muram_dma(void __iomem *addr) +{ + return 0; +} +#endif /* defined(CONFIG_QUICC_ENGINE) */ /* Structure that defines QE firmware binary files. * -- cgit v0.10.2