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