summaryrefslogtreecommitdiff
path: root/big-little/virtualisor/kfscb_trap_handler.c
blob: 7813cce21f36e086770425e4d5af6f0833671769 (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
/*
 * Copyright (c) 2012, ARM Limited. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with
 * or without modification, are permitted provided that the
 * following conditions are met:
 *
 * Redistributions of source code must retain the above
 * copyright notice, this list of conditions and the
 * following disclaimer.
 *
 * Redistributions in binary form must reproduce the
 * above copyright notice, this list of conditions and
 * the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of ARM nor the names of its
 * contributors may be used to endorse or promote products
 * derived from this software without specific prior written
 * permission.
 */

#include "misc.h"
#include "virt_helpers.h"
#include "context.h"

/*
 * Whether A15 or A7, the KFSCB accesses are virtualised in exactly the same
 * manner.
 */
void handle_kfscb_abort(unsigned pa, unsigned *data, unsigned write)
{
	unsigned reg_offset = pa & 0xfff;
	unsigned cluster_id = read_clusterid();

	/*
	 * The OS always asks for the Eagle resets.
	 * We have to be more intelligent and return
	 * the apt value.
	 */
	if (cluster_id == KFC)
		pa += 4;

	switch (reg_offset) {

	/* Access to KFSCB registers */
	case (RST_HOLD0):
		if (write) {
			/* Entry */
			if (*data & (*data ^ read32(pa + 0xc))) {
				save_context(find_first_cpu(), OP_TYPE_HP);
				smc(SMC_SEC_SHUTDOWN, *data, OP_TYPE_HP);
			} else {
				/* Exit */
				write32(pa, *data);
			}
		} else {
			*data = read32(pa);
		}

		break;

	default:
		if (write) {
			write32(pa, *data);
		} else {
			*data = read32(pa);
		}
	}

	return;
}