1 /*
2  * Copyright (c) 2021-2022 Arm Limited. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "atu_rss_drv.h"
18 
19 #include <stddef.h>
20 
21 #define ATU_GET_ATUPS(atu_base) (                                     \
22     (uint8_t)(((atu_base)->atubc & ATU_ATUBC_PS_MASK) >> ATU_ATUBC_PS_OFF))
23 
24 #define ATU_ATUBC_PS_OFF                4u
25     /*!< ATU Build Configuration Register Page Size bit field offset */
26 #define ATU_ATUBC_PS_MASK               (0xFu << ATU_ATUBC_PS_OFF)
27     /*!< ATU Build Configuration Register Page Size bit field mask */
28 #define ATU_ATUBC_RC_OFF                0u
29     /*!< ATU Build Configuration Register Region Count bit field offset */
30 #define ATU_ATUBC_RC_MASK               (0x7u << ATU_ATUBC_RC_OFF)
31     /*!< ATU Build Configuration Register Region Count bit field mask */
32 #define ATU_ATUIS_ME_OFF                0u
33     /*!< ATU Interrupt Status Register Mismatch Error bit field offset */
34 #define ATU_ATUIS_ME_MASK               (0x1u << ATU_ATUIS_ME_OFF)
35     /*!< ATU Interrupt Status Register Mismatch Error bit field mask */
36 #define ATU_ATUIE_ME_OFF                0u
37     /*!< ATU Interrupt Enable Register Mismatch Error bit field offset */
38 #define ATU_ATUIE_ME_MASK               (0x1u << ATU_ATUIE_ME_OFF)
39     /*!< ATU Interrupt Enable Register Mismatch Error bit field mask */
40 #define ATU_ATUIC_ME_OFF                0u
41     /*!< ATU Interrupt Clear Register Mismatch Error bit field offset */
42 #define ATU_ATUIC_ME_MASK               (0x1u << ATU_ATUIC_ME_OFF)
43     /*!< ATU Interrupt Clear Register Mismatch Error bit field mask */
44 #define ATU_ATUROBA_AXNSE_OFF           14u
45     /*!< ATU ROBA Register AxNSE bit field offset */
46 #define ATU_ATUROBA_AXNSE_MASK          (0x3u << ATU_ATUROBA_AXNSE_OFF)
47     /*!< ATU ROBA Register AxNSE bit field mask */
48 #define ATU_ATUROBA_AXCACHE3_OFF        12u
49     /*!< ATU ROBA Register AxCACHE3 bit field offset */
50 #define ATU_ATUROBA_AXCACHE3_MASK       (0x3u << ATU_ATUROBA_AXCACHE3_OFF)
51     /*!< ATU ROBA Register AxCACHE3 bit field mask */
52 #define ATU_ATUROBA_AXCACHE2_OFF        10u
53     /*!< ATU ROBA Register AxCACHE2 bit field offset */
54 #define ATU_ATUROBA_AXCACHE2_MASK       (0x3u << ATU_ATUROBA_AXCACHE2_OFF)
55     /*!< ATU ROBA Register AxCACHE2 bit field mask */
56 #define ATU_ATUROBA_AXCACHE1_OFF        8u
57     /*!< ATU ROBA Register AxCACHE1 bit field offset */
58 #define ATU_ATUROBA_AXCACHE1_MASK       (0x3u << ATU_ATUROBA_AXCACHE1_OFF)
59     /*!< ATU ROBA Register AxCACHE1 bit field mask */
60 #define ATU_ATUROBA_AXCACHE0_OFF        6u
61     /*!< ATU ROBA Register AxCACHE0 bit field offset */
62 #define ATU_ATUROBA_AXCACHE0_MASK       (0x3u << ATU_ATUROBA_AXCACHE0_OFF)
63     /*!< ATU ROBA Register AxCACHE0 bit field mask */
64 #define ATU_ATUROBA_AXPROT2_OFF         4u
65     /*!< ATU ROBA Register AxPROT2 bit field offset */
66 #define ATU_ATUROBA_AXPROT2_MASK        (0x3u << ATU_ATUROBA_AXPROT2_OFF)
67     /*!< ATU ROBA Register AxPROT2 bit field mask */
68 #define ATU_ATUROBA_AXPROT1_OFF         2u
69     /*!< ATU ROBA Register AxPROT1 bit field offset */
70 #define ATU_ATUROBA_AXPROT1_MASK        (0x3u << ATU_ATUROBA_AXPROT1_OFF)
71     /*!< ATU ROBA Register AxPROT1 bit field mask */
72 #define ATU_ATUROBA_AXPROT0_OFF         0u
73     /*!< ATU ROBA Register AxPROT0 bit field offset */
74 #define ATU_ATUROBA_AXPROT0_MASK        (0x3u << ATU_ATUROBA_AXPROT0_OFF)
75     /*!< ATU ROBA Register AxPROT0 bit field mask */
76 
77 /**
78  * \brief ATU register map structure
79  */
80 struct _atu_reg_map_t {
81     volatile uint32_t atubc;
82                 /*!< Offset: 0x000 (R/ ) ATU Build Configuration Register */
83     volatile uint32_t atuc;
84                 /*!< Offset: 0x004 (R/W) ATU Configuration Register */
85     volatile uint32_t atuis;
86                 /*!< Offset: 0x008 (R/ ) ATU Interrupt Status Register */
87     volatile uint32_t atuie;
88                 /*!< Offset: 0x00C (R/W) ATU Interrupt Enable Register */
89     volatile uint32_t atuic;
90                 /*!< Offset: 0x010 (R/W) ATU Interrupt Clear Register */
91     volatile uint32_t atuma;
92                 /*!< Offset: 0x014 (R/ ) ATU Mismatched Address Register */
93     volatile uint32_t reserved_0[2];   /*!< Offset: 0x018-0x01C Reserved */
94     volatile uint32_t atursla[32];
95                 /*!< Offset: 0x020 (R/W) ATU Region Start Logical Address n
96                  *                       Register */
97     volatile uint32_t aturela[32];
98                 /*!< Offset: 0x0A0 (R/W) ATU Region End Logical Address n
99                  *                       Register */
100     volatile uint32_t aturav_l[32];
101                 /*!< Offset: 0x120 (R/W) ATU Region Add Value Low n Register */
102     volatile uint32_t aturav_m[32];
103                 /*!< Offset: 0x1A0 (R/W) ATU Region Add Value High n Register */
104     volatile uint32_t aturoba[32];
105                 /*!< Offset: 0x220 (R/W) ATU Region Output Bus Attributes n
106                  *                       Register */
107     volatile uint32_t aturgp[32];
108                 /*!< Offset: 0x2A0 (R/W) ATU Region General Purpose n
109                  *                       Register */
110     volatile uint32_t reserved_1[811]; /*!< Offset: 0x320-0xFCC Reserved */
111     volatile uint32_t pidr4;
112                 /*!< Offset: 0xFD0 (R/ ) Peripheral ID 4 */
113     volatile uint32_t reserved_2[2];   /*!< Offset: 0xFD4-0xFDC Reserved */
114     volatile uint32_t pidr0;
115                 /*!< Offset: 0xFE0 (R/ ) Peripheral ID 0 */
116     volatile uint32_t pidr1;
117                 /*!< Offset: 0xFE4 (R/ ) Peripheral ID 1 */
118     volatile uint32_t pidr2;
119                 /*!< Offset: 0xFE8 (R/ ) Peripheral ID 2 */
120     volatile uint32_t pidr3;
121                 /*!< Offset: 0xFEC (R/ ) Peripheral ID 3 */
122     volatile uint32_t cidr0;
123                 /*!< Offset: 0xFF0 (R/ ) Component ID 0 */
124     volatile uint32_t cidr1;
125                 /*!< Offset: 0xFF4 (R/ ) Component ID 1 */
126     volatile uint32_t cidr2;
127                 /*!< Offset: 0xFF8 (R/ ) Component ID 2 */
128     volatile uint32_t cidr3;
129                 /*!< Offset: 0xFFC (R/ ) Component ID 3 */
130 };
131 
_set_bus_attribute(struct atu_dev_t * dev,enum atu_roba_t val,uint8_t region,uint8_t shift)132 static enum atu_error_t _set_bus_attribute(struct atu_dev_t* dev,
133                     enum atu_roba_t val, uint8_t region, uint8_t shift)
134 {
135     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
136 
137     if(region >= get_supported_region_count(dev))
138         return ATU_ERR_INVALID_REGION;
139 
140     p_atu->aturoba[region] = ((p_atu->aturoba[region] & ~(0x3u << shift)) |
141                               (val << shift));
142 
143     return ATU_ERR_NONE;
144 }
145 
get_page_size(struct atu_dev_t * dev)146 uint16_t get_page_size(struct atu_dev_t* dev)
147 {
148     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
149 
150     return (uint16_t)(0x1u << ATU_GET_ATUPS(p_atu));
151 }
152 
get_supported_region_count(struct atu_dev_t * dev)153 uint8_t get_supported_region_count(struct atu_dev_t* dev)
154 {
155     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
156 
157     return (uint8_t)(0x1u << (p_atu->atubc & ATU_ATUBC_RC_MASK));
158 }
159 
enable_atu_region(struct atu_dev_t * dev,uint8_t region)160 enum atu_error_t enable_atu_region(struct atu_dev_t* dev, uint8_t region)
161 {
162     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
163 
164     if(region >= get_supported_region_count(dev))
165         return ATU_ERR_INVALID_REGION;
166 
167     p_atu->atuc |= (1u << region);
168 
169     return ATU_ERR_NONE;
170 }
171 
disable_atu_region(struct atu_dev_t * dev,uint8_t region)172 enum atu_error_t disable_atu_region(struct atu_dev_t* dev, uint8_t region)
173 {
174     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
175 
176     if(region >= get_supported_region_count(dev))
177         return ATU_ERR_INVALID_REGION;
178 
179     p_atu->atuc &= ~(1u << region);
180 
181     return ATU_ERR_NONE;
182 }
183 
me_interrupt_is_waiting(struct atu_dev_t * dev)184 bool me_interrupt_is_waiting(struct atu_dev_t* dev)
185 {
186     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
187 
188     return (bool)(p_atu->atuis & ATU_ATUIS_ME_MASK);
189 }
190 
enable_me_interrupt(struct atu_dev_t * dev)191 void enable_me_interrupt(struct atu_dev_t* dev)
192 {
193     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
194 
195     p_atu->atuie |= ATU_ATUIE_ME_MASK;
196 }
197 
clear_me_interrupt(struct atu_dev_t * dev)198 void clear_me_interrupt(struct atu_dev_t* dev)
199 {
200     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
201 
202     p_atu->atuic |= ATU_ATUIC_ME_MASK;
203 }
204 
get_mismatch_address(struct atu_dev_t * dev)205 uint32_t get_mismatch_address(struct atu_dev_t* dev)
206 {
207     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
208 
209     return p_atu->atuma;
210 }
211 
set_start_logical_address(struct atu_dev_t * dev,uint32_t address,uint8_t region)212 enum atu_error_t set_start_logical_address(struct atu_dev_t* dev,
213                     uint32_t address, uint8_t region)
214 {
215     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
216 
217     uint8_t ps = ATU_GET_ATUPS(p_atu);
218 
219     if(region >= get_supported_region_count(dev))
220         return ATU_ERR_INVALID_REGION;
221 
222     /* The value stored in this field is the start logical address
223      * right shifted by the value of the PS */
224     p_atu->atursla[region] = (address >> ps);
225 
226     return ATU_ERR_NONE;
227 }
228 
set_end_logical_address(struct atu_dev_t * dev,uint32_t address,uint8_t region)229 enum atu_error_t set_end_logical_address(struct atu_dev_t* dev,
230                     uint32_t address, uint8_t region)
231 {
232     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
233 
234     uint8_t ps = ATU_GET_ATUPS(p_atu);
235 
236     if(region >= get_supported_region_count(dev))
237         return ATU_ERR_INVALID_REGION;
238 
239     /* The end page should be greater than or equal to the start page */
240     if((address >> ps) < p_atu->atursla[region])
241         return ATU_ERR_INVALID_ADDRESS;
242 
243     /* The value stored in this field is the start logical address
244      * right shifted by the value of the PS */
245     p_atu->aturela[region] = (address >> ps);
246 
247     return ATU_ERR_NONE;
248 }
249 
set_add_value(struct atu_dev_t * dev,uint64_t offset_address,uint8_t region)250 enum atu_error_t set_add_value(struct atu_dev_t* dev,
251                     uint64_t offset_address, uint8_t region)
252 {
253     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
254 
255     if(region >= get_supported_region_count(dev))
256         return ATU_ERR_INVALID_REGION;
257 
258     p_atu->aturav_l[region] = (uint32_t)(offset_address);
259 
260     p_atu->aturav_m[region] = (uint32_t)(offset_address >> 32);
261 
262     return ATU_ERR_NONE;
263 }
264 
set_axnsc(struct atu_dev_t * dev,enum atu_roba_t val,uint8_t region)265 enum atu_error_t set_axnsc(struct atu_dev_t* dev,
266                     enum atu_roba_t val, uint8_t region)
267 {
268     return _set_bus_attribute(dev, val, region, ATU_ATUROBA_AXNSE_OFF);
269 }
270 
set_axcache3(struct atu_dev_t * dev,enum atu_roba_t val,uint8_t region)271 enum atu_error_t set_axcache3(struct atu_dev_t* dev,
272                     enum atu_roba_t val, uint8_t region)
273 {
274     return _set_bus_attribute(dev, val, region, ATU_ATUROBA_AXCACHE3_OFF);
275 }
276 
set_axcache2(struct atu_dev_t * dev,enum atu_roba_t val,uint8_t region)277 enum atu_error_t set_axcache2(struct atu_dev_t* dev,
278                     enum atu_roba_t val, uint8_t region)
279 {
280     return _set_bus_attribute(dev, val, region, ATU_ATUROBA_AXCACHE2_OFF);
281 }
282 
set_axcache1(struct atu_dev_t * dev,enum atu_roba_t val,uint8_t region)283 enum atu_error_t set_axcache1(struct atu_dev_t* dev,
284                     enum atu_roba_t val, uint8_t region)
285 {
286     return _set_bus_attribute(dev, val, region, ATU_ATUROBA_AXCACHE1_OFF);
287 }
288 
set_axcache0(struct atu_dev_t * dev,enum atu_roba_t val,uint8_t region)289 enum atu_error_t set_axcache0(struct atu_dev_t* dev,
290                     enum atu_roba_t val, uint8_t region)
291 {
292     return _set_bus_attribute(dev, val, region, ATU_ATUROBA_AXCACHE0_OFF);
293 }
294 
set_axprot2(struct atu_dev_t * dev,enum atu_roba_t val,uint8_t region)295 enum atu_error_t set_axprot2(struct atu_dev_t* dev,
296                     enum atu_roba_t val, uint8_t region)
297 {
298     return _set_bus_attribute(dev, val, region, ATU_ATUROBA_AXPROT2_OFF);
299 }
300 
set_axprot1(struct atu_dev_t * dev,enum atu_roba_t val,uint8_t region)301 enum atu_error_t set_axprot1(struct atu_dev_t* dev,
302                     enum atu_roba_t val, uint8_t region)
303 {
304     return _set_bus_attribute(dev, val, region, ATU_ATUROBA_AXPROT1_OFF);
305 }
306 
set_axprot0(struct atu_dev_t * dev,enum atu_roba_t val,uint8_t region)307 enum atu_error_t set_axprot0(struct atu_dev_t* dev,
308                     enum atu_roba_t val, uint8_t region)
309 {
310     return _set_bus_attribute(dev, val, region, ATU_ATUROBA_AXPROT0_OFF);
311 }
312 
set_gp_value(struct atu_dev_t * dev,uint8_t val,uint8_t region)313 enum atu_error_t set_gp_value(struct atu_dev_t* dev,
314                     uint8_t val, uint8_t region)
315 {
316     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
317 
318     if(region >= get_supported_region_count(dev))
319         return ATU_ERR_INVALID_REGION;
320 
321     p_atu->aturgp[region] = (uint32_t)val;
322 
323     return ATU_ERR_NONE;
324 }
325 
get_gp_value(struct atu_dev_t * dev,uint8_t region)326 uint8_t get_gp_value(struct atu_dev_t* dev, uint8_t region)
327 {
328     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
329 
330     return (uint8_t)(p_atu->aturgp[region] & 0xFF);
331 }
332 
atu_initialize_region(struct atu_dev_t * dev,uint8_t region,uint32_t log_addr,uint64_t phys_addr,uint32_t size)333 enum atu_error_t atu_initialize_region(struct atu_dev_t *dev, uint8_t region,
334                                        uint32_t log_addr, uint64_t phys_addr,
335                                        uint32_t size)
336 {
337     enum atu_error_t err;
338     struct _atu_reg_map_t* p_atu = (struct _atu_reg_map_t*)dev->cfg->base;
339 
340     uint32_t end_log_addr = log_addr + size - 1;
341     uint8_t ps = ATU_GET_ATUPS(p_atu);
342     uint64_t add_value = (phys_addr - log_addr) >> ps;
343 
344     if (dev == NULL) {
345         /* Invalid parameters */
346         return ATU_ERR_INVALID_ARG;
347     }
348 
349     err = set_start_logical_address(dev, log_addr, region);
350     if (err != ATU_ERR_NONE) {
351         return err;
352     }
353 
354     err = set_end_logical_address(dev, end_log_addr, region);
355     if (err != ATU_ERR_NONE) {
356         return err;
357     }
358 
359     err = set_add_value(dev, add_value, region);
360     if (err != ATU_ERR_NONE) {
361         return err;
362     }
363 
364     err = enable_atu_region(dev, region);
365     if (err != ATU_ERR_NONE) {
366         return err;
367     }
368 
369     return ATU_ERR_NONE;
370 }
371 
atu_uninitialize_region(struct atu_dev_t * dev,uint8_t region)372 enum atu_error_t atu_uninitialize_region(struct atu_dev_t *dev, uint8_t region)
373 {
374     enum atu_error_t err;
375 
376     if (dev == NULL) {
377         /* Invalid parameters */
378         return ATU_ERR_INVALID_ARG;
379     }
380 
381     err = disable_atu_region(dev, region);
382     if (err != ATU_ERR_NONE) {
383         return err;
384     }
385 
386     return ATU_ERR_NONE;
387 }
388