Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/cache/starfive_starlink_cache.c
26378 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Cache Management Operations for StarFive's Starlink cache controller
4
*
5
* Copyright (C) 2024 Shanghai StarFive Technology Co., Ltd.
6
*
7
* Author: Joshua Yeong <[email protected]>
8
*/
9
10
#include <linux/bitfield.h>
11
#include <linux/cacheflush.h>
12
#include <linux/iopoll.h>
13
#include <linux/of_address.h>
14
15
#include <asm/dma-noncoherent.h>
16
17
#define STARLINK_CACHE_FLUSH_START_ADDR 0x0
18
#define STARLINK_CACHE_FLUSH_END_ADDR 0x8
19
#define STARLINK_CACHE_FLUSH_CTL 0x10
20
#define STARLINK_CACHE_ALIGN 0x40
21
22
#define STARLINK_CACHE_ADDRESS_RANGE_MASK GENMASK(39, 0)
23
#define STARLINK_CACHE_FLUSH_CTL_MODE_MASK GENMASK(2, 1)
24
#define STARLINK_CACHE_FLUSH_CTL_ENABLE_MASK BIT(0)
25
26
#define STARLINK_CACHE_FLUSH_CTL_CLEAN_INVALIDATE 0
27
#define STARLINK_CACHE_FLUSH_CTL_MAKE_INVALIDATE 1
28
#define STARLINK_CACHE_FLUSH_CTL_CLEAN_SHARED 2
29
#define STARLINK_CACHE_FLUSH_POLL_DELAY_US 1
30
#define STARLINK_CACHE_FLUSH_TIMEOUT_US 5000000
31
32
static void __iomem *starlink_cache_base;
33
34
static void starlink_cache_flush_complete(void)
35
{
36
volatile void __iomem *ctl = starlink_cache_base + STARLINK_CACHE_FLUSH_CTL;
37
u64 v;
38
int ret;
39
40
ret = readq_poll_timeout_atomic(ctl, v, !(v & STARLINK_CACHE_FLUSH_CTL_ENABLE_MASK),
41
STARLINK_CACHE_FLUSH_POLL_DELAY_US,
42
STARLINK_CACHE_FLUSH_TIMEOUT_US);
43
if (ret)
44
WARN(1, "StarFive Starlink cache flush operation timeout\n");
45
}
46
47
static void starlink_cache_dma_cache_wback(phys_addr_t paddr, unsigned long size)
48
{
49
writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
50
starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
51
writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
52
starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
53
54
mb();
55
writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
56
STARLINK_CACHE_FLUSH_CTL_CLEAN_SHARED),
57
starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
58
59
starlink_cache_flush_complete();
60
}
61
62
static void starlink_cache_dma_cache_invalidate(phys_addr_t paddr, unsigned long size)
63
{
64
writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
65
starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
66
writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
67
starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
68
69
mb();
70
writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
71
STARLINK_CACHE_FLUSH_CTL_MAKE_INVALIDATE),
72
starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
73
74
starlink_cache_flush_complete();
75
}
76
77
static void starlink_cache_dma_cache_wback_inv(phys_addr_t paddr, unsigned long size)
78
{
79
writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr),
80
starlink_cache_base + STARLINK_CACHE_FLUSH_START_ADDR);
81
writeq(FIELD_PREP(STARLINK_CACHE_ADDRESS_RANGE_MASK, paddr + size),
82
starlink_cache_base + STARLINK_CACHE_FLUSH_END_ADDR);
83
84
mb();
85
writeq(FIELD_PREP(STARLINK_CACHE_FLUSH_CTL_MODE_MASK,
86
STARLINK_CACHE_FLUSH_CTL_CLEAN_INVALIDATE),
87
starlink_cache_base + STARLINK_CACHE_FLUSH_CTL);
88
89
starlink_cache_flush_complete();
90
}
91
92
static const struct riscv_nonstd_cache_ops starlink_cache_ops = {
93
.wback = &starlink_cache_dma_cache_wback,
94
.inv = &starlink_cache_dma_cache_invalidate,
95
.wback_inv = &starlink_cache_dma_cache_wback_inv,
96
};
97
98
static const struct of_device_id starlink_cache_ids[] = {
99
{ .compatible = "starfive,jh8100-starlink-cache" },
100
{ /* sentinel */ }
101
};
102
103
static int __init starlink_cache_init(void)
104
{
105
struct device_node *np;
106
u32 block_size;
107
int ret;
108
109
np = of_find_matching_node(NULL, starlink_cache_ids);
110
if (!of_device_is_available(np))
111
return -ENODEV;
112
113
ret = of_property_read_u32(np, "cache-block-size", &block_size);
114
if (ret)
115
return ret;
116
117
if (block_size % STARLINK_CACHE_ALIGN)
118
return -EINVAL;
119
120
starlink_cache_base = of_iomap(np, 0);
121
if (!starlink_cache_base)
122
return -ENOMEM;
123
124
riscv_cbom_block_size = block_size;
125
riscv_noncoherent_supported();
126
riscv_noncoherent_register_cache_ops(&starlink_cache_ops);
127
128
return 0;
129
}
130
arch_initcall(starlink_cache_init);
131
132