staging: ti dspbridge: add core driver sources
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / tidspbridge / core / mmu_fault.c
blob5c0124f70732b4fda2b9cc1f99f499a802f510df
1 /*
2 * mmu_fault.c
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6 * Implements DSP MMU fault handling functions.
8 * Copyright (C) 2005-2006 Texas Instruments, Inc.
10 * This package is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
14 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 /* ----------------------------------- DSP/BIOS Bridge */
20 #include <dspbridge/std.h>
21 #include <dspbridge/dbdefs.h>
23 /* ----------------------------------- Trace & Debug */
24 #include <dspbridge/host_os.h>
25 #include <dspbridge/dbc.h>
27 /* ----------------------------------- OS Adaptation Layer */
28 #include <dspbridge/drv.h>
30 /* ----------------------------------- Link Driver */
31 #include <dspbridge/dspdeh.h>
33 /* ------------------------------------ Hardware Abstraction Layer */
34 #include <hw_defs.h>
35 #include <hw_mmu.h>
37 /* ----------------------------------- This */
38 #include "_deh.h"
39 #include <dspbridge/cfg.h>
40 #include "_tiomap.h"
41 #include "mmu_fault.h"
43 static u32 dmmu_event_mask;
44 u32 fault_addr;
46 static bool mmu_check_if_fault(struct bridge_dev_context *dev_context);
49 * ======== mmu_fault_dpc ========
50 * Deferred procedure call to handle DSP MMU fault.
52 void mmu_fault_dpc(IN unsigned long pRefData)
54 struct deh_mgr *hdeh_mgr = (struct deh_mgr *)pRefData;
56 if (hdeh_mgr)
57 bridge_deh_notify(hdeh_mgr, DSP_MMUFAULT, 0L);
62 * ======== mmu_fault_isr ========
63 * ISR to be triggered by a DSP MMU fault interrupt.
65 irqreturn_t mmu_fault_isr(int irq, IN void *pRefData)
67 struct deh_mgr *deh_mgr_obj = (struct deh_mgr *)pRefData;
68 struct bridge_dev_context *dev_context;
69 struct cfg_hostres *resources;
71 DBC_REQUIRE(irq == INT_DSP_MMU_IRQ);
72 DBC_REQUIRE(deh_mgr_obj);
74 if (deh_mgr_obj) {
76 dev_context =
77 (struct bridge_dev_context *)deh_mgr_obj->hbridge_context;
79 resources = dev_context->resources;
81 if (!resources) {
82 dev_dbg(bridge, "%s: Failed to get Host Resources\n",
83 __func__);
84 return IRQ_HANDLED;
86 if (mmu_check_if_fault(dev_context)) {
87 printk(KERN_INFO "***** DSPMMU FAULT ***** IRQStatus "
88 "0x%x\n", dmmu_event_mask);
89 printk(KERN_INFO "***** DSPMMU FAULT ***** fault_addr "
90 "0x%x\n", fault_addr);
92 * Schedule a DPC directly. In the future, it may be
93 * necessary to check if DSP MMU fault is intended for
94 * Bridge.
96 tasklet_schedule(&deh_mgr_obj->dpc_tasklet);
98 /* Reset err_info structure before use. */
99 deh_mgr_obj->err_info.dw_err_mask = DSP_MMUFAULT;
100 deh_mgr_obj->err_info.dw_val1 = fault_addr >> 16;
101 deh_mgr_obj->err_info.dw_val2 = fault_addr & 0xFFFF;
102 deh_mgr_obj->err_info.dw_val3 = 0L;
103 /* Disable the MMU events, else once we clear it will
104 * start to raise INTs again */
105 hw_mmu_event_disable(resources->dw_dmmu_base,
106 HW_MMU_TRANSLATION_FAULT);
107 } else {
108 hw_mmu_event_disable(resources->dw_dmmu_base,
109 HW_MMU_ALL_INTERRUPTS);
112 return IRQ_HANDLED;
116 * ======== mmu_check_if_fault ========
117 * Check to see if MMU Fault is valid TLB miss from DSP
118 * Note: This function is called from an ISR
120 static bool mmu_check_if_fault(struct bridge_dev_context *dev_context)
123 bool ret = false;
124 hw_status hw_status_obj;
125 struct cfg_hostres *resources = dev_context->resources;
127 if (!resources) {
128 dev_dbg(bridge, "%s: Failed to get Host Resources in\n",
129 __func__);
130 return ret;
132 hw_status_obj =
133 hw_mmu_event_status(resources->dw_dmmu_base, &dmmu_event_mask);
134 if (dmmu_event_mask == HW_MMU_TRANSLATION_FAULT) {
135 hw_mmu_fault_addr_read(resources->dw_dmmu_base, &fault_addr);
136 ret = true;
138 return ret;