aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter De Schrijver <pdeschrijver@nvidia.com>2014-06-12 11:36:35 -0400
committerThierry Reding <treding@nvidia.com>2014-07-17 07:36:44 -0400
commit3f394f80645bf0c38a30042ba605c71663331035 (patch)
tree6acabf07689afc6b71bb0409d100ffb732fcb236
parent304664eab93f9e95a8d28fbd9702ede88bb10cc5 (diff)
ARM: tegra: export apb dma readl/writel
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>
-rw-r--r--arch/arm/mach-tegra/apbio.c51
-rw-r--r--include/soc/tegra/fuse.h14
2 files changed, 45 insertions, 20 deletions
diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c
index 5f9647b3f81d..f2488722c79c 100644
--- a/arch/arm/mach-tegra/apbio.c
+++ b/arch/arm/mach-tegra/apbio.c
@@ -32,8 +32,8 @@ static u32 *tegra_apb_bb;
32static dma_addr_t tegra_apb_bb_phys; 32static dma_addr_t tegra_apb_bb_phys;
33static DECLARE_COMPLETION(tegra_apb_wait); 33static DECLARE_COMPLETION(tegra_apb_wait);
34 34
35static u32 tegra_apb_readl_direct(unsigned long offset); 35static int tegra_apb_readl_direct(unsigned long offset, u32 *value);
36static void tegra_apb_writel_direct(u32 value, unsigned long offset); 36static int tegra_apb_writel_direct(u32 value, unsigned long offset);
37 37
38static struct dma_chan *tegra_apb_dma_chan; 38static struct dma_chan *tegra_apb_dma_chan;
39static struct dma_slave_config dma_sconfig; 39static struct dma_slave_config dma_sconfig;
@@ -128,58 +128,64 @@ static int do_dma_transfer(unsigned long apb_add,
128 return 0; 128 return 0;
129} 129}
130 130
131static u32 tegra_apb_readl_using_dma(unsigned long offset) 131int tegra_apb_readl_using_dma(unsigned long offset, u32 *value)
132{ 132{
133 int ret; 133 int ret;
134 134
135 if (!tegra_apb_dma_chan && !tegra_apb_dma_init()) 135 if (!tegra_apb_dma_chan && !tegra_apb_dma_init())
136 return tegra_apb_readl_direct(offset); 136 return tegra_apb_readl_direct(offset, value);
137 137
138 mutex_lock(&tegra_apb_dma_lock); 138 mutex_lock(&tegra_apb_dma_lock);
139 ret = do_dma_transfer(offset, DMA_DEV_TO_MEM); 139 ret = do_dma_transfer(offset, DMA_DEV_TO_MEM);
140 if (ret < 0) { 140 if (ret < 0)
141 pr_err("error in reading offset 0x%08lx using dma\n", offset); 141 pr_err("error in reading offset 0x%08lx using dma\n", offset);
142 *(u32 *)tegra_apb_bb = 0; 142 else
143 } 143 *value = *tegra_apb_bb;
144
144 mutex_unlock(&tegra_apb_dma_lock); 145 mutex_unlock(&tegra_apb_dma_lock);
145 return *((u32 *)tegra_apb_bb); 146
147 return ret;
146} 148}
147 149
148static void tegra_apb_writel_using_dma(u32 value, unsigned long offset) 150int tegra_apb_writel_using_dma(u32 value, unsigned long offset)
149{ 151{
150 int ret; 152 int ret;
151 153
152 if (!tegra_apb_dma_chan && !tegra_apb_dma_init()) { 154 if (!tegra_apb_dma_chan && !tegra_apb_dma_init())
153 tegra_apb_writel_direct(value, offset); 155 return tegra_apb_writel_direct(value, offset);
154 return;
155 }
156 156
157 mutex_lock(&tegra_apb_dma_lock); 157 mutex_lock(&tegra_apb_dma_lock);
158 *((u32 *)tegra_apb_bb) = value; 158 *((u32 *)tegra_apb_bb) = value;
159 ret = do_dma_transfer(offset, DMA_MEM_TO_DEV); 159 ret = do_dma_transfer(offset, DMA_MEM_TO_DEV);
160 mutex_unlock(&tegra_apb_dma_lock);
160 if (ret < 0) 161 if (ret < 0)
161 pr_err("error in writing offset 0x%08lx using dma\n", offset); 162 pr_err("error in writing offset 0x%08lx using dma\n", offset);
162 mutex_unlock(&tegra_apb_dma_lock); 163
164 return ret;
163} 165}
164#else 166#else
165#define tegra_apb_readl_using_dma tegra_apb_readl_direct 167#define tegra_apb_readl_using_dma tegra_apb_readl_direct
166#define tegra_apb_writel_using_dma tegra_apb_writel_direct 168#define tegra_apb_writel_using_dma tegra_apb_writel_direct
167#endif 169#endif
168 170
169typedef u32 (*apbio_read_fptr)(unsigned long offset); 171typedef int (*apbio_read_fptr)(unsigned long offset, u32 *value);
170typedef void (*apbio_write_fptr)(u32 value, unsigned long offset); 172typedef int (*apbio_write_fptr)(u32 value, unsigned long offset);
171 173
172static apbio_read_fptr apbio_read; 174static apbio_read_fptr apbio_read;
173static apbio_write_fptr apbio_write; 175static apbio_write_fptr apbio_write;
174 176
175static u32 tegra_apb_readl_direct(unsigned long offset) 177static int tegra_apb_readl_direct(unsigned long offset, u32 *value)
176{ 178{
177 return readl(IO_ADDRESS(offset)); 179 *value = readl(IO_ADDRESS(offset));
180
181 return 0;
178} 182}
179 183
180static void tegra_apb_writel_direct(u32 value, unsigned long offset) 184static int tegra_apb_writel_direct(u32 value, unsigned long offset)
181{ 185{
182 writel(value, IO_ADDRESS(offset)); 186 writel(value, IO_ADDRESS(offset));
187
188 return 0;
183} 189}
184 190
185void tegra_apb_io_init(void) 191void tegra_apb_io_init(void)
@@ -197,7 +203,12 @@ void tegra_apb_io_init(void)
197 203
198u32 tegra_apb_readl(unsigned long offset) 204u32 tegra_apb_readl(unsigned long offset)
199{ 205{
200 return apbio_read(offset); 206 u32 val;
207
208 if (apbio_read(offset, &val) < 0)
209 return 0;
210 else
211 return val;
201} 212}
202 213
203void tegra_apb_writel(u32 value, unsigned long offset) 214void tegra_apb_writel(u32 value, unsigned long offset)
diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h
index 0e03f104fbf8..a43a750dd0a3 100644
--- a/include/soc/tegra/fuse.h
+++ b/include/soc/tegra/fuse.h
@@ -27,6 +27,20 @@
27u32 tegra_read_chipid(void); 27u32 tegra_read_chipid(void);
28u8 tegra_get_chip_id(void); 28u8 tegra_get_chip_id(void);
29 29
30#if defined(CONFIG_TEGRA20_APB_DMA)
31int tegra_apb_readl_using_dma(unsigned long offset, u32 *value);
32int tegra_apb_writel_using_dma(u32 value, unsigned long offset);
33#else
34static inline int tegra_apb_readl_using_dma(unsigned long offset, u32 *value)
35{
36 return -EINVAL;
37}
38static inline int tegra_apb_writel_using_dma(u32 value, unsigned long offset)
39{
40 return -EINVAL;
41}
42#endif /* CONFIG_TEGRA20_APB_DMA */
43
30#endif /* __ASSEMBLY__ */ 44#endif /* __ASSEMBLY__ */
31 45
32#endif /* __SOC_TEGRA_FUSE_H__ */ 46#endif /* __SOC_TEGRA_FUSE_H__ */