xref: /openbmc/linux/drivers/gpu/drm/lima/lima_l2_cache.c (revision 4b4193256c8d3bc3a5397b5cd9494c2ad386317d)
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