diff options
Diffstat (limited to 'arch/arm/mach-tegra/apbio.c')
-rw-r--r-- | arch/arm/mach-tegra/apbio.c | 59 |
1 files changed, 54 insertions, 5 deletions
diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c index e75451e517bd..74ac0db53739 100644 --- a/arch/arm/mach-tegra/apbio.c +++ b/arch/arm/mach-tegra/apbio.c | |||
@@ -15,6 +15,10 @@ | |||
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <mach/iomap.h> | ||
19 | #include <linux/of.h> | ||
20 | |||
21 | #ifdef CONFIG_TEGRA_SYSTEM_DMA | ||
18 | #include <linux/dma-mapping.h> | 22 | #include <linux/dma-mapping.h> |
19 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
20 | #include <linux/completion.h> | 24 | #include <linux/completion.h> |
@@ -22,7 +26,6 @@ | |||
22 | #include <linux/mutex.h> | 26 | #include <linux/mutex.h> |
23 | 27 | ||
24 | #include <mach/dma.h> | 28 | #include <mach/dma.h> |
25 | #include <mach/iomap.h> | ||
26 | 29 | ||
27 | #include "apbio.h" | 30 | #include "apbio.h" |
28 | 31 | ||
@@ -33,6 +36,9 @@ static u32 *tegra_apb_bb; | |||
33 | static dma_addr_t tegra_apb_bb_phys; | 36 | static dma_addr_t tegra_apb_bb_phys; |
34 | static DECLARE_COMPLETION(tegra_apb_wait); | 37 | static DECLARE_COMPLETION(tegra_apb_wait); |
35 | 38 | ||
39 | static u32 tegra_apb_readl_direct(unsigned long offset); | ||
40 | static void tegra_apb_writel_direct(u32 value, unsigned long offset); | ||
41 | |||
36 | bool tegra_apb_init(void) | 42 | bool tegra_apb_init(void) |
37 | { | 43 | { |
38 | struct tegra_dma_channel *ch; | 44 | struct tegra_dma_channel *ch; |
@@ -72,13 +78,13 @@ static void apb_dma_complete(struct tegra_dma_req *req) | |||
72 | complete(&tegra_apb_wait); | 78 | complete(&tegra_apb_wait); |
73 | } | 79 | } |
74 | 80 | ||
75 | u32 tegra_apb_readl(unsigned long offset) | 81 | static u32 tegra_apb_readl_using_dma(unsigned long offset) |
76 | { | 82 | { |
77 | struct tegra_dma_req req; | 83 | struct tegra_dma_req req; |
78 | int ret; | 84 | int ret; |
79 | 85 | ||
80 | if (!tegra_apb_dma && !tegra_apb_init()) | 86 | if (!tegra_apb_dma && !tegra_apb_init()) |
81 | return readl(IO_TO_VIRT(offset)); | 87 | return tegra_apb_readl_direct(offset); |
82 | 88 | ||
83 | mutex_lock(&tegra_apb_dma_lock); | 89 | mutex_lock(&tegra_apb_dma_lock); |
84 | req.complete = apb_dma_complete; | 90 | req.complete = apb_dma_complete; |
@@ -108,13 +114,13 @@ u32 tegra_apb_readl(unsigned long offset) | |||
108 | return *((u32 *)tegra_apb_bb); | 114 | return *((u32 *)tegra_apb_bb); |
109 | } | 115 | } |
110 | 116 | ||
111 | void tegra_apb_writel(u32 value, unsigned long offset) | 117 | static void tegra_apb_writel_using_dma(u32 value, unsigned long offset) |
112 | { | 118 | { |
113 | struct tegra_dma_req req; | 119 | struct tegra_dma_req req; |
114 | int ret; | 120 | int ret; |
115 | 121 | ||
116 | if (!tegra_apb_dma && !tegra_apb_init()) { | 122 | if (!tegra_apb_dma && !tegra_apb_init()) { |
117 | writel(value, IO_TO_VIRT(offset)); | 123 | tegra_apb_writel_direct(value, offset); |
118 | return; | 124 | return; |
119 | } | 125 | } |
120 | 126 | ||
@@ -143,3 +149,46 @@ void tegra_apb_writel(u32 value, unsigned long offset) | |||
143 | 149 | ||
144 | mutex_unlock(&tegra_apb_dma_lock); | 150 | mutex_unlock(&tegra_apb_dma_lock); |
145 | } | 151 | } |
152 | #else | ||
153 | #define tegra_apb_readl_using_dma tegra_apb_readl_direct | ||
154 | #define tegra_apb_writel_using_dma tegra_apb_writel_direct | ||
155 | #endif | ||
156 | |||
157 | typedef u32 (*apbio_read_fptr)(unsigned long offset); | ||
158 | typedef void (*apbio_write_fptr)(u32 value, unsigned long offset); | ||
159 | |||
160 | static apbio_read_fptr apbio_read; | ||
161 | static apbio_write_fptr apbio_write; | ||
162 | |||
163 | static u32 tegra_apb_readl_direct(unsigned long offset) | ||
164 | { | ||
165 | return readl(IO_TO_VIRT(offset)); | ||
166 | } | ||
167 | |||
168 | static void tegra_apb_writel_direct(u32 value, unsigned long offset) | ||
169 | { | ||
170 | writel(value, IO_TO_VIRT(offset)); | ||
171 | } | ||
172 | |||
173 | void tegra_apb_io_init(void) | ||
174 | { | ||
175 | /* Need to use dma only when it is Tegra20 based platform */ | ||
176 | if (of_machine_is_compatible("nvidia,tegra20") || | ||
177 | !of_have_populated_dt()) { | ||
178 | apbio_read = tegra_apb_readl_using_dma; | ||
179 | apbio_write = tegra_apb_writel_using_dma; | ||
180 | } else { | ||
181 | apbio_read = tegra_apb_readl_direct; | ||
182 | apbio_write = tegra_apb_writel_direct; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | u32 tegra_apb_readl(unsigned long offset) | ||
187 | { | ||
188 | return apbio_read(offset); | ||
189 | } | ||
190 | |||
191 | void tegra_apb_writel(u32 value, unsigned long offset) | ||
192 | { | ||
193 | apbio_write(value, offset); | ||
194 | } | ||