summaryrefslogtreecommitdiffstats
path: root/drivers/staging/tidspbridge/core/mmu_fault.c
blob: 42fe23f13eb76933978ccefbf9b9a2ff76bb03cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
 * mmu_fault.c
 *
 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
 *
 * Implements DSP MMU fault handling functions.
 *
 * Copyright (C) 2005-2006 Texas Instruments, Inc.
 *
 * This package is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/*  ----------------------------------- DSP/BIOS Bridge */
#include <dspbridge/std.h>
#include <dspbridge/dbdefs.h>

/*  ----------------------------------- Trace & Debug */
#include <dspbridge/host_os.h>
#include <dspbridge/dbc.h>

/*  ----------------------------------- OS Adaptation Layer */
#include <dspbridge/drv.h>

/*  ----------------------------------- Link Driver */
#include <dspbridge/dspdeh.h>

/* ------------------------------------ Hardware Abstraction Layer */
#include <hw_defs.h>
#include <hw_mmu.h>

/*  ----------------------------------- This */
#include "_deh.h"
#include <dspbridge/cfg.h>
#include "_tiomap.h"
#include "mmu_fault.h"

u32 fault_addr;

/*
 *  ======== mmu_fault_dpc ========
 *      Deferred procedure call to handle DSP MMU fault.
 */
void mmu_fault_dpc(IN unsigned long pRefData)
{
	struct deh_mgr *hdeh_mgr = (struct deh_mgr *)pRefData;

	if (!hdeh_mgr)
		return;

	bridge_deh_notify(hdeh_mgr, DSP_MMUFAULT, 0L);
}

/*
 *  ======== mmu_fault_isr ========
 *      ISR to be triggered by a DSP MMU fault interrupt.
 */
irqreturn_t mmu_fault_isr(int irq, IN void *pRefData)
{
	struct deh_mgr *deh_mgr_obj = pRefData;
	struct cfg_hostres *resources;
	u32 dmmu_event_mask;

	if (!deh_mgr_obj)
		return IRQ_HANDLED;

	resources = deh_mgr_obj->hbridge_context->resources;
	if (!resources) {
		dev_dbg(bridge, "%s: Failed to get Host Resources\n",
				__func__);
		return IRQ_HANDLED;
	}

	hw_mmu_event_status(resources->dw_dmmu_base, &dmmu_event_mask);
	if (dmmu_event_mask == HW_MMU_TRANSLATION_FAULT) {
		hw_mmu_fault_addr_read(resources->dw_dmmu_base, &fault_addr);
		dev_info(bridge, "%s: status=0x%x, fault_addr=0x%x\n", __func__,
				dmmu_event_mask, fault_addr);
		/*
		 * Schedule a DPC directly. In the future, it may be
		 * necessary to check if DSP MMU fault is intended for
		 * Bridge.
		 */
		tasklet_schedule(&deh_mgr_obj->dpc_tasklet);

		/* Reset err_info structure before use. */
		deh_mgr_obj->err_info.dw_err_mask = DSP_MMUFAULT;
		deh_mgr_obj->err_info.dw_val1 = fault_addr >> 16;
		deh_mgr_obj->err_info.dw_val2 = fault_addr & 0xFFFF;
		deh_mgr_obj->err_info.dw_val3 = 0L;
		/* Disable the MMU events, else once we clear it will
		 * start to raise INTs again */
		hw_mmu_event_disable(resources->dw_dmmu_base,
				HW_MMU_TRANSLATION_FAULT);
	} else {
		hw_mmu_event_disable(resources->dw_dmmu_base,
				HW_MMU_ALL_INTERRUPTS);
	}
	return IRQ_HANDLED;
}
OpenPOWER on IntegriCloud