1014a9e22SJerin Jacob /* SPDX-License-Identifier: BSD-3-Clause
2014a9e22SJerin Jacob * Copyright(C) 2021 Marvell.
3014a9e22SJerin Jacob */
4014a9e22SJerin Jacob
5014a9e22SJerin Jacob #ifndef _ROC_IO_H_
6014a9e22SJerin Jacob #define _ROC_IO_H_
7014a9e22SJerin Jacob
83d171da6SBruce Richardson #include "roc_platform.h" /* for __plt_always_inline macro */
93d171da6SBruce Richardson
1070b6be62SNithin Dabilpuram #ifndef ROC_LMT_BASE_ID_GET
11014a9e22SJerin Jacob #define ROC_LMT_BASE_ID_GET(lmt_addr, lmt_id) \
12014a9e22SJerin Jacob do { \
13014a9e22SJerin Jacob /* 32 Lines per core */ \
14014a9e22SJerin Jacob lmt_id = plt_lcore_id() << ROC_LMT_LINES_PER_CORE_LOG2; \
15014a9e22SJerin Jacob /* Each line is of 128B */ \
16014a9e22SJerin Jacob (lmt_addr) += ((uint64_t)lmt_id << ROC_LMT_LINE_SIZE_LOG2); \
17014a9e22SJerin Jacob } while (0)
1870b6be62SNithin Dabilpuram #endif
19014a9e22SJerin Jacob
2070b6be62SNithin Dabilpuram /* Define it if not defined in roc_platform.h */
2170b6be62SNithin Dabilpuram #ifndef ROC_LMT_CPT_BASE_ID_GET
22ee48f711SNithin Dabilpuram #define ROC_LMT_CPT_BASE_ID_GET(lmt_addr, lmt_id) \
23ee48f711SNithin Dabilpuram do { \
24ee48f711SNithin Dabilpuram /* 16 Lines per core */ \
25ee48f711SNithin Dabilpuram lmt_id = ROC_LMT_CPT_BASE_ID_OFF; \
26ee48f711SNithin Dabilpuram lmt_id += (plt_lcore_id() << ROC_LMT_CPT_LINES_PER_CORE_LOG2); \
27ee48f711SNithin Dabilpuram /* Each line is of 128B */ \
28ee48f711SNithin Dabilpuram (lmt_addr) += ((uint64_t)lmt_id << ROC_LMT_LINE_SIZE_LOG2); \
29ee48f711SNithin Dabilpuram } while (0)
3070b6be62SNithin Dabilpuram #endif
31ee48f711SNithin Dabilpuram
32014a9e22SJerin Jacob #define roc_load_pair(val0, val1, addr) \
33*93998f3cSTyler Retzlaff __extension__ ({ \
34014a9e22SJerin Jacob asm volatile("ldp %x[x0], %x[x1], [%x[p1]]" \
35014a9e22SJerin Jacob : [x0] "=r"(val0), [x1] "=r"(val1) \
36014a9e22SJerin Jacob : [p1] "r"(addr)); \
37014a9e22SJerin Jacob })
38014a9e22SJerin Jacob
39014a9e22SJerin Jacob #define roc_store_pair(val0, val1, addr) \
40*93998f3cSTyler Retzlaff __extension__ ({ \
41014a9e22SJerin Jacob asm volatile( \
42014a9e22SJerin Jacob "stp %x[x0], %x[x1], [%x[p1], #0]!" ::[x0] "r"(val0), \
43014a9e22SJerin Jacob [x1] "r"(val1), [p1] "r"(addr)); \
44014a9e22SJerin Jacob })
45014a9e22SJerin Jacob
46014a9e22SJerin Jacob #define roc_prefetch_store_keep(ptr) \
47*93998f3cSTyler Retzlaff __extension__ ({ asm volatile("prfm pstl1keep, [%x0]\n" : : "r"(ptr)); })
48014a9e22SJerin Jacob
49014a9e22SJerin Jacob #if defined(__clang__)
50014a9e22SJerin Jacob static __plt_always_inline void
roc_atomic128_cas_noreturn(uint64_t swap0,uint64_t swap1,int64_t * ptr)51014a9e22SJerin Jacob roc_atomic128_cas_noreturn(uint64_t swap0, uint64_t swap1, int64_t *ptr)
52014a9e22SJerin Jacob {
53014a9e22SJerin Jacob register uint64_t x0 __asm("x0") = swap0;
54014a9e22SJerin Jacob register uint64_t x1 __asm("x1") = swap1;
55014a9e22SJerin Jacob
56014a9e22SJerin Jacob asm volatile(PLT_CPU_FEATURE_PREAMBLE
57014a9e22SJerin Jacob "casp %[x0], %[x1], %[x0], %[x1], [%[ptr]]\n"
58014a9e22SJerin Jacob : [x0] "+r"(x0), [x1] "+r"(x1)
59014a9e22SJerin Jacob : [ptr] "r"(ptr)
60014a9e22SJerin Jacob : "memory");
61014a9e22SJerin Jacob }
62014a9e22SJerin Jacob #else
63014a9e22SJerin Jacob static __plt_always_inline void
roc_atomic128_cas_noreturn(uint64_t swap0,uint64_t swap1,uint64_t ptr)64014a9e22SJerin Jacob roc_atomic128_cas_noreturn(uint64_t swap0, uint64_t swap1, uint64_t ptr)
65014a9e22SJerin Jacob {
66014a9e22SJerin Jacob __uint128_t wdata = swap0 | ((__uint128_t)swap1 << 64);
67014a9e22SJerin Jacob
68014a9e22SJerin Jacob asm volatile(PLT_CPU_FEATURE_PREAMBLE
69014a9e22SJerin Jacob "casp %[wdata], %H[wdata], %[wdata], %H[wdata], [%[ptr]]\n"
70014a9e22SJerin Jacob : [wdata] "+r"(wdata)
71014a9e22SJerin Jacob : [ptr] "r"(ptr)
72014a9e22SJerin Jacob : "memory");
73014a9e22SJerin Jacob }
74014a9e22SJerin Jacob #endif
75014a9e22SJerin Jacob
76014a9e22SJerin Jacob static __plt_always_inline uint64_t
roc_atomic64_cas(uint64_t compare,uint64_t swap,int64_t * ptr)77014a9e22SJerin Jacob roc_atomic64_cas(uint64_t compare, uint64_t swap, int64_t *ptr)
78014a9e22SJerin Jacob {
79014a9e22SJerin Jacob asm volatile(PLT_CPU_FEATURE_PREAMBLE
80014a9e22SJerin Jacob "cas %[compare], %[swap], [%[ptr]]\n"
81014a9e22SJerin Jacob : [compare] "+r"(compare)
82014a9e22SJerin Jacob : [swap] "r"(swap), [ptr] "r"(ptr)
83014a9e22SJerin Jacob : "memory");
84014a9e22SJerin Jacob
85014a9e22SJerin Jacob return compare;
86014a9e22SJerin Jacob }
87014a9e22SJerin Jacob
88014a9e22SJerin Jacob static __plt_always_inline uint64_t
roc_atomic64_casl(uint64_t compare,uint64_t swap,int64_t * ptr)8909cad550SAshwin Sekhar T K roc_atomic64_casl(uint64_t compare, uint64_t swap, int64_t *ptr)
9009cad550SAshwin Sekhar T K {
9109cad550SAshwin Sekhar T K asm volatile(PLT_CPU_FEATURE_PREAMBLE
9209cad550SAshwin Sekhar T K "casl %[compare], %[swap], [%[ptr]]\n"
9309cad550SAshwin Sekhar T K : [compare] "+r"(compare)
9409cad550SAshwin Sekhar T K : [swap] "r"(swap), [ptr] "r"(ptr)
9509cad550SAshwin Sekhar T K : "memory");
9609cad550SAshwin Sekhar T K
9709cad550SAshwin Sekhar T K return compare;
9809cad550SAshwin Sekhar T K }
9909cad550SAshwin Sekhar T K
10009cad550SAshwin Sekhar T K static __plt_always_inline uint64_t
roc_atomic64_add_nosync(int64_t incr,int64_t * ptr)101014a9e22SJerin Jacob roc_atomic64_add_nosync(int64_t incr, int64_t *ptr)
102014a9e22SJerin Jacob {
103014a9e22SJerin Jacob uint64_t result;
104014a9e22SJerin Jacob
105014a9e22SJerin Jacob /* Atomic add with no ordering */
106014a9e22SJerin Jacob asm volatile(PLT_CPU_FEATURE_PREAMBLE "ldadd %x[i], %x[r], [%[b]]"
107014a9e22SJerin Jacob : [r] "=r"(result), "+m"(*ptr)
108014a9e22SJerin Jacob : [i] "r"(incr), [b] "r"(ptr)
109014a9e22SJerin Jacob : "memory");
110014a9e22SJerin Jacob return result;
111014a9e22SJerin Jacob }
112014a9e22SJerin Jacob
113014a9e22SJerin Jacob static __plt_always_inline uint64_t
roc_atomic64_add_sync(int64_t incr,int64_t * ptr)114014a9e22SJerin Jacob roc_atomic64_add_sync(int64_t incr, int64_t *ptr)
115014a9e22SJerin Jacob {
116014a9e22SJerin Jacob uint64_t result;
117014a9e22SJerin Jacob
118014a9e22SJerin Jacob /* Atomic add with ordering */
119014a9e22SJerin Jacob asm volatile(PLT_CPU_FEATURE_PREAMBLE "ldadda %x[i], %x[r], [%[b]]"
120014a9e22SJerin Jacob : [r] "=r"(result), "+m"(*ptr)
121014a9e22SJerin Jacob : [i] "r"(incr), [b] "r"(ptr)
122014a9e22SJerin Jacob : "memory");
123014a9e22SJerin Jacob return result;
124014a9e22SJerin Jacob }
125014a9e22SJerin Jacob
126014a9e22SJerin Jacob static __plt_always_inline uint64_t
roc_lmt_submit_ldeor(plt_iova_t io_address)127014a9e22SJerin Jacob roc_lmt_submit_ldeor(plt_iova_t io_address)
128014a9e22SJerin Jacob {
129014a9e22SJerin Jacob uint64_t result;
130014a9e22SJerin Jacob
131014a9e22SJerin Jacob asm volatile(PLT_CPU_FEATURE_PREAMBLE "ldeor xzr, %x[rf], [%[rs]]"
132014a9e22SJerin Jacob : [rf] "=r"(result)
133a032b598SNithin Dabilpuram : [rs] "r"(io_address)
134a032b598SNithin Dabilpuram : "memory");
135014a9e22SJerin Jacob return result;
136014a9e22SJerin Jacob }
137014a9e22SJerin Jacob
138014a9e22SJerin Jacob static __plt_always_inline uint64_t
roc_lmt_submit_ldeorl(plt_iova_t io_address)139014a9e22SJerin Jacob roc_lmt_submit_ldeorl(plt_iova_t io_address)
140014a9e22SJerin Jacob {
141014a9e22SJerin Jacob uint64_t result;
142014a9e22SJerin Jacob
143014a9e22SJerin Jacob asm volatile(PLT_CPU_FEATURE_PREAMBLE "ldeorl xzr,%x[rf],[%[rs]]"
144014a9e22SJerin Jacob : [rf] "=r"(result)
145a032b598SNithin Dabilpuram : [rs] "r"(io_address)
146a032b598SNithin Dabilpuram : "memory");
147014a9e22SJerin Jacob return result;
148014a9e22SJerin Jacob }
149014a9e22SJerin Jacob
150014a9e22SJerin Jacob static __plt_always_inline void
roc_lmt_submit_steor(uint64_t data,plt_iova_t io_address)151014a9e22SJerin Jacob roc_lmt_submit_steor(uint64_t data, plt_iova_t io_address)
152014a9e22SJerin Jacob {
153014a9e22SJerin Jacob asm volatile(PLT_CPU_FEATURE_PREAMBLE
154014a9e22SJerin Jacob "steor %x[d], [%[rs]]" ::[d] "r"(data),
155a032b598SNithin Dabilpuram [rs] "r"(io_address)
156a032b598SNithin Dabilpuram : "memory");
157014a9e22SJerin Jacob }
158014a9e22SJerin Jacob
159014a9e22SJerin Jacob static __plt_always_inline void
roc_lmt_submit_steorl(uint64_t data,plt_iova_t io_address)160014a9e22SJerin Jacob roc_lmt_submit_steorl(uint64_t data, plt_iova_t io_address)
161014a9e22SJerin Jacob {
162014a9e22SJerin Jacob asm volatile(PLT_CPU_FEATURE_PREAMBLE
163014a9e22SJerin Jacob "steorl %x[d], [%[rs]]" ::[d] "r"(data),
164a032b598SNithin Dabilpuram [rs] "r"(io_address)
165a032b598SNithin Dabilpuram : "memory");
166014a9e22SJerin Jacob }
167014a9e22SJerin Jacob
168014a9e22SJerin Jacob static __plt_always_inline void
roc_lmt_mov(void * out,const void * in,const uint32_t lmtext)169014a9e22SJerin Jacob roc_lmt_mov(void *out, const void *in, const uint32_t lmtext)
170014a9e22SJerin Jacob {
171014a9e22SJerin Jacob volatile const __uint128_t *src128 = (const __uint128_t *)in;
172014a9e22SJerin Jacob volatile __uint128_t *dst128 = (__uint128_t *)out;
173f1cdb3c5SPavan Nikhilesh uint32_t i;
174014a9e22SJerin Jacob
175014a9e22SJerin Jacob dst128[0] = src128[0];
176014a9e22SJerin Jacob dst128[1] = src128[1];
177014a9e22SJerin Jacob /* lmtext receives following value:
178014a9e22SJerin Jacob * 1: NIX_SUBDC_EXT needed i.e. tx vlan case
179014a9e22SJerin Jacob */
180f1cdb3c5SPavan Nikhilesh for (i = 0; i < lmtext; i++)
181f1cdb3c5SPavan Nikhilesh dst128[2 + i] = src128[2 + i];
182ae2c2cb6SPavan Nikhilesh }
183ae2c2cb6SPavan Nikhilesh
184ae2c2cb6SPavan Nikhilesh static __plt_always_inline void
roc_lmt_mov64(void * out,const void * in)185ae2c2cb6SPavan Nikhilesh roc_lmt_mov64(void *out, const void *in)
186ae2c2cb6SPavan Nikhilesh {
187ae2c2cb6SPavan Nikhilesh volatile const __uint128_t *src128 = (const __uint128_t *)in;
188ae2c2cb6SPavan Nikhilesh volatile __uint128_t *dst128 = (__uint128_t *)out;
189ae2c2cb6SPavan Nikhilesh
190ae2c2cb6SPavan Nikhilesh dst128[0] = src128[0];
191ae2c2cb6SPavan Nikhilesh dst128[1] = src128[1];
192ae2c2cb6SPavan Nikhilesh dst128[2] = src128[2];
193014a9e22SJerin Jacob dst128[3] = src128[3];
194014a9e22SJerin Jacob }
195ae2c2cb6SPavan Nikhilesh
196ae2c2cb6SPavan Nikhilesh static __plt_always_inline void
roc_lmt_mov_nv(void * out,const void * in,const uint32_t lmtext)197ae2c2cb6SPavan Nikhilesh roc_lmt_mov_nv(void *out, const void *in, const uint32_t lmtext)
198ae2c2cb6SPavan Nikhilesh {
199ae2c2cb6SPavan Nikhilesh const __uint128_t *src128 = (const __uint128_t *)in;
200ae2c2cb6SPavan Nikhilesh __uint128_t *dst128 = (__uint128_t *)out;
201ae2c2cb6SPavan Nikhilesh
202ae2c2cb6SPavan Nikhilesh dst128[0] = src128[0];
203ae2c2cb6SPavan Nikhilesh dst128[1] = src128[1];
204ae2c2cb6SPavan Nikhilesh /* lmtext receives following value:
205ae2c2cb6SPavan Nikhilesh * 1: NIX_SUBDC_EXT needed i.e. tx vlan case
206ae2c2cb6SPavan Nikhilesh */
207ae2c2cb6SPavan Nikhilesh if (lmtext)
208ae2c2cb6SPavan Nikhilesh dst128[2] = src128[2];
209014a9e22SJerin Jacob }
210014a9e22SJerin Jacob
211014a9e22SJerin Jacob static __plt_always_inline void
roc_lmt_mov_seg(void * out,const void * in,const uint16_t segdw)212014a9e22SJerin Jacob roc_lmt_mov_seg(void *out, const void *in, const uint16_t segdw)
213014a9e22SJerin Jacob {
214014a9e22SJerin Jacob volatile const __uint128_t *src128 = (const __uint128_t *)in;
215014a9e22SJerin Jacob volatile __uint128_t *dst128 = (__uint128_t *)out;
216014a9e22SJerin Jacob uint8_t i;
217014a9e22SJerin Jacob
218014a9e22SJerin Jacob for (i = 0; i < segdw; i++)
219014a9e22SJerin Jacob dst128[i] = src128[i];
220014a9e22SJerin Jacob }
221014a9e22SJerin Jacob
222014a9e22SJerin Jacob static __plt_always_inline void
roc_lmt_mov_one(void * out,const void * in)223014a9e22SJerin Jacob roc_lmt_mov_one(void *out, const void *in)
224014a9e22SJerin Jacob {
225014a9e22SJerin Jacob volatile const __uint128_t *src128 = (const __uint128_t *)in;
226014a9e22SJerin Jacob volatile __uint128_t *dst128 = (__uint128_t *)out;
227014a9e22SJerin Jacob
228014a9e22SJerin Jacob *dst128 = *src128;
229014a9e22SJerin Jacob }
230014a9e22SJerin Jacob
231014a9e22SJerin Jacob /* Non volatile version of roc_lmt_mov_seg() */
232014a9e22SJerin Jacob static __plt_always_inline void
roc_lmt_mov_seg_nv(void * out,const void * in,const uint16_t segdw)233014a9e22SJerin Jacob roc_lmt_mov_seg_nv(void *out, const void *in, const uint16_t segdw)
234014a9e22SJerin Jacob {
235014a9e22SJerin Jacob const __uint128_t *src128 = (const __uint128_t *)in;
236014a9e22SJerin Jacob __uint128_t *dst128 = (__uint128_t *)out;
237014a9e22SJerin Jacob uint8_t i;
238014a9e22SJerin Jacob
239014a9e22SJerin Jacob for (i = 0; i < segdw; i++)
240014a9e22SJerin Jacob dst128[i] = src128[i];
241014a9e22SJerin Jacob }
242014a9e22SJerin Jacob
243804c108bSTomasz Duszynski static __plt_always_inline void
roc_atf_ret(void)244804c108bSTomasz Duszynski roc_atf_ret(void)
245804c108bSTomasz Duszynski {
246804c108bSTomasz Duszynski /* This will allow wfi in EL0 to cause async exception to EL3
247804c108bSTomasz Duszynski * which will optionally perform necessary actions.
248804c108bSTomasz Duszynski */
249804c108bSTomasz Duszynski __asm("wfi");
250804c108bSTomasz Duszynski }
251804c108bSTomasz Duszynski
252014a9e22SJerin Jacob #endif /* _ROC_IO_H_ */
253