1 /*
2 * Copyright (c) 2010, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * */
32 /*
33 * dmm.c
34 *
35 * DMM driver support functions for TI OMAP processors.
36 */
37 #include "proto.h"
38 #include "dmm.h"
40 #define BITS_32(in_NbBits) ((((u32)1 << in_NbBits) - 1) | ((u32)1 << in_NbBits))
41 #define BITFIELD_32(in_UpBit, in_LowBit)\
42 (BITS_32(in_UpBit) & ~((BITS_32(in_LowBit)) >> 1))
43 #define BF BITFIELD_32
46 /* IMPORTANT NOTE: This function needs to be IRQ safe. Adding traces
47 * or other non-interrupt safe calls to it will result in a crash in
48 * CPU dll. */
49 s32 dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum pat_mode mode)
50 {
51 uintptr_t r = NULL;
52 u32 v = -1, w = -1;
54 /* Only manual refill supported */
55 if (mode != MANUAL)
56 return -EFAULT;
58 /*
59 * Check that the DMM_PAT_STATUS register
60 * has not reported an error.
61 */
62 r = (uintptr_t)((u32)dmm->base | DMM_PAT_STATUS__0);
63 v = __raw_readl(r);
64 if ((v & 0xFC00) != 0) {
65 return -EFAULT;
66 }
68 /* Set "next" register to NULL */
69 r = (uintptr_t)((u32)dmm->base | DMM_PAT_DESCR__0);
70 v = __raw_readl(r);
71 w = (v & (~(BF(31, 4)))) | ((((u32)NULL) << 4) & BF(31, 4));
72 __raw_writel(w, r);
74 /* Set area to be refilled */
75 r = (uintptr_t)((u32)dmm->base | DMM_PAT_AREA__0);
76 v = __raw_readl(r);
77 #ifdef TILER_PLATFORM_OMAP5
78 w = (v & (~(BF(31, 24)))) | ((((s8)pd->area.y1) << 24) & BF(31, 24));
79 #else
80 w = (v & (~(BF(30, 24)))) | ((((s8)pd->area.y1) << 24) & BF(30, 24));
81 #endif
82 __raw_writel(w, r);
84 v = __raw_readl(r);
85 w = (v & (~(BF(23, 16)))) | ((((s8)pd->area.x1) << 16) & BF(23, 16));
86 __raw_writel(w, r);
88 v = __raw_readl(r);
89 #ifdef TILER_PLATFORM_OMAP5
90 w = (v & (~(BF(15, 8)))) | ((((s8)pd->area.y0) << 8) & BF(15, 8));
91 #else
92 w = (v & (~(BF(14, 8)))) | ((((s8)pd->area.y0) << 8) & BF(14, 8));
93 #endif
94 __raw_writel(w, r);
96 v = __raw_readl(r);
97 w = (v & (~(BF(7, 0)))) | ((((s8)pd->area.x0) << 0) & BF(7, 0));
98 __raw_writel(w, r);
99 wmb();
101 /* First, clear the DMM_PAT_IRQSTATUS register */
102 r = (uintptr_t)((u32)dmm->base | (u32)DMM_PAT_IRQSTATUS);
103 __raw_writel(0xFFFFFFFF, r);
104 wmb();
106 r = (uintptr_t)((u32)dmm->base | (u32)DMM_PAT_IRQSTATUS_RAW);
107 v = 0xFFFFFFFF;
109 while (v != 0x0) {
110 v = __raw_readl(r);
111 }
113 /* Fill data register */
114 r = (uintptr_t)((u32)dmm->base | DMM_PAT_DATA__0);
115 v = __raw_readl(r);
117 /* Apply 4 bit left shft to counter the 4 bit right shift */
118 w = (v & (~(BF(31, 4)))) | ((((u32)(pd->data >> 4)) << 4) & BF(31, 4));
119 __raw_writel(w, r);
120 wmb();
122 /* Read back PAT_DATA__0 to see if write was successful */
123 v = 0x0;
124 while (v != pd->data) {
125 v = __raw_readl(r);
126 }
128 r = (uintptr_t)((u32)dmm->base | (u32)DMM_PAT_CTRL__0);
129 v = __raw_readl(r);
131 w = (v & (~(BF(31, 28)))) | ((((u32)pd->ctrl.ini) << 28) & BF(31, 28));
132 __raw_writel(w, r);
134 v = __raw_readl(r);
135 w = (v & (~(BF(16, 16)))) | ((((u32)pd->ctrl.sync) << 16) & BF(16, 16));
136 __raw_writel(w, r);
138 v = __raw_readl(r);
139 w = (v & (~(BF(9, 8)))) | ((((u32)pd->ctrl.lut_id) << 8) & BF(9, 8));
140 __raw_writel(w, r);
142 v = __raw_readl(r);
143 w = (v & (~(BF(6, 4)))) | ((((u32)pd->ctrl.dir) << 4) & BF(6, 4));
144 __raw_writel(w, r);
146 v = __raw_readl(r);
147 w = (v & (~(BF(0, 0)))) | ((((u32)pd->ctrl.start) << 0) & BF(0, 0));
148 __raw_writel(w, r);
149 wmb();
151 /*
152 * Now, check if PAT_IRQSTATUS_RAW has been
153 * set after the PAT has been refilled
154 */
155 r = (uintptr_t)((u32)dmm->base | (u32)DMM_PAT_IRQSTATUS_RAW);
156 v = 0x0;
157 while ((v & 0x3) != 0x3) {
158 v = __raw_readl(r);
159 }
161 /* Again, clear the DMM_PAT_IRQSTATUS register */
162 r = (uintptr_t)((u32)dmm->base | (u32)DMM_PAT_IRQSTATUS);
163 __raw_writel(0xFFFFFFFF, r);
164 wmb();
166 r = (uintptr_t)((u32)dmm->base | (u32)DMM_PAT_IRQSTATUS_RAW);
167 v = 0xFFFFFFFF;
169 while (v != 0x0) {
170 v = __raw_readl(r);
171 }
173 /* Again, set "next" register to NULL to clear any PAT STATUS errors */
174 r = (uintptr_t)((u32)dmm->base | DMM_PAT_DESCR__0);
175 v = __raw_readl(r);
176 w = (v & (~(BF(31, 4)))) | ((((u32)NULL) << 4) & BF(31, 4));
177 __raw_writel(w, r);
179 /*
180 * Now, check that the DMM_PAT_STATUS register
181 * has not reported an error before exiting.
182 */
183 r = (uintptr_t)((u32)dmm->base | DMM_PAT_STATUS__0);
184 v = __raw_readl(r);
185 if ((v & 0xFC00) != 0) {
186 return -EFAULT;
187 }
189 return 0;
190 }
192 struct dmm *dmm_pat_init(u32 id)
193 {
194 u32 base = 0;
195 struct dmm *dmm = NULL;
196 switch (id) {
197 case 0:
198 /* only support id 0 for now */
199 base = DMM_BASE;
200 break;
201 default:
202 return NULL;
203 }
205 dmm = kmalloc(sizeof(*dmm), GFP_KERNEL);
206 if (!dmm)
207 return NULL;
209 dmm->base = mmap_device_io(DMM_SIZE, base);
210 if (!dmm->base) {
211 kfree(dmm);
212 return NULL;
213 }
215 __raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__0);
216 __raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__1);
217 __raw_writel(0x80808080, dmm->base + DMM_PAT_VIEW_MAP__0);
218 __raw_writel(0x80000000, dmm->base + DMM_PAT_VIEW_MAP_BASE);
219 __raw_writel(0x88888888, dmm->base + DMM_TILER_OR__0);
220 __raw_writel(0x88888888, dmm->base + DMM_TILER_OR__1);
222 /* Set PEG to zero for ISS */
223 __raw_writel(0x8, dmm->base + DMM_PEG_PRIO + 0x4 * 2);
225 return dmm;
226 }
228 /**
229 * Clean up the physical address translator.
230 * @param dmm Device data
231 * @return an error status.
232 */
233 void dmm_pat_release(struct dmm *dmm)
234 {
235 if (dmm) {
236 munmap_device_io(dmm->base, DMM_SIZE);
237 kfree(dmm);
238 }
239 }
241 s32 dmm_init(void)
242 {
243 return 0;
244 }
246 void dmm_exit(void)
247 {
248 return;
249 }