blob: 57edacd620054ba04bfca903306e89813305afe2 [file] [log] [blame]
Kristofer Jonsson537c71c2020-05-05 14:17:22 +02001/*
2 * Copyright (c) 2019-2020 Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19/*****************************************************************************
20 * Includes
21 *****************************************************************************/
22
23#include "ethosu55_interface.h"
24#include "ethosu_common.h"
Bhavik Pateldae5be02020-06-18 15:25:15 +020025#include "ethosu_driver.h"
26#include "pmu_ethosu.h"
27
Kristofer Jonsson537c71c2020-05-05 14:17:22 +020028#include <assert.h>
Per Åstrande07b1f92020-09-28 08:31:46 +020029#include <inttypes.h>
Bhavik Pateldae5be02020-06-18 15:25:15 +020030#include <stddef.h>
Kristofer Jonsson537c71c2020-05-05 14:17:22 +020031
32/*****************************************************************************
33 * Defines
34 *****************************************************************************/
35
36#define COMMA ,
37#define SEMICOLON ;
38
Kristofer Jonsson537c71c2020-05-05 14:17:22 +020039#define EVTYPE(A, name) \
40 case PMU_EVENT_TYPE_##name: \
41 return ETHOSU_PMU_##name
42
43#define EVID(A, name) (PMU_EVENT_TYPE_##name)
44
Bhavik Patel8e32b0b2020-06-23 13:48:25 +020045#define NPU_REG_PMEVCNTR(x) (NPU_REG_PMEVCNTR0 + ((x) * sizeof(uint32_t)))
46#define NPU_REG_PMEVTYPER(x) (NPU_REG_PMEVTYPER0 + ((x) * sizeof(uint32_t)))
47
Kristofer Jonsson537c71c2020-05-05 14:17:22 +020048/*****************************************************************************
49 * Variables
50 *****************************************************************************/
51
Kristofer Jonsson537c71c2020-05-05 14:17:22 +020052static const enum pmu_event_type eventbyid[] = {EXPAND_PMU_EVENT_TYPE(EVID, COMMA)};
53
54/*****************************************************************************
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +020055 * Static functions
Kristofer Jonsson537c71c2020-05-05 14:17:22 +020056 *****************************************************************************/
57
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +020058static enum ethosu_pmu_event_type pmu_event_type(uint32_t id)
Kristofer Jonsson537c71c2020-05-05 14:17:22 +020059{
60 switch (id)
61 {
62 EXPAND_PMU_EVENT_TYPE(EVTYPE, SEMICOLON);
Per Åstrande07b1f92020-09-28 08:31:46 +020063 default:
64 LOG_ERR("Unknown PMU event id: 0x%" PRIx32 "\n", id);
Kristofer Jonsson537c71c2020-05-05 14:17:22 +020065 }
66
67 return ETHOSU_PMU_SENTINEL;
68}
69
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +020070static uint32_t pmu_event_value(enum ethosu_pmu_event_type event)
Kristofer Jonsson537c71c2020-05-05 14:17:22 +020071{
Per Åstrand51c18ba2020-09-28 11:25:36 +020072 int a = event;
73 if ((a < ETHOSU_PMU_SENTINEL) && (a >= ETHOSU_PMU_NO_EVENT))
74 {
75 return eventbyid[event];
76 }
77 else
Kristofer Jonsson537c71c2020-05-05 14:17:22 +020078 {
79 return (uint32_t)(-1);
80 }
Kristofer Jonsson537c71c2020-05-05 14:17:22 +020081}
82
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +020083/*****************************************************************************
84 * Functions
85 *****************************************************************************/
Bhavik Patel8e32b0b2020-06-23 13:48:25 +020086
87void ETHOSU_PMU_Enable(void)
88{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +020089 LOG_DEBUG("%s:\n", __FUNCTION__);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +020090 struct pmcr_r pmcr;
Kristofer Jonssonef387ea2020-08-25 16:32:21 +020091 pmcr.word = ethosu_drv.dev.pmcr;
Bhavik Patel8e32b0b2020-06-23 13:48:25 +020092 pmcr.cnt_en = 1;
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +020093 ethosu_write_reg_shadow(&ethosu_drv.dev, NPU_REG_PMCR, pmcr.word, &ethosu_drv.dev.pmcr);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +020094}
95
96void ETHOSU_PMU_Disable(void)
97{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +020098 LOG_DEBUG("%s:\n", __FUNCTION__);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +020099 struct pmcr_r pmcr;
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200100 pmcr.word = ethosu_drv.dev.pmcr;
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200101 pmcr.cnt_en = 0;
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200102 ethosu_write_reg_shadow(&ethosu_drv.dev, NPU_REG_PMCR, pmcr.word, &ethosu_drv.dev.pmcr);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200103}
104
105void ETHOSU_PMU_Set_EVTYPER(uint32_t num, enum ethosu_pmu_event_type type)
106{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200107 ASSERT(num < ETHOSU_PMU_NCOUNTERS);
108 uint32_t val = pmu_event_value(type);
109 LOG_DEBUG("%s: num=%u, type=%d, val=%u\n", __FUNCTION__, num, type, val);
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200110 ethosu_write_reg_shadow(&ethosu_drv.dev, NPU_REG_PMEVTYPER(num), val, &ethosu_drv.dev.pmu_evtypr[num]);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200111}
112
113enum ethosu_pmu_event_type ETHOSU_PMU_Get_EVTYPER(uint32_t num)
114{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200115 ASSERT(num < ETHOSU_PMU_NCOUNTERS);
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200116 uint32_t val = ethosu_drv.dev.pmu_evtypr[num];
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200117 enum ethosu_pmu_event_type type = pmu_event_type(val);
118 LOG_DEBUG("%s: num=%u, type=%d, val=%u\n", __FUNCTION__, num, type, val);
119 return type;
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200120}
121
122void ETHOSU_PMU_CYCCNT_Reset(void)
123{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200124 LOG_DEBUG("%s:\n", __FUNCTION__);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200125 struct pmcr_r pmcr;
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200126 pmcr.word = ethosu_drv.dev.pmcr;
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200127 pmcr.cycle_cnt_rst = 1;
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200128 ethosu_write_reg_shadow(&ethosu_drv.dev, NPU_REG_PMCR, pmcr.word, &ethosu_drv.dev.pmcr);
129 ethosu_drv.dev.pmccntr[0] = 0;
130 ethosu_drv.dev.pmccntr[1] = 0;
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200131}
132
133void ETHOSU_PMU_EVCNTR_ALL_Reset(void)
134{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200135 LOG_DEBUG("%s:\n", __FUNCTION__);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200136 struct pmcr_r pmcr;
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200137 pmcr.word = ethosu_drv.dev.pmcr;
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200138 pmcr.event_cnt_rst = 1;
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200139 ethosu_write_reg_shadow(&ethosu_drv.dev, NPU_REG_PMCR, pmcr.word, &ethosu_drv.dev.pmcr);
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200140
141 for (uint32_t i = 0; i < ETHOSU_PMU_NCOUNTERS; i++)
142 {
143 ethosu_drv.dev.pmu_evcntr[i] = 0;
144 }
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200145}
146
147void ETHOSU_PMU_CNTR_Enable(uint32_t mask)
148{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200149 LOG_DEBUG("%s: mask=0x%08x\n", __FUNCTION__, mask);
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200150 ethosu_write_reg_shadow(&ethosu_drv.dev, NPU_REG_PMCNTENSET, mask, &ethosu_drv.dev.pmcnten);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200151}
152
153void ETHOSU_PMU_CNTR_Disable(uint32_t mask)
154{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200155 LOG_DEBUG("%s: mask=0x%08x\n", __FUNCTION__, mask);
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200156 ethosu_write_reg_shadow(&ethosu_drv.dev, NPU_REG_PMCNTENCLR, mask, &ethosu_drv.dev.pmcnten);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200157}
158
Bhavik Pateldae5be02020-06-18 15:25:15 +0200159uint32_t ETHOSU_PMU_CNTR_Status(void)
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200160{
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200161 LOG_DEBUG("%s: mask=0x%08x\n", __FUNCTION__, ethosu_drv.dev.pmcnten);
162 return ethosu_drv.dev.pmcnten;
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200163}
164
165uint64_t ETHOSU_PMU_Get_CCNTR(void)
166{
Kristofer Jonssonbad5a492020-10-23 10:45:30 +0200167 uint32_t val_lo = ethosu_read_reg(&ethosu_drv.dev, NPU_REG_PMCCNTR_LO);
168 uint32_t val_hi = ethosu_read_reg(&ethosu_drv.dev, NPU_REG_PMCCNTR_HI);
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200169 uint64_t val = ((uint64_t)val_hi << 32) | val_lo;
170 uint64_t shadow = ((uint64_t)ethosu_drv.dev.pmccntr[1] << 32) | ethosu_drv.dev.pmccntr[0];
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200171
Kristofer Jonssonbad5a492020-10-23 10:45:30 +0200172 LOG_DEBUG("%s: val=%" PRIu64 ", shadow=%" PRIu64 "\n", __FUNCTION__, val, shadow);
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200173
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200174 // Return the shadow variable in case the NPU was powered off and lost the cycle count
175 if (shadow > val)
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200176 {
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200177 return shadow;
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200178 }
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200179
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200180 // Update the shadow variable
181 ethosu_drv.dev.pmccntr[0] = val_lo;
182 ethosu_drv.dev.pmccntr[1] = val_hi;
183
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200184 return val;
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200185}
186
187void ETHOSU_PMU_Set_CCNTR(uint64_t val)
188{
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200189 uint32_t active = ETHOSU_PMU_CNTR_Status() & ETHOSU_PMU_CCNT_Msk;
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200190
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200191 LOG_DEBUG("%s: val=%llu\n", __FUNCTION__, val);
192
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200193 if (active)
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200194 {
195 ETHOSU_PMU_CNTR_Disable(ETHOSU_PMU_CCNT_Msk);
196 }
197
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200198 ethosu_write_reg_shadow(&ethosu_drv.dev, NPU_REG_PMCCNTR_LO, val & MASK_0_31_BITS, &ethosu_drv.dev.pmccntr[0]);
199 ethosu_write_reg_shadow(
200 &ethosu_drv.dev, NPU_REG_PMCCNTR_HI, (val & MASK_32_47_BITS) >> 32, &ethosu_drv.dev.pmccntr[1]);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200201
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200202 if (active)
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200203 {
204 ETHOSU_PMU_CNTR_Enable(ETHOSU_PMU_CCNT_Msk);
205 }
206}
207
208uint32_t ETHOSU_PMU_Get_EVCNTR(uint32_t num)
209{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200210 ASSERT(num < ETHOSU_PMU_NCOUNTERS);
211 uint32_t val = ethosu_read_reg(&ethosu_drv.dev, NPU_REG_PMEVCNTR(num));
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200212 LOG_DEBUG("%s: num=%u, val=%u, shadow=%u\n", __FUNCTION__, num, val, ethosu_drv.dev.pmu_evcntr[num]);
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200213
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200214 // Return the shadow variable in case the NPU was powered off and lost the event count
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200215 if (ethosu_drv.dev.pmu_evcntr[num] > val)
216 {
217 return ethosu_drv.dev.pmu_evcntr[num];
218 }
219
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200220 // Update the shadow variable
221 ethosu_drv.dev.pmu_evcntr[num] = val;
222
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200223 return val;
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200224}
225
226void ETHOSU_PMU_Set_EVCNTR(uint32_t num, uint32_t val)
227{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200228 ASSERT(num < ETHOSU_PMU_NCOUNTERS);
229 LOG_DEBUG("%s: num=%u, val=%u\n", __FUNCTION__, num, val);
Bhavik Pateldae5be02020-06-18 15:25:15 +0200230 ethosu_write_reg(&ethosu_drv.dev, NPU_REG_PMEVCNTR(num), val);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200231}
232
233uint32_t ETHOSU_PMU_Get_CNTR_OVS(void)
234{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200235 LOG_DEBUG("%s:\n", __FUNCTION__);
Bhavik Pateldae5be02020-06-18 15:25:15 +0200236 return ethosu_read_reg(&ethosu_drv.dev, NPU_REG_PMOVSSET);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200237}
238
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200239void ETHOSU_PMU_Set_CNTR_OVS(uint32_t mask)
240{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200241 LOG_DEBUG("%s:\n", __FUNCTION__);
Bhavik Pateldae5be02020-06-18 15:25:15 +0200242 ethosu_write_reg(&ethosu_drv.dev, NPU_REG_PMOVSCLR, mask);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200243}
244
245void ETHOSU_PMU_Set_CNTR_IRQ_Enable(uint32_t mask)
246{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200247 LOG_DEBUG("%s: mask=0x%08x\n", __FUNCTION__, mask);
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200248 ethosu_write_reg_shadow(&ethosu_drv.dev, NPU_REG_PMINTSET, mask, &ethosu_drv.dev.pmint);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200249}
250
251void ETHOSU_PMU_Set_CNTR_IRQ_Disable(uint32_t mask)
252{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200253 LOG_DEBUG("%s: mask=0x%08x\n", __FUNCTION__, mask);
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200254 ethosu_write_reg_shadow(&ethosu_drv.dev, NPU_REG_PMINTCLR, mask, &ethosu_drv.dev.pmint);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200255}
256
Bhavik Pateldae5be02020-06-18 15:25:15 +0200257uint32_t ETHOSU_PMU_Get_IRQ_Enable(void)
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200258{
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200259 LOG_DEBUG("%s: mask=0x%08x\n", __FUNCTION__, ethosu_drv.dev.pmint);
260 return ethosu_drv.dev.pmint;
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200261}
262
263void ETHOSU_PMU_CNTR_Increment(uint32_t mask)
264{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200265 LOG_DEBUG("%s:\n", __FUNCTION__);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200266 uint32_t cntrs_active = ETHOSU_PMU_CNTR_Status();
267
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200268 // Disable counters
269 ETHOSU_PMU_CNTR_Disable(mask);
270
271 // Increment cycle counter
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200272 if (mask & ETHOSU_PMU_CCNT_Msk)
273 {
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200274 uint64_t val = ETHOSU_PMU_Get_CCNTR() + 1;
275 ethosu_write_reg_shadow(&ethosu_drv.dev, NPU_REG_PMCCNTR_LO, val & MASK_0_31_BITS, &ethosu_drv.dev.pmccntr[0]);
276 ethosu_write_reg_shadow(
277 &ethosu_drv.dev, NPU_REG_PMCCNTR_HI, (val & MASK_32_47_BITS) >> 32, &ethosu_drv.dev.pmccntr[1]);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200278 }
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200279
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200280 for (int i = 0; i < ETHOSU_PMU_NCOUNTERS; i++)
281 {
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200282 if (mask & (1 << i))
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200283 {
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200284 uint32_t val = ETHOSU_PMU_Get_EVCNTR(i);
285 ethosu_write_reg_shadow(&ethosu_drv.dev, NPU_REG_PMEVCNTR(i), val + 1, &ethosu_drv.dev.pmu_evcntr[i]);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200286 }
287 }
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200288
289 // Reenable the active counters
290 ETHOSU_PMU_CNTR_Enable(cntrs_active);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200291}
292
293void ETHOSU_PMU_PMCCNTR_CFG_Set_Start_Event(uint32_t start_event)
294{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200295 LOG_DEBUG("%s: start_event=%u\n", __FUNCTION__, start_event);
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200296 struct pmccntr_cfg_r cfg;
297 cfg.word = ethosu_drv.dev.pmccntr_cfg;
298 cfg.CYCLE_CNT_CFG_START = start_event;
299 ethosu_write_reg_shadow(&ethosu_drv.dev, NPU_REG_PMCCNTR_CFG, cfg.word, &ethosu_drv.dev.pmccntr_cfg);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200300}
301
302void ETHOSU_PMU_PMCCNTR_CFG_Set_Stop_Event(uint32_t stop_event)
303{
Kristofer Jonssonef387ea2020-08-25 16:32:21 +0200304 LOG_DEBUG("%s: stop_event=%u\n", __FUNCTION__, stop_event);
Kristofer Jonsson4dc73dc2020-10-16 12:33:47 +0200305 struct pmccntr_cfg_r cfg;
306 cfg.word = ethosu_drv.dev.pmccntr_cfg;
307 cfg.CYCLE_CNT_CFG_STOP = stop_event;
308 ethosu_write_reg_shadow(&ethosu_drv.dev, NPU_REG_PMCCNTR_CFG, cfg.word, &ethosu_drv.dev.pmccntr_cfg);
Bhavik Patel8e32b0b2020-06-23 13:48:25 +0200309}