ARM: tegra: export apb dma readl/writel
authorPeter De Schrijver <pdeschrijver@nvidia.com>
Thu, 12 Jun 2014 15:36:35 +0000 (18:36 +0300)
committerThierry Reding <treding@nvidia.com>
Thu, 17 Jul 2014 11:36:44 +0000 (13:36 +0200)
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. Also have the APB DMA readl and writel return an error in
case of a read failure instead of just returning zero or ignore write
failures.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
arch/arm/mach-tegra/apbio.c
include/soc/tegra/fuse.h

index 5f9647b3f81dca5a26628beb17157766b4805991..f2488722c79c91d90ea8e3db3f02a56c4f55e1db 100644 (file)
@@ -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)
index 0e03f104fbf842cb7dc263a741e9da75df7e07dd..a43a750dd0a3512b731e1e5e8d255051c08f5aa9 100644 (file)
 u32 tegra_read_chipid(void);
 u8 tegra_get_chip_id(void);
 
+#if defined(CONFIG_TEGRA20_APB_DMA)
+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 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 /* CONFIG_TEGRA20_APB_DMA */
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __SOC_TEGRA_FUSE_H__ */
This page took 0.042922 seconds and 5 git commands to generate.