]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/plat-omap/dsp/mmu.h
ARM: OMAP: Adapt to new MMU framework
[linux-2.6-omap-h63xx.git] / arch / arm / plat-omap / dsp / mmu.h
1 #ifndef __PLAT_OMAP_DSP_MMU_H
2 #define __PLAT_OMAP_DSP_MMU_H
3
4 #ifdef CONFIG_ARCH_OMAP1
5
6 #ifdef CONFIG_ARCH_OMAP15XX
7 struct omap_mmu dsp_mmu = {
8         .name           = "dsp",
9         .type           = OMAP_MMU_DSP,
10         .base           = OMAP15XX_DSP_START,
11         .membase        = OMAP15XX_DSP_BASE,
12         .memsize        = OMAP15XX_DSP_SIZE,
13         .nr_tlb_entries = 32,
14         .addrspace      = 24,
15         .ops            = &omap1_mmu_ops,
16 };
17 #endif
18 #ifdef CONFIG_ARCH_OMAP16XX
19 struct omap_mmu dsp_mmu = {
20         .name           = "dsp",
21         .type           = OMAP_MMU_DSP,
22         .base           = OMAP16XX_DSP_START,
23         .membase        = OMAP16XX_DSP_BASE,
24         .memsize        = OMAP16XX_DSP_SIZE,
25         .nr_tlb_entries = 32,
26         .addrspace      = 24,
27         .ops            = &omap1_mmu_ops,
28 };
29 #endif
30 #else /* OMAP2 */
31 struct omap_mmu dsp_mmu = {
32         .name           = "dsp",
33         .type           = OMAP_MMU_DSP,
34         .base           = DSP_MMU_24XX_VIRT,
35         .membase        = DSP_MEM_24XX_VIRT,
36         .memsize        = DSP_MEM_24XX_SIZE,
37         .nr_tlb_entries = 32,
38         .addrspace      = 24,
39         .ops            = &omap2_mmu_ops,
40 };
41
42 #define IOMAP_VAL       0x3f
43 #endif
44
45 static u32 dsp_fault_adr;
46
47 #ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
48 static struct omapfb_notifier_block *omapfb_nb;
49 static int omapfb_ready;
50 #endif
51
52 /*
53  * OMAP1 EMIFF access
54  */
55 #ifdef CONFIG_ARCH_OMAP1
56 #define EMIF_PRIO_LB_MASK       0x0000f000
57 #define EMIF_PRIO_LB_SHIFT      12
58 #define EMIF_PRIO_DMA_MASK      0x00000f00
59 #define EMIF_PRIO_DMA_SHIFT     8
60 #define EMIF_PRIO_DSP_MASK      0x00000070
61 #define EMIF_PRIO_DSP_SHIFT     4
62 #define EMIF_PRIO_MPU_MASK      0x00000007
63 #define EMIF_PRIO_MPU_SHIFT     0
64 #define set_emiff_dma_prio(prio) \
65         do { \
66                 omap_writel((omap_readl(OMAP_TC_OCPT1_PRIOR) & \
67                              ~EMIF_PRIO_DMA_MASK) | \
68                             ((prio) << EMIF_PRIO_DMA_SHIFT), \
69                             OMAP_TC_OCPT1_PRIOR); \
70         } while(0)
71 #else
72 #define set_emiff_dma_prio(prio)        do { } while (0)
73 #endif /* CONFIG_ARCH_OMAP1 */
74
75 /*
76  * workqueue for mmu int
77  */
78 #ifdef CONFIG_ARCH_OMAP1
79 /*
80  * MMU fault mask:
81  * We ignore prefetch err.
82  */
83 #define MMUFAULT_MASK \
84         (DSP_MMU_FAULT_ST_PERM |\
85          DSP_MMU_FAULT_ST_TLB_MISS |\
86          DSP_MMU_FAULT_ST_TRANS)
87
88 static void do_mmu_int(struct work_struct *unused)
89 {
90         unsigned long status;
91         unsigned long adh, adl;
92         unsigned long dp;
93
94         status = omap_mmu_read_reg(&dsp_mmu, DSP_MMU_FAULT_ST);
95         adh = omap_mmu_read_reg(&dsp_mmu, DSP_MMU_FAULT_AD_H);
96         adl = omap_mmu_read_reg(&dsp_mmu, DSP_MMU_FAULT_AD_L);
97         dp = adh & DSP_MMU_FAULT_AD_H_DP;
98         dsp_fault_adr = MK32(adh & DSP_MMU_FAULT_AD_H_ADR_MASK, adl);
99
100         /* if the fault is masked, nothing to do */
101         if ((status & MMUFAULT_MASK) == 0) {
102                 pr_debug( "DSP MMU interrupt, but ignoring.\n");
103                 /*
104                  * note: in OMAP1710,
105                  * when CACHE + DMA domain gets out of idle in DSP,
106                  * MMU interrupt occurs but DSP_MMU_FAULT_ST is not set.
107                  * in this case, we just ignore the interrupt.
108                  */
109                 if (status) {
110                         pr_debug( "%s%s%s%s\n",
111                                   (status & DSP_MMU_FAULT_ST_PREF)?
112                                   "  (prefetch err)" : "",
113                                   (status & DSP_MMU_FAULT_ST_PERM)?
114                                   "  (permission fault)" : "",
115                                   (status & DSP_MMU_FAULT_ST_TLB_MISS)?
116                                   "  (TLB miss)" : "",
117                                   (status & DSP_MMU_FAULT_ST_TRANS) ?
118                                   "  (translation fault)": "");
119                         pr_debug( "fault address = %#08x\n", dsp_fault_adr);
120                 }
121                 enable_irq(omap_dsp->mmu_irq);
122                 return;
123         }
124
125
126         pr_info("%s%s%s%s\n",
127                 (status & DSP_MMU_FAULT_ST_PREF)?
128                 (MMUFAULT_MASK & DSP_MMU_FAULT_ST_PREF)?
129                 "  prefetch err":
130                 "  (prefetch err)":
131                 "",
132                 (status & DSP_MMU_FAULT_ST_PERM)?
133                 (MMUFAULT_MASK & DSP_MMU_FAULT_ST_PERM)?
134                 "  permission fault":
135                 "  (permission fault)":
136                 "",
137                 (status & DSP_MMU_FAULT_ST_TLB_MISS)?
138                 (MMUFAULT_MASK & DSP_MMU_FAULT_ST_TLB_MISS)?
139                 "  TLB miss":
140                 "  (TLB miss)":
141                 "",
142                 (status & DSP_MMU_FAULT_ST_TRANS)?
143                 (MMUFAULT_MASK & DSP_MMU_FAULT_ST_TRANS)?
144                 "  translation fault":
145                 "  (translation fault)":
146                 "");
147
148         pr_info("fault address = %#08x\n", dsp_fault_adr);
149
150         if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
151                 dsp_err_set(ERRCODE_MMU, (unsigned long)dsp_fault_adr);
152         else {
153                 __dsp_mmu_itack(&dsp_mmu);
154
155                 pr_info("Resetting DSP...\n");
156                 dsp_cpustat_request(CPUSTAT_RESET);
157                 /*
158                  * if we enable followings, semaphore lock should be avoided.
159                  *
160                  pr_info("Flushing DSP MMU...\n");
161                  exmap_flush();
162                  dsp_mmu_init();
163                 */
164         }
165
166         enable_irq(omap_dsp->mmu_irq);
167 }
168 #elif defined(CONFIG_ARCH_OMAP2)
169 static void do_mmu_int(struct work_struct *unused)
170 {
171         unsigned long status;
172
173         status = omap_mmu_read_reg(&dsp_mmu, DSP_MMU_IRQSTATUS);
174         dsp_fault_adr = omap_mmu_read_reg(&dsp_mmu, DSP_MMU_FAULT_AD);
175
176 #define MMU_IRQ_MASK \
177         (DSP_MMU_IRQ_MULTIHITFAULT | \
178          DSP_MMU_IRQ_TABLEWALKFAULT | \
179          DSP_MMU_IRQ_EMUMISS | \
180          DSP_MMU_IRQ_TRANSLATIONFAULT | \
181          DSP_MMU_IRQ_TLBMISS)
182
183         pr_info("%s%s%s%s%s\n",
184                 (status & DSP_MMU_IRQ_MULTIHITFAULT)?
185                 (MMU_IRQ_MASK & DSP_MMU_IRQ_MULTIHITFAULT)?
186                 "  multi hit":
187                 "  (multi hit)":
188                 "",
189                 (status & DSP_MMU_IRQ_TABLEWALKFAULT)?
190                 (MMU_IRQ_MASK & DSP_MMU_IRQ_TABLEWALKFAULT)?
191                 "  table walk fault":
192                 "  (table walk fault)":
193                 "",
194                 (status & DSP_MMU_IRQ_EMUMISS)?
195                 (MMU_IRQ_MASK & DSP_MMU_IRQ_EMUMISS)?
196                 "  EMU miss":
197                 "  (EMU miss)":
198                 "",
199                 (status & DSP_MMU_IRQ_TRANSLATIONFAULT)?
200                 (MMU_IRQ_MASK & DSP_MMU_IRQ_TRANSLATIONFAULT)?
201                 "  translation fault":
202                 "  (translation fault)":
203                 "",
204                 (status & DSP_MMU_IRQ_TLBMISS)?
205                 (MMU_IRQ_MASK & DSP_MMU_IRQ_TLBMISS)?
206                 "  TLB miss":
207                 "  (TLB miss)":
208                 "");
209
210         pr_info("fault address = %#08x\n", dsp_fault_adr);
211
212         if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
213                 dsp_err_set(ERRCODE_MMU, (unsigned long)dsp_fault_adr);
214         else {
215                 pr_info("Resetting DSP...\n");
216                 dsp_cpustat_request(CPUSTAT_RESET);
217         }
218
219         omap_mmu_disable(&dsp_mmu);
220         omap_mmu_write_reg(&dsp_mmu, status, DSP_MMU_IRQSTATUS);
221         omap_mmu_enable(&dsp_mmu, 0);
222
223         enable_irq(omap_dsp->mmu_irq);
224 }
225 #endif
226
227 static DECLARE_WORK(mmu_int_work, do_mmu_int);
228
229 #ifdef CONFIG_ARCH_OMAP1
230 static int dsp_mmu_itack(void)
231 {
232         unsigned long dspadr;
233
234         pr_info("omapdsp: sending DSP MMU interrupt ack.\n");
235         if (!dsp_err_isset(ERRCODE_MMU)) {
236                 printk(KERN_ERR "omapdsp: DSP MMU error has not been set.\n");
237                 return -EINVAL;
238         }
239         dspadr = dsp_fault_adr & ~(SZ_4K-1);
240         /* FIXME: reserve TLB entry for this */
241         omap_mmu_exmap(&dsp_mmu, dspadr, 0, SZ_4K, EXMAP_TYPE_MEM);
242         pr_info("omapdsp: falling into recovery runlevel...\n");
243         dsp_set_runlevel(RUNLEVEL_RECOVERY);
244         __dsp_mmu_itack(&dsp_mmu);
245         udelay(100);
246         omap_mmu_exunmap(&dsp_mmu, dspadr);
247         dsp_err_clear(ERRCODE_MMU);
248         return 0;
249 }
250
251 /*
252  * intmem_enable() / disable():
253  * if the address is in DSP internal memories,
254  * we send PM mailbox commands so that DSP DMA domain won't go in idle
255  * when ARM is accessing to those memories.
256  */
257 static int intmem_enable(void)
258 {
259         int ret = 0;
260
261         if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
262                 ret = mbcompose_send(PM, PM_ENABLE, DSPREG_ICR_DMA);
263
264         return ret;
265 }
266
267 static void intmem_disable(void) {
268         if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
269                 mbcompose_send(PM, PM_DISABLE, DSPREG_ICR_DMA);
270 }
271 #else
272 static int intmem_enable(void) { return 0; }
273 static void intmem_disable(void) { }
274 static int dsp_mmu_itack(void) { return 0; }
275 #endif
276
277 #endif /* __PLAT_OMAP_DSP_MMU_H */