.ioctl = dsp_mem_ioctl,
};
-/*
- * DSP MMU interrupt handler
- */
-static irqreturn_t dsp_mmu_interrupt(int irq, void *dev_id)
-{
- disable_irq(omap_dsp->mmu_irq);
- schedule_work(&mmu_int_work);
- return IRQ_HANDLED;
-}
-
void dsp_mem_start(void)
{
dsp_register_mem_cb(intmem_enable, intmem_disable);
dsp_unregister_mem_cb();
}
+static void dsp_mmu_irq_work(struct work_struct *work)
+{
+ struct omap_mmu *mmu = container_of(work, struct omap_mmu, irq_work);
+
+ if (dsp_cfgstat_get_stat() == CFGSTAT_READY) {
+ dsp_err_set(ERRCODE_MMU, mmu->fault_address);
+ return;
+ }
+ omap_mmu_itack(mmu);
+ pr_info("Resetting DSP...\n");
+ dsp_cpustat_request(CPUSTAT_RESET);
+ omap_mmu_enable(mmu, 0);
+}
+
/*
* later half of dsp memory initialization
*/
-void dsp_mem_late_init(void)
+int dsp_mem_late_init(void)
{
- int ret = 0;
+ int ret;
dsp_mem_ipi_init();
+
+ INIT_WORK(&dsp_mmu.irq_work, dsp_mmu_irq_work);
+ ret = omap_mmu_register(&dsp_mmu);
+ if (ret) {
+ dsp_reset_idle_boot_base();
+ goto out;
+ }
+ omap_dsp->mmu = &dsp_mmu;
+ out:
+ return ret;
+}
+
+int __init dsp_mem_init(void)
+{
#ifdef CONFIG_ARCH_OMAP2
dsp_mmu.clk = dsp_fck_handle;
dsp_mmu.memclk = dsp_ick_handle;
dsp_mmu.clk = dsp_ck_handle;
dsp_mmu.memclk = api_ck_handle;
#endif
- ret = omap_mmu_register(&dsp_mmu);
-}
-
-int __init dsp_mem_init(void)
-{
- int ret;
- /*
- * DSP MMU interrupt setup
- */
- ret = request_irq(omap_dsp->mmu_irq, dsp_mmu_interrupt, IRQF_DISABLED,
- "dsp_mmu", NULL);
- if (ret) {
- printk(KERN_ERR
- "failed to register DSP MMU interrupt: %d\n", ret);
- goto fail;
- }
-
- /* MMU interrupt is not enabled until DSP runs */
- disable_irq(omap_dsp->mmu_irq);
-
return 0;
- fail:
-#ifdef CONFIG_ARCH_OMAP1
- dsp_reset_idle_boot_base();
-#endif
- return ret;
}
void dsp_mem_exit(void)
{
- free_irq(omap_dsp->mmu_irq, NULL);
-
- /* recover disable_depth */
- enable_irq(omap_dsp->mmu_irq);
-
-#ifdef CONFIG_ARCH_OMAP1
dsp_reset_idle_boot_base();
-#endif
omap_mmu_unregister(&dsp_mmu);
}
#ifdef CONFIG_ARCH_OMAP15XX
struct omap_mmu dsp_mmu = {
- .name = "dsp",
+ .name = "mmu:dsp",
.type = OMAP_MMU_DSP,
.base = DSP_MMU_BASE,
.membase = OMAP15XX_DSP_BASE,
.memsize = OMAP15XX_DSP_SIZE,
.nr_tlb_entries = 32,
.addrspace = 24,
+ .irq = INT_1510_DSP_MMU,
.ops = &omap1_mmu_ops,
};
#endif
#ifdef CONFIG_ARCH_OMAP16XX
struct omap_mmu dsp_mmu = {
- .name = "dsp",
+ .name = "mmu:dsp",
.type = OMAP_MMU_DSP,
.base = DSP_MMU_BASE,
.membase = OMAP16XX_DSP_BASE,
.memsize = OMAP16XX_DSP_SIZE,
.nr_tlb_entries = 32,
.addrspace = 24,
+ .irq = INT_1610_DSP_MMU,
.ops = &omap1_mmu_ops,
};
#endif
#else /* OMAP2 */
struct omap_mmu dsp_mmu = {
- .name = "dsp",
+ .name = "mmu:dsp",
.type = OMAP_MMU_DSP,
.base = DSP_MMU_24XX_VIRT,
.membase = DSP_MEM_24XX_VIRT,
.memsize = DSP_MEM_24XX_SIZE,
.nr_tlb_entries = 32,
.addrspace = 24,
+ .irq = INT_24XX_DSP_MMU,
.ops = &omap2_mmu_ops,
};
#define IOMAP_VAL 0x3f
#endif
-static u32 dsp_fault_adr;
-
#ifdef CONFIG_FB_OMAP_LCDC_EXTERNAL
static struct omapfb_notifier_block *omapfb_nb;
static int omapfb_ready;
#define set_emiff_dma_prio(prio) do { } while (0)
#endif /* CONFIG_ARCH_OMAP1 */
-/*
- * workqueue for mmu int
- */
-#ifdef CONFIG_ARCH_OMAP1
-/*
- * MMU fault mask:
- * We ignore prefetch err.
- */
-#define MMUFAULT_MASK \
- (DSP_MMU_FAULT_ST_PERM |\
- DSP_MMU_FAULT_ST_TLB_MISS |\
- DSP_MMU_FAULT_ST_TRANS)
-
-static void do_mmu_int(struct work_struct *unused)
-{
- unsigned long status;
- unsigned long adh, adl;
- unsigned long dp;
-
- status = omap_mmu_read_reg(&dsp_mmu, DSP_MMU_FAULT_ST);
- adh = omap_mmu_read_reg(&dsp_mmu, DSP_MMU_FAULT_AD_H);
- adl = omap_mmu_read_reg(&dsp_mmu, DSP_MMU_FAULT_AD_L);
- dp = adh & DSP_MMU_FAULT_AD_H_DP;
- dsp_fault_adr = MK32(adh & DSP_MMU_FAULT_AD_H_ADR_MASK, adl);
-
- /* if the fault is masked, nothing to do */
- if ((status & MMUFAULT_MASK) == 0) {
- pr_debug( "DSP MMU interrupt, but ignoring.\n");
- /*
- * note: in OMAP1710,
- * when CACHE + DMA domain gets out of idle in DSP,
- * MMU interrupt occurs but DSP_MMU_FAULT_ST is not set.
- * in this case, we just ignore the interrupt.
- */
- if (status) {
- pr_debug( "%s%s%s%s\n",
- (status & DSP_MMU_FAULT_ST_PREF)?
- " (prefetch err)" : "",
- (status & DSP_MMU_FAULT_ST_PERM)?
- " (permission fault)" : "",
- (status & DSP_MMU_FAULT_ST_TLB_MISS)?
- " (TLB miss)" : "",
- (status & DSP_MMU_FAULT_ST_TRANS) ?
- " (translation fault)": "");
- pr_debug( "fault address = %#08x\n", dsp_fault_adr);
- }
- enable_irq(omap_dsp->mmu_irq);
- return;
- }
-
-
- pr_info("%s%s%s%s\n",
- (status & DSP_MMU_FAULT_ST_PREF)?
- (MMUFAULT_MASK & DSP_MMU_FAULT_ST_PREF)?
- " prefetch err":
- " (prefetch err)":
- "",
- (status & DSP_MMU_FAULT_ST_PERM)?
- (MMUFAULT_MASK & DSP_MMU_FAULT_ST_PERM)?
- " permission fault":
- " (permission fault)":
- "",
- (status & DSP_MMU_FAULT_ST_TLB_MISS)?
- (MMUFAULT_MASK & DSP_MMU_FAULT_ST_TLB_MISS)?
- " TLB miss":
- " (TLB miss)":
- "",
- (status & DSP_MMU_FAULT_ST_TRANS)?
- (MMUFAULT_MASK & DSP_MMU_FAULT_ST_TRANS)?
- " translation fault":
- " (translation fault)":
- "");
-
- pr_info("fault address = %#08x\n", dsp_fault_adr);
-
- if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
- dsp_err_set(ERRCODE_MMU, (unsigned long)dsp_fault_adr);
- else {
- __dsp_mmu_itack(&dsp_mmu);
-
- pr_info("Resetting DSP...\n");
- dsp_cpustat_request(CPUSTAT_RESET);
- /*
- * if we enable followings, semaphore lock should be avoided.
- *
- pr_info("Flushing DSP MMU...\n");
- exmap_flush();
- dsp_mmu_init();
- */
- }
-
- enable_irq(omap_dsp->mmu_irq);
-}
-#elif defined(CONFIG_ARCH_OMAP2)
-static void do_mmu_int(struct work_struct *unused)
-{
- unsigned long status;
-
- status = omap_mmu_read_reg(&dsp_mmu, DSP_MMU_IRQSTATUS);
- dsp_fault_adr = omap_mmu_read_reg(&dsp_mmu, DSP_MMU_FAULT_AD);
-
-#define MMU_IRQ_MASK \
- (DSP_MMU_IRQ_MULTIHITFAULT | \
- DSP_MMU_IRQ_TABLEWALKFAULT | \
- DSP_MMU_IRQ_EMUMISS | \
- DSP_MMU_IRQ_TRANSLATIONFAULT | \
- DSP_MMU_IRQ_TLBMISS)
-
- pr_info("%s%s%s%s%s\n",
- (status & DSP_MMU_IRQ_MULTIHITFAULT)?
- (MMU_IRQ_MASK & DSP_MMU_IRQ_MULTIHITFAULT)?
- " multi hit":
- " (multi hit)":
- "",
- (status & DSP_MMU_IRQ_TABLEWALKFAULT)?
- (MMU_IRQ_MASK & DSP_MMU_IRQ_TABLEWALKFAULT)?
- " table walk fault":
- " (table walk fault)":
- "",
- (status & DSP_MMU_IRQ_EMUMISS)?
- (MMU_IRQ_MASK & DSP_MMU_IRQ_EMUMISS)?
- " EMU miss":
- " (EMU miss)":
- "",
- (status & DSP_MMU_IRQ_TRANSLATIONFAULT)?
- (MMU_IRQ_MASK & DSP_MMU_IRQ_TRANSLATIONFAULT)?
- " translation fault":
- " (translation fault)":
- "",
- (status & DSP_MMU_IRQ_TLBMISS)?
- (MMU_IRQ_MASK & DSP_MMU_IRQ_TLBMISS)?
- " TLB miss":
- " (TLB miss)":
- "");
-
- pr_info("fault address = %#08x\n", dsp_fault_adr);
-
- if (dsp_cfgstat_get_stat() == CFGSTAT_READY)
- dsp_err_set(ERRCODE_MMU, (unsigned long)dsp_fault_adr);
- else {
- pr_info("Resetting DSP...\n");
- dsp_cpustat_request(CPUSTAT_RESET);
- }
-
- omap_mmu_disable(&dsp_mmu);
- omap_mmu_write_reg(&dsp_mmu, status, DSP_MMU_IRQSTATUS);
- omap_mmu_enable(&dsp_mmu, 0);
-
- enable_irq(omap_dsp->mmu_irq);
-}
-#endif
-
-static DECLARE_WORK(mmu_int_work, do_mmu_int);
-
#ifdef CONFIG_ARCH_OMAP1
static int dsp_mmu_itack(void)
{
omap_mmu_exmap(&dsp_mmu, dspadr, 0, SZ_4K, EXMAP_TYPE_MEM);
pr_info("omapdsp: falling into recovery runlevel...\n");
dsp_set_runlevel(RUNLEVEL_RECOVERY);
- __dsp_mmu_itack(&dsp_mmu);
+ omap_mmu_itack(&dsp_mmu);
udelay(100);
omap_mmu_exunmap(&dsp_mmu, dspadr);
dsp_err_clear(ERRCODE_MMU);