[PATCH 1/6] ARM: tegra: export apb dma readl/writel

2013-12-19 Thread Peter De Schrijver
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(_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(_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(_apb_dma_lock);
*((u32 *)tegra_apb_bb) = value;
ret = do_dma_transfer(offset, DMA_MEM_TO_DEV);
+   mutex_unlock(_apb_dma_lock);
if (ret < 0)
pr_err("error in writing offset 0x%08lx using dma\n", offset);
-   mutex_unlock(_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, ) < 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_ */
-- 
1.7.7.rc0.72.g4b5ea.dirty

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/6] ARM: tegra: export apb dma readl/writel

2013-12-19 Thread Peter De Schrijver
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 pdeschrij...@nvidia.com
---
 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_ */
-- 
1.7.7.rc0.72.g4b5ea.dirty

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/