1 | // SPDX-License-Identifier: GPL-2.0 OR MIT |
2 | /* Copyright 2017-2019 Qiang Yu <yuq825@gmail.com> */ |
3 | |
4 | #include <linux/iopoll.h> |
5 | #include <linux/device.h> |
6 | |
7 | #include "lima_device.h" |
8 | #include "lima_l2_cache.h" |
9 | #include "lima_regs.h" |
10 | |
11 | #define l2_cache_write(reg, data) writel(data, ip->iomem + reg) |
12 | #define l2_cache_read(reg) readl(ip->iomem + reg) |
13 | |
14 | static int lima_l2_cache_wait_idle(struct lima_ip *ip) |
15 | { |
16 | struct lima_device *dev = ip->dev; |
17 | int err; |
18 | u32 v; |
19 | |
20 | err = readl_poll_timeout(ip->iomem + LIMA_L2_CACHE_STATUS, v, |
21 | !(v & LIMA_L2_CACHE_STATUS_COMMAND_BUSY), |
22 | 0, 1000); |
23 | if (err) { |
24 | dev_err(dev->dev, "l2 cache wait command timeout\n" ); |
25 | return err; |
26 | } |
27 | return 0; |
28 | } |
29 | |
30 | int lima_l2_cache_flush(struct lima_ip *ip) |
31 | { |
32 | int ret; |
33 | |
34 | spin_lock(lock: &ip->data.lock); |
35 | l2_cache_write(LIMA_L2_CACHE_COMMAND, LIMA_L2_CACHE_COMMAND_CLEAR_ALL); |
36 | ret = lima_l2_cache_wait_idle(ip); |
37 | spin_unlock(lock: &ip->data.lock); |
38 | return ret; |
39 | } |
40 | |
41 | static int lima_l2_cache_hw_init(struct lima_ip *ip) |
42 | { |
43 | int err; |
44 | |
45 | err = lima_l2_cache_flush(ip); |
46 | if (err) |
47 | return err; |
48 | |
49 | l2_cache_write(LIMA_L2_CACHE_ENABLE, |
50 | LIMA_L2_CACHE_ENABLE_ACCESS | |
51 | LIMA_L2_CACHE_ENABLE_READ_ALLOCATE); |
52 | l2_cache_write(LIMA_L2_CACHE_MAX_READS, 0x1c); |
53 | |
54 | return 0; |
55 | } |
56 | |
57 | int lima_l2_cache_resume(struct lima_ip *ip) |
58 | { |
59 | return lima_l2_cache_hw_init(ip); |
60 | } |
61 | |
62 | void lima_l2_cache_suspend(struct lima_ip *ip) |
63 | { |
64 | |
65 | } |
66 | |
67 | int lima_l2_cache_init(struct lima_ip *ip) |
68 | { |
69 | int i; |
70 | u32 size; |
71 | struct lima_device *dev = ip->dev; |
72 | |
73 | /* l2_cache2 only exists when one of PP4-7 present */ |
74 | if (ip->id == lima_ip_l2_cache2) { |
75 | for (i = lima_ip_pp4; i <= lima_ip_pp7; i++) { |
76 | if (dev->ip[i].present) |
77 | break; |
78 | } |
79 | if (i > lima_ip_pp7) |
80 | return -ENODEV; |
81 | } |
82 | |
83 | spin_lock_init(&ip->data.lock); |
84 | |
85 | size = l2_cache_read(LIMA_L2_CACHE_SIZE); |
86 | dev_info(dev->dev, "l2 cache %uK, %u-way, %ubyte cache line, %ubit external bus\n" , |
87 | 1 << (((size >> 16) & 0xff) - 10), |
88 | 1 << ((size >> 8) & 0xff), |
89 | 1 << (size & 0xff), |
90 | 1 << ((size >> 24) & 0xff)); |
91 | |
92 | return lima_l2_cache_hw_init(ip); |
93 | } |
94 | |
95 | void lima_l2_cache_fini(struct lima_ip *ip) |
96 | { |
97 | |
98 | } |
99 | |