1/*
2 * Copyright 2014, General Dynamics C4 Systems
3 *
4 * This software may be distributed and modified according to the terms of
5 * the GNU General Public License version 2. Note that NO WARRANTY is provided.
6 * See "LICENSE_GPLv2.txt" for details.
7 *
8 * @TAG(GD_GPL)
9 */
10
11#include <config.h>
12#include <api/types.h>
13#include <arch/machine.h>
14#include <arch/machine/hardware.h>
15#include <util.h>
16
17/* Prototyped here as this is referenced from assembly */
18void arm_errata(void);
19
20#ifdef ARM1136_WORKAROUND
21/*
22 * Potentially work around ARM1136 errata #364296, which can cause data
23 * cache corruption.
24 *
25 * The fix involves disabling hit-under-miss via an undocumented bit in
26 * the aux control register, as well as the FI bit in the control
27 * register. The result of enabling these two bits is for fast
28 * interrupts to *not* be enabled, but hit-under-miss to be disabled. We
29 * only need to do this for a particular revision of the ARM1136.
30 */
31BOOT_CODE static void
32errata_arm1136(void)
33{
34    /* See if we are affected by the errata. */
35    if ((getProcessorID() & ~0xf) == ARM1136_R0PX) {
36
37        /* Enable the Fast Interrupts bit in the control register. */
38        writeSystemControlRegister(
39            readSystemControlRegister() | BIT(CONTROL_FI));
40
41        /* Set undocumented bit 31 in the auxiliary control register */
42        writeAuxiliaryControlRegister(
43            readAuxiliaryControlRegister() | BIT(31));
44    }
45}
46#endif
47
48#ifdef CONFIG_ARM_ERRATA_773022
49/*
50 * There is an errata for Cortex-A15 up to r0p4 where the loop buffer
51 * may deliver incorrect instructions. The work around is to disable
52 * the loop buffer. Errata is number 773022.
53 */
54BOOT_CODE static void errata_armA15_773022(void)
55{
56    /* Fetch the processor primary part number. */
57    uint32_t proc_id = getProcessorID();
58    uint32_t variant = (proc_id >> 20) & MASK(4);
59    uint32_t revision = proc_id & MASK(4);
60    uint32_t part = (proc_id >> 4) & MASK(12);
61
62    /* Check that we are running A15 and a revision upto r0p4. */
63    if (part == 0xc0f && variant == 0 && revision <= 4) {
64        /* Disable loop buffer in the auxiliary control register */
65        writeAuxiliaryControlRegister(
66            readAuxiliaryControlRegister() | BIT(1));
67    }
68}
69#endif
70
71BOOT_CODE void VISIBLE arm_errata(void)
72{
73#ifdef ARM1136_WORKAROUND
74    errata_arm1136();
75#endif
76#ifdef CONFIG_ARM_ERRATA_773022
77    errata_armA15_773022();
78#endif
79}
80
81