From patchwork Thu Dec 19 15:54:29 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter De Schrijver X-Patchwork-Id: 303583 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 8AC8B2C009B for ; Fri, 20 Dec 2013 02:55:22 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753842Ab3LSPy7 (ORCPT ); Thu, 19 Dec 2013 10:54:59 -0500 Received: from hqemgate16.nvidia.com ([216.228.121.65]:2885 "EHLO hqemgate16.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755479Ab3LSPy6 (ORCPT ); Thu, 19 Dec 2013 10:54:58 -0500 Received: from hqnvupgp08.nvidia.com (Not Verified[216.228.121.13]) by hqemgate16.nvidia.com id ; Thu, 19 Dec 2013 07:54:57 -0800 Received: from hqemhub03.nvidia.com ([172.20.12.94]) by hqnvupgp08.nvidia.com (PGP Universal service); Thu, 19 Dec 2013 07:56:12 -0800 X-PGP-Universal: processed; by hqnvupgp08.nvidia.com on Thu, 19 Dec 2013 07:56:12 -0800 Received: from hqnvemgw02.nvidia.com (172.16.227.111) by HQEMHUB03.nvidia.com (172.20.150.15) with Microsoft SMTP Server id 8.3.327.1; Thu, 19 Dec 2013 07:54:57 -0800 Received: from thelma.nvidia.com (Not Verified[172.16.212.77]) by hqnvemgw02.nvidia.com with MailMarshal (v7,1,2,5326) id ; Thu, 19 Dec 2013 07:54:57 -0800 Received: from tbergstrom-lnx.nvidia.com (tbergstrom-lnx.nvidia.com [10.21.24.170]) by thelma.nvidia.com (8.13.8+Sun/8.8.8) with ESMTP id rBJFsej9009131; Thu, 19 Dec 2013 07:54:52 -0800 (PST) From: Peter De Schrijver To: Peter De Schrijver CC: , , , Russell King , Stephen Warren , Thierry Reding , Andrew Morton , Linus Walleij , Hiroshi Doyu , Wolfram Sang , Prashant Gaikwad Subject: [PATCH 1/6] ARM: tegra: export apb dma readl/writel Date: Thu, 19 Dec 2013 17:54:29 +0200 Message-ID: <1387468474-26521-2-git-send-email-pdeschrijver@nvidia.com> X-Mailer: git-send-email 1.7.7.rc0.72.g4b5ea.dirty In-Reply-To: <1387468474-26521-1-git-send-email-pdeschrijver@nvidia.com> References: <1387468474-26521-1-git-send-email-pdeschrijver@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 Sender: linux-tegra-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-tegra@vger.kernel.org Export APB DMA readl and writel. These are needed because we can't access the fuses directly on Tegra20 without potentially causing a system hang. Signed-off-by: Peter De Schrijver --- arch/arm/mach-tegra/apbio.c | 51 ++++++++++++++++++++++++++---------------- include/linux/tegra-soc.h | 16 +++++++++++++ 2 files changed, 47 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c index bc47197..e0bf49d 100644 --- a/arch/arm/mach-tegra/apbio.c +++ b/arch/arm/mach-tegra/apbio.c @@ -32,8 +32,8 @@ static u32 *tegra_apb_bb; static dma_addr_t tegra_apb_bb_phys; static DECLARE_COMPLETION(tegra_apb_wait); -static u32 tegra_apb_readl_direct(unsigned long offset); -static void tegra_apb_writel_direct(u32 value, unsigned long offset); +static int tegra_apb_readl_direct(unsigned long offset, u32 *value); +static int tegra_apb_writel_direct(u32 value, unsigned long offset); static struct dma_chan *tegra_apb_dma_chan; static struct dma_slave_config dma_sconfig; @@ -128,58 +128,64 @@ static int do_dma_transfer(unsigned long apb_add, return 0; } -static u32 tegra_apb_readl_using_dma(unsigned long offset) +int tegra_apb_readl_using_dma(unsigned long offset, u32 *value) { int ret; if (!tegra_apb_dma_chan && !tegra_apb_dma_init()) - return tegra_apb_readl_direct(offset); + return tegra_apb_readl_direct(offset, value); mutex_lock(&tegra_apb_dma_lock); ret = do_dma_transfer(offset, DMA_DEV_TO_MEM); - if (ret < 0) { + if (ret < 0) pr_err("error in reading offset 0x%08lx using dma\n", offset); - *(u32 *)tegra_apb_bb = 0; - } + else + *value = *tegra_apb_bb; + mutex_unlock(&tegra_apb_dma_lock); - return *((u32 *)tegra_apb_bb); + + return ret; } -static void tegra_apb_writel_using_dma(u32 value, unsigned long offset) +int tegra_apb_writel_using_dma(u32 value, unsigned long offset) { int ret; - if (!tegra_apb_dma_chan && !tegra_apb_dma_init()) { - tegra_apb_writel_direct(value, offset); - return; - } + if (!tegra_apb_dma_chan && !tegra_apb_dma_init()) + return tegra_apb_writel_direct(value, offset); mutex_lock(&tegra_apb_dma_lock); *((u32 *)tegra_apb_bb) = value; ret = do_dma_transfer(offset, DMA_MEM_TO_DEV); + mutex_unlock(&tegra_apb_dma_lock); if (ret < 0) pr_err("error in writing offset 0x%08lx using dma\n", offset); - mutex_unlock(&tegra_apb_dma_lock); + + return ret; } #else #define tegra_apb_readl_using_dma tegra_apb_readl_direct #define tegra_apb_writel_using_dma tegra_apb_writel_direct #endif -typedef u32 (*apbio_read_fptr)(unsigned long offset); -typedef void (*apbio_write_fptr)(u32 value, unsigned long offset); +typedef int (*apbio_read_fptr)(unsigned long offset, u32 *value); +typedef int (*apbio_write_fptr)(u32 value, unsigned long offset); static apbio_read_fptr apbio_read; static apbio_write_fptr apbio_write; -static u32 tegra_apb_readl_direct(unsigned long offset) +static int tegra_apb_readl_direct(unsigned long offset, u32 *value) { - return readl(IO_ADDRESS(offset)); + *value = readl(IO_ADDRESS(offset)); + + return 0; } -static void tegra_apb_writel_direct(u32 value, unsigned long offset) +static int tegra_apb_writel_direct(u32 value, unsigned long offset) { writel(value, IO_ADDRESS(offset)); + + return 0; } void tegra_apb_io_init(void) @@ -197,7 +203,12 @@ void tegra_apb_io_init(void) u32 tegra_apb_readl(unsigned long offset) { - return apbio_read(offset); + u32 val; + + if (apbio_read(offset, &val) < 0) + return 0; + else + return val; } void tegra_apb_writel(u32 value, unsigned long offset) diff --git a/include/linux/tegra-soc.h b/include/linux/tegra-soc.h index 95f611d..f53fe9c 100644 --- a/include/linux/tegra-soc.h +++ b/include/linux/tegra-soc.h @@ -19,4 +19,20 @@ u32 tegra_read_chipid(void); + +#if defined(CONFIG_TEGRA20_APB_DMA) +void tegra_apb_io_init(void); +int tegra_apb_readl_using_dma(unsigned long offset, u32 *value); +int tegra_apb_writel_using_dma(u32 value, unsigned long offset); +#else +static inline void tegra_apb_io_init(void) {} +static inline int tegra_apb_readl_using_dma(unsigned long offset, u32 *value) +{ + return -EINVAL; +} +static inline int tegra_apb_writel_using_dma(u32 value, unsigned long offset) +{ + return -EINVAL; +} +#endif #endif /* __LINUX_TEGRA_SOC_H_ */