Commit | Line | Data |
---|---|---|
458eef2f LW |
1 | /* |
2 | * Copyright (C) ST-Ericsson SA 2011 | |
3 | * | |
4 | * License terms: GNU General Public License (GPL) version 2 | |
5 | */ | |
6 | ||
7 | #include <linux/io.h> | |
8 | #include <asm/cacheflush.h> | |
9 | #include <asm/hardware/cache-l2x0.h> | |
10 | #include <mach/hardware.h> | |
11 | #include <mach/id.h> | |
12 | ||
13 | static void __iomem *l2x0_base; | |
14 | ||
15 | static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask) | |
16 | { | |
17 | /* wait for the operation to complete */ | |
18 | while (readl_relaxed(reg) & mask) | |
19 | cpu_relax(); | |
20 | } | |
21 | ||
22 | static inline void ux500_cache_sync(void) | |
23 | { | |
24 | writel_relaxed(0, l2x0_base + L2X0_CACHE_SYNC); | |
25 | ux500_cache_wait(l2x0_base + L2X0_CACHE_SYNC, 1); | |
26 | } | |
27 | ||
28 | /* | |
29 | * The L2 cache cannot be turned off in the non-secure world. | |
30 | * Dummy until a secure service is in place. | |
31 | */ | |
32 | static void ux500_l2x0_disable(void) | |
33 | { | |
34 | } | |
35 | ||
36 | /* | |
37 | * This is only called when doing a kexec, just after turning off the L2 | |
38 | * and L1 cache, and it is surrounded by a spinlock in the generic version. | |
39 | * However, we're not really turning off the L2 cache right now and the | |
40 | * PL310 does not support exclusive accesses (used to implement the spinlock). | |
41 | * So, the invalidation needs to be done without the spinlock. | |
42 | */ | |
43 | static void ux500_l2x0_inv_all(void) | |
44 | { | |
45 | uint32_t l2x0_way_mask = (1<<16) - 1; /* Bitmask of active ways */ | |
46 | ||
47 | /* invalidate all ways */ | |
48 | writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); | |
49 | ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); | |
50 | ux500_cache_sync(); | |
51 | } | |
52 | ||
53 | static int ux500_l2x0_init(void) | |
54 | { | |
55 | if (cpu_is_u5500()) | |
56 | l2x0_base = __io_address(U5500_L2CC_BASE); | |
57 | else if (cpu_is_u8500()) | |
58 | l2x0_base = __io_address(U8500_L2CC_BASE); | |
59 | else | |
60 | ux500_unknown_soc(); | |
61 | ||
62 | /* 64KB way size, 8 way associativity, force WA */ | |
63 | l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); | |
64 | ||
65 | /* Override invalidate function */ | |
66 | outer_cache.disable = ux500_l2x0_disable; | |
67 | outer_cache.inv_all = ux500_l2x0_inv_all; | |
68 | ||
69 | return 0; | |
70 | } | |
71 | ||
72 | early_initcall(ux500_l2x0_init); |