11459a227SAleksandr Rybalko /*- 25ec1d020SAndrew Turner * SPDX-License-Identifier: BSD-2-Clause 31459a227SAleksandr Rybalko * 41459a227SAleksandr Rybalko * Copyright (c) 2003-2008 Joseph Koshy 51459a227SAleksandr Rybalko * Copyright (c) 2007 The FreeBSD Foundation 61459a227SAleksandr Rybalko * Copyright (c) 2021 Ampere Computing LLC 71459a227SAleksandr Rybalko * 81459a227SAleksandr Rybalko * Portions of this software were developed by A. Joseph Koshy under 91459a227SAleksandr Rybalko * sponsorship from the FreeBSD Foundation and Google, Inc. 101459a227SAleksandr Rybalko * 111459a227SAleksandr Rybalko * Redistribution and use in source and binary forms, with or without 121459a227SAleksandr Rybalko * modification, are permitted provided that the following conditions 131459a227SAleksandr Rybalko * are met: 141459a227SAleksandr Rybalko * 1. Redistributions of source code must retain the above copyright 151459a227SAleksandr Rybalko * notice, this list of conditions and the following disclaimer. 161459a227SAleksandr Rybalko * 2. Redistributions in binary form must reproduce the above copyright 171459a227SAleksandr Rybalko * notice, this list of conditions and the following disclaimer in the 181459a227SAleksandr Rybalko * documentation and/or other materials provided with the distribution. 191459a227SAleksandr Rybalko * 201459a227SAleksandr Rybalko * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 211459a227SAleksandr Rybalko * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221459a227SAleksandr Rybalko * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231459a227SAleksandr Rybalko * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 241459a227SAleksandr Rybalko * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251459a227SAleksandr Rybalko * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261459a227SAleksandr Rybalko * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271459a227SAleksandr Rybalko * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281459a227SAleksandr Rybalko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291459a227SAleksandr Rybalko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301459a227SAleksandr Rybalko * SUCH DAMAGE. 311459a227SAleksandr Rybalko */ 321459a227SAleksandr Rybalko 331459a227SAleksandr Rybalko /* Support for ARM DMC-620 Memory Controller PMU */ 341459a227SAleksandr Rybalko 351459a227SAleksandr Rybalko #include <sys/cdefs.h> 361459a227SAleksandr Rybalko __FBSDID("$FreeBSD$"); 371459a227SAleksandr Rybalko 381459a227SAleksandr Rybalko #include <sys/param.h> 391459a227SAleksandr Rybalko #include <sys/lock.h> 401459a227SAleksandr Rybalko #include <sys/malloc.h> 411459a227SAleksandr Rybalko #include <sys/mutex.h> 421459a227SAleksandr Rybalko #include <sys/pmc.h> 431459a227SAleksandr Rybalko #include <sys/pmckern.h> 441459a227SAleksandr Rybalko #include <sys/systm.h> 451459a227SAleksandr Rybalko 461459a227SAleksandr Rybalko #include <dev/hwpmc/pmu_dmc620_reg.h> 471459a227SAleksandr Rybalko 481459a227SAleksandr Rybalko #define DMC620_TYPE_CLKDIV2 0 491459a227SAleksandr Rybalko #define DMC620_TYPE_CLK 1 501459a227SAleksandr Rybalko #define CLASS2TYPE(c) ((c) - PMC_CLASS_DMC620_PMU_CD2) 511459a227SAleksandr Rybalko 521459a227SAleksandr Rybalko /* Create wrapper for each class. */ 531459a227SAleksandr Rybalko #define CLASSDEP_FN2(fn, t1, a1, t2, a2) \ 541459a227SAleksandr Rybalko static int fn(int class, t1 a1, t2 a2); \ 551459a227SAleksandr Rybalko static int fn ## _cd2(t1 a1, t2 a2) \ 561459a227SAleksandr Rybalko { \ 571459a227SAleksandr Rybalko return (fn(PMC_CLASS_DMC620_PMU_CD2, a1, a2)); \ 581459a227SAleksandr Rybalko } \ 591459a227SAleksandr Rybalko static int fn ## _c(t1 a1, t2 a2) \ 601459a227SAleksandr Rybalko { \ 611459a227SAleksandr Rybalko return (fn(PMC_CLASS_DMC620_PMU_C, a1, a2)); \ 621459a227SAleksandr Rybalko } \ 631459a227SAleksandr Rybalko static int fn(int class, t1 a1, t2 a2) 641459a227SAleksandr Rybalko 651459a227SAleksandr Rybalko #define CLASSDEP_FN3(fn, t1, a1, t2, a2, t3, a3) \ 661459a227SAleksandr Rybalko static int fn(int class, t1 a1, t2 a2, t3 a3); \ 671459a227SAleksandr Rybalko static int fn ## _cd2(t1 a1, t2 a2, t3 a3) \ 681459a227SAleksandr Rybalko { \ 691459a227SAleksandr Rybalko return (fn(PMC_CLASS_DMC620_PMU_CD2, a1, a2, a3)); \ 701459a227SAleksandr Rybalko } \ 711459a227SAleksandr Rybalko static int fn ## _c(t1 a1, t2 a2, t3 a3) \ 721459a227SAleksandr Rybalko { \ 731459a227SAleksandr Rybalko return (fn(PMC_CLASS_DMC620_PMU_C, a1, a2, a3)); \ 741459a227SAleksandr Rybalko } \ 751459a227SAleksandr Rybalko static int fn(int class, t1 a1, t2 a2, t3 a3) 761459a227SAleksandr Rybalko 771459a227SAleksandr Rybalko #define CLASSDEP_FN4(fn, t1, a1, t2, a2, t3, a3, t4, a4) \ 781459a227SAleksandr Rybalko static int fn(int class, t1 a1, t2 a2, t3 a3, t4 a4); \ 791459a227SAleksandr Rybalko static int fn ## _cd2(t1 a1, t2 a2, t3 a3, t4 a4) \ 801459a227SAleksandr Rybalko { \ 811459a227SAleksandr Rybalko return (fn(PMC_CLASS_DMC620_PMU_CD2, a1, a2, a3, a4)); \ 821459a227SAleksandr Rybalko } \ 831459a227SAleksandr Rybalko static int fn ## _c(t1 a1, t2 a2, t3 a3, t4 a4) \ 841459a227SAleksandr Rybalko { \ 851459a227SAleksandr Rybalko return (fn(PMC_CLASS_DMC620_PMU_C, a1, a2, a3, a4)); \ 861459a227SAleksandr Rybalko } \ 871459a227SAleksandr Rybalko static int fn(int class, t1 a1, t2 a2, t3 a3, t4 a4) 881459a227SAleksandr Rybalko 891459a227SAleksandr Rybalko struct dmc620_pmc { 901459a227SAleksandr Rybalko void *arg; 911459a227SAleksandr Rybalko int domain; 921459a227SAleksandr Rybalko }; 931459a227SAleksandr Rybalko 941459a227SAleksandr Rybalko struct dmc620_descr { 951459a227SAleksandr Rybalko struct pmc_descr pd_descr; /* "base class" */ 961459a227SAleksandr Rybalko void *pd_rw_arg; /* Argument to use with read/write */ 971459a227SAleksandr Rybalko struct pmc *pd_pmc; 981459a227SAleksandr Rybalko struct pmc_hw *pd_phw; 991459a227SAleksandr Rybalko uint32_t pd_config; 1001459a227SAleksandr Rybalko uint32_t pd_match; 1011459a227SAleksandr Rybalko uint32_t pd_mask; 1021459a227SAleksandr Rybalko uint32_t pd_evsel; /* address of EVSEL register */ 1031459a227SAleksandr Rybalko uint32_t pd_perfctr; /* address of PERFCTR register */ 1041459a227SAleksandr Rybalko 1051459a227SAleksandr Rybalko }; 1061459a227SAleksandr Rybalko 1071459a227SAleksandr Rybalko static struct dmc620_descr **dmc620_pmcdesc[2]; 1081459a227SAleksandr Rybalko static struct dmc620_pmc dmc620_pmcs[DMC620_UNIT_MAX]; 1091459a227SAleksandr Rybalko static int dmc620_npmcs = 0; 1101459a227SAleksandr Rybalko 1111459a227SAleksandr Rybalko void 1121459a227SAleksandr Rybalko dmc620_pmc_register(int unit, void *arg, int domain) 1131459a227SAleksandr Rybalko { 1141459a227SAleksandr Rybalko 1151459a227SAleksandr Rybalko if (unit >= DMC620_UNIT_MAX) { 1161459a227SAleksandr Rybalko /* TODO */ 1171459a227SAleksandr Rybalko return; 1181459a227SAleksandr Rybalko } 1191459a227SAleksandr Rybalko 1201459a227SAleksandr Rybalko dmc620_pmcs[unit].arg = arg; 1211459a227SAleksandr Rybalko dmc620_pmcs[unit].domain = domain; 1221459a227SAleksandr Rybalko dmc620_npmcs++; 1231459a227SAleksandr Rybalko } 1241459a227SAleksandr Rybalko 1251459a227SAleksandr Rybalko void 1261459a227SAleksandr Rybalko dmc620_pmc_unregister(int unit) 1271459a227SAleksandr Rybalko { 1281459a227SAleksandr Rybalko 1291459a227SAleksandr Rybalko dmc620_pmcs[unit].arg = NULL; 1301459a227SAleksandr Rybalko dmc620_npmcs--; 1311459a227SAleksandr Rybalko } 1321459a227SAleksandr Rybalko 1331459a227SAleksandr Rybalko int 13405cef747SAndrew Turner pmc_dmc620_nclasses(void) 1351459a227SAleksandr Rybalko { 1361459a227SAleksandr Rybalko 1371459a227SAleksandr Rybalko if (dmc620_npmcs > 0) 1381459a227SAleksandr Rybalko return (2); 1391459a227SAleksandr Rybalko return (0); 1401459a227SAleksandr Rybalko } 1411459a227SAleksandr Rybalko 1421459a227SAleksandr Rybalko static inline struct dmc620_descr * 1431459a227SAleksandr Rybalko dmc620desc(int class, int cpu, int ri) 1441459a227SAleksandr Rybalko { 1451459a227SAleksandr Rybalko int c; 1461459a227SAleksandr Rybalko 1471459a227SAleksandr Rybalko c = CLASS2TYPE(class); 1481459a227SAleksandr Rybalko KASSERT((c & 0xfffffffe) == 0, ("[dmc620,%d] 'c' can only be 0 or 1. " 1491459a227SAleksandr Rybalko "now %d", __LINE__, c)); 1501459a227SAleksandr Rybalko 1511459a227SAleksandr Rybalko return (dmc620_pmcdesc[c][ri]); 1521459a227SAleksandr Rybalko } 1531459a227SAleksandr Rybalko 1541459a227SAleksandr Rybalko static inline int 1551459a227SAleksandr Rybalko cntr(int class, int ri) 1561459a227SAleksandr Rybalko { 1571459a227SAleksandr Rybalko int c; 1581459a227SAleksandr Rybalko 1591459a227SAleksandr Rybalko c = CLASS2TYPE(class); 1601459a227SAleksandr Rybalko KASSERT((c & 0xfffffffe) == 0, ("[dmc620,%d] 'c' can only be 0 or 1. " 1611459a227SAleksandr Rybalko "now %d", __LINE__, c)); 1621459a227SAleksandr Rybalko 1631459a227SAleksandr Rybalko if (c == DMC620_TYPE_CLKDIV2) 1641459a227SAleksandr Rybalko return (ri % DMC620_CLKDIV2_COUNTERS_N); 1651459a227SAleksandr Rybalko return ((ri % DMC620_CLK_COUNTERS_N) + DMC620_CLKDIV2_COUNTERS_N); 1661459a227SAleksandr Rybalko } 1671459a227SAleksandr Rybalko 1681459a227SAleksandr Rybalko static inline int 1691459a227SAleksandr Rybalko class2mdep(int class) 1701459a227SAleksandr Rybalko { 1711459a227SAleksandr Rybalko 1721459a227SAleksandr Rybalko switch (class) { 1731459a227SAleksandr Rybalko case PMC_CLASS_DMC620_PMU_CD2: 1741459a227SAleksandr Rybalko return (PMC_MDEP_CLASS_INDEX_DMC620_CD2); 1751459a227SAleksandr Rybalko case PMC_CLASS_DMC620_PMU_C: 1761459a227SAleksandr Rybalko return (PMC_MDEP_CLASS_INDEX_DMC620_C); 1771459a227SAleksandr Rybalko } 1781459a227SAleksandr Rybalko return (-1); 1791459a227SAleksandr Rybalko } 1801459a227SAleksandr Rybalko 1811459a227SAleksandr Rybalko static inline int 1821459a227SAleksandr Rybalko class_ri2unit(int class, int ri) 1831459a227SAleksandr Rybalko { 1841459a227SAleksandr Rybalko 1851459a227SAleksandr Rybalko if (class == PMC_CLASS_DMC620_PMU_CD2) 1861459a227SAleksandr Rybalko return (ri / DMC620_CLKDIV2_COUNTERS_N); 1871459a227SAleksandr Rybalko else 1881459a227SAleksandr Rybalko return (ri / DMC620_CLK_COUNTERS_N); 1891459a227SAleksandr Rybalko } 1901459a227SAleksandr Rybalko 1911459a227SAleksandr Rybalko /* 1921459a227SAleksandr Rybalko * read a pmc register 1931459a227SAleksandr Rybalko */ 1941459a227SAleksandr Rybalko 195*39f92a76SMitchell Horne CLASSDEP_FN4(dmc620_read_pmc, int, cpu, int, ri, struct pmc *, pm, 196*39f92a76SMitchell Horne pmc_value_t *, v) 1971459a227SAleksandr Rybalko { 1981459a227SAleksandr Rybalko struct dmc620_descr *desc; 1991459a227SAleksandr Rybalko 2001459a227SAleksandr Rybalko KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 2011459a227SAleksandr Rybalko ("[dmc620,%d] illegal CPU value %d", __LINE__, cpu)); 2021459a227SAleksandr Rybalko KASSERT(ri >= 0, ("[dmc620,%d] row-index %d out of range", __LINE__, 2031459a227SAleksandr Rybalko ri)); 2041459a227SAleksandr Rybalko 2051459a227SAleksandr Rybalko desc = dmc620desc(class, cpu, ri); 2061459a227SAleksandr Rybalko 2071459a227SAleksandr Rybalko PMCDBG3(MDP,REA,1,"%s id=%d class=%d", __func__, ri, class); 2081459a227SAleksandr Rybalko 2091459a227SAleksandr Rybalko /* 2101459a227SAleksandr Rybalko * Should emulate 64bits, because 32 bits counter overflows faster than 2111459a227SAleksandr Rybalko * pmcstat default period. 2121459a227SAleksandr Rybalko */ 2131459a227SAleksandr Rybalko /* Always CPU0. Single controller for all CPUs. */ 2141459a227SAleksandr Rybalko *v = ((uint64_t)pm->pm_pcpu_state[0].pps_overflowcnt << 32) | 2151459a227SAleksandr Rybalko pmu_dmc620_rd4(desc->pd_rw_arg, cntr(class, ri), 2161459a227SAleksandr Rybalko DMC620_COUNTER_VALUE_LO); 2171459a227SAleksandr Rybalko 2181459a227SAleksandr Rybalko PMCDBG3(MDP, REA, 2, "%s id=%d -> %jd", __func__, ri, *v); 2191459a227SAleksandr Rybalko 2201459a227SAleksandr Rybalko return (0); 2211459a227SAleksandr Rybalko } 2221459a227SAleksandr Rybalko 2231459a227SAleksandr Rybalko /* 2241459a227SAleksandr Rybalko * Write a pmc register. 2251459a227SAleksandr Rybalko */ 2261459a227SAleksandr Rybalko 227*39f92a76SMitchell Horne CLASSDEP_FN4(dmc620_write_pmc, int, cpu, int, ri, struct pmc *, pm, 228*39f92a76SMitchell Horne pmc_value_t, v) 2291459a227SAleksandr Rybalko { 2301459a227SAleksandr Rybalko struct dmc620_descr *desc; 2311459a227SAleksandr Rybalko 2321459a227SAleksandr Rybalko KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 2331459a227SAleksandr Rybalko ("[dmc620,%d] illegal CPU value %d", __LINE__, cpu)); 2341459a227SAleksandr Rybalko KASSERT(ri >= 0, ("[dmc620,%d] row-index %d out of range", __LINE__, 2351459a227SAleksandr Rybalko ri)); 2361459a227SAleksandr Rybalko 2371459a227SAleksandr Rybalko desc = dmc620desc(class, cpu, ri); 2381459a227SAleksandr Rybalko 2391459a227SAleksandr Rybalko PMCDBG4(MDP, WRI, 1, "%s cpu=%d ri=%d v=%jx", __func__, cpu, ri, v); 2401459a227SAleksandr Rybalko 2411459a227SAleksandr Rybalko pmu_dmc620_wr4(desc->pd_rw_arg, cntr(class, ri), 2421459a227SAleksandr Rybalko DMC620_COUNTER_VALUE_LO, v); 2431459a227SAleksandr Rybalko return (0); 2441459a227SAleksandr Rybalko } 2451459a227SAleksandr Rybalko 2461459a227SAleksandr Rybalko /* 2471459a227SAleksandr Rybalko * configure hardware pmc according to the configuration recorded in 2481459a227SAleksandr Rybalko * pmc 'pm'. 2491459a227SAleksandr Rybalko */ 2501459a227SAleksandr Rybalko 2511459a227SAleksandr Rybalko CLASSDEP_FN3(dmc620_config_pmc, int, cpu, int, ri, struct pmc *, pm) 2521459a227SAleksandr Rybalko { 2531459a227SAleksandr Rybalko struct pmc_hw *phw; 2541459a227SAleksandr Rybalko 2551459a227SAleksandr Rybalko PMCDBG4(MDP, CFG, 1, "%s cpu=%d ri=%d pm=%p", __func__, cpu, ri, pm); 2561459a227SAleksandr Rybalko 2571459a227SAleksandr Rybalko KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 2581459a227SAleksandr Rybalko ("[dmc620,%d] illegal CPU value %d", __LINE__, cpu)); 2591459a227SAleksandr Rybalko KASSERT(ri >= 0, ("[dmc620,%d] row-index %d out of range", __LINE__, 2601459a227SAleksandr Rybalko ri)); 2611459a227SAleksandr Rybalko 2621459a227SAleksandr Rybalko phw = dmc620desc(class, cpu, ri)->pd_phw; 2631459a227SAleksandr Rybalko 2641459a227SAleksandr Rybalko KASSERT(pm == NULL || phw->phw_pmc == NULL, 2651459a227SAleksandr Rybalko ("[dmc620,%d] pm=%p phw->pm=%p hwpmc not unconfigured", 2661459a227SAleksandr Rybalko __LINE__, pm, phw->phw_pmc)); 2671459a227SAleksandr Rybalko 2681459a227SAleksandr Rybalko phw->phw_pmc = pm; 2691459a227SAleksandr Rybalko return (0); 2701459a227SAleksandr Rybalko } 2711459a227SAleksandr Rybalko 2721459a227SAleksandr Rybalko /* 2731459a227SAleksandr Rybalko * Retrieve a configured PMC pointer from hardware state. 2741459a227SAleksandr Rybalko */ 2751459a227SAleksandr Rybalko 2761459a227SAleksandr Rybalko CLASSDEP_FN3(dmc620_get_config, int, cpu, int, ri, struct pmc **, ppm) 2771459a227SAleksandr Rybalko { 2781459a227SAleksandr Rybalko 2791459a227SAleksandr Rybalko *ppm = dmc620desc(class, cpu, ri)->pd_phw->phw_pmc; 2801459a227SAleksandr Rybalko 2811459a227SAleksandr Rybalko return (0); 2821459a227SAleksandr Rybalko } 2831459a227SAleksandr Rybalko 2841459a227SAleksandr Rybalko /* 2851459a227SAleksandr Rybalko * Check if a given allocation is feasible. 2861459a227SAleksandr Rybalko */ 2871459a227SAleksandr Rybalko 2881459a227SAleksandr Rybalko CLASSDEP_FN4(dmc620_allocate_pmc, int, cpu, int, ri, struct pmc *,pm, 2891459a227SAleksandr Rybalko const struct pmc_op_pmcallocate *, a) 2901459a227SAleksandr Rybalko { 2911459a227SAleksandr Rybalko const struct pmc_descr *pd; 2921459a227SAleksandr Rybalko uint64_t caps, control; 2931459a227SAleksandr Rybalko enum pmc_event pe; 2941459a227SAleksandr Rybalko uint8_t e; 2951459a227SAleksandr Rybalko 2961459a227SAleksandr Rybalko (void) cpu; 2971459a227SAleksandr Rybalko 2981459a227SAleksandr Rybalko KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 2991459a227SAleksandr Rybalko ("[dmc620,%d] illegal CPU value %d", __LINE__, cpu)); 3001459a227SAleksandr Rybalko KASSERT(ri >= 0, ("[dmc620,%d] row-index %d out of range", __LINE__, 3011459a227SAleksandr Rybalko ri)); 3021459a227SAleksandr Rybalko 3031459a227SAleksandr Rybalko pd = &dmc620desc(class, cpu, ri)->pd_descr; 3041459a227SAleksandr Rybalko if (dmc620_pmcs[class_ri2unit(class, ri)].domain != 3051459a227SAleksandr Rybalko pcpu_find(cpu)->pc_domain) 3061459a227SAleksandr Rybalko return (EINVAL); 3071459a227SAleksandr Rybalko 3081459a227SAleksandr Rybalko /* check class match */ 3091459a227SAleksandr Rybalko if (pd->pd_class != a->pm_class) 3101459a227SAleksandr Rybalko return (EINVAL); 3111459a227SAleksandr Rybalko 3121459a227SAleksandr Rybalko caps = pm->pm_caps; 3131459a227SAleksandr Rybalko 3141459a227SAleksandr Rybalko PMCDBG3(MDP, ALL, 1, "%s ri=%d caps=0x%x", __func__, ri, caps); 3151459a227SAleksandr Rybalko 3161459a227SAleksandr Rybalko pe = a->pm_ev; 3171459a227SAleksandr Rybalko if (class == PMC_CLASS_DMC620_PMU_CD2) 3181459a227SAleksandr Rybalko e = pe - PMC_EV_DMC620_PMU_CD2_FIRST; 3191459a227SAleksandr Rybalko else 3201459a227SAleksandr Rybalko e = pe - PMC_EV_DMC620_PMU_C_FIRST; 3211459a227SAleksandr Rybalko 3221459a227SAleksandr Rybalko control = (e << DMC620_COUNTER_CONTROL_EVENT_SHIFT) & 3231459a227SAleksandr Rybalko DMC620_COUNTER_CONTROL_EVENT_MASK; 3241459a227SAleksandr Rybalko 3251459a227SAleksandr Rybalko if (caps & PMC_CAP_INVERT) 3261459a227SAleksandr Rybalko control |= DMC620_COUNTER_CONTROL_INVERT; 3271459a227SAleksandr Rybalko 3281459a227SAleksandr Rybalko pm->pm_md.pm_dmc620.pm_control = control; 3291459a227SAleksandr Rybalko pm->pm_md.pm_dmc620.pm_match = a->pm_md.pm_dmc620.pm_dmc620_match; 3301459a227SAleksandr Rybalko pm->pm_md.pm_dmc620.pm_mask = a->pm_md.pm_dmc620.pm_dmc620_mask; 3311459a227SAleksandr Rybalko 3321459a227SAleksandr Rybalko PMCDBG3(MDP, ALL, 2, "%s ri=%d -> control=0x%x", __func__, ri, control); 3331459a227SAleksandr Rybalko 3341459a227SAleksandr Rybalko return (0); 3351459a227SAleksandr Rybalko } 3361459a227SAleksandr Rybalko 3371459a227SAleksandr Rybalko /* 3381459a227SAleksandr Rybalko * Release machine dependent state associated with a PMC. This is a 3391459a227SAleksandr Rybalko * no-op on this architecture. 3401459a227SAleksandr Rybalko * 3411459a227SAleksandr Rybalko */ 3421459a227SAleksandr Rybalko 3431459a227SAleksandr Rybalko /* ARGSUSED0 */ 3441459a227SAleksandr Rybalko CLASSDEP_FN3(dmc620_release_pmc, int, cpu, int, ri, struct pmc *, pmc) 3451459a227SAleksandr Rybalko { 346d78bef0eSBjoern A. Zeeb struct pmc_hw *phw __diagused; 3471459a227SAleksandr Rybalko 3481459a227SAleksandr Rybalko (void) pmc; 3491459a227SAleksandr Rybalko 3501459a227SAleksandr Rybalko KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 3511459a227SAleksandr Rybalko ("[dmc620,%d] illegal CPU value %d", __LINE__, cpu)); 3521459a227SAleksandr Rybalko KASSERT(ri >= 0, ("[dmc620,%d] row-index %d out of range", __LINE__, 3531459a227SAleksandr Rybalko ri)); 3541459a227SAleksandr Rybalko 3551459a227SAleksandr Rybalko phw = dmc620desc(class, cpu, ri)->pd_phw; 3561459a227SAleksandr Rybalko 3571459a227SAleksandr Rybalko KASSERT(phw->phw_pmc == NULL, 3581459a227SAleksandr Rybalko ("[dmc620,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); 3591459a227SAleksandr Rybalko 3601459a227SAleksandr Rybalko return (0); 3611459a227SAleksandr Rybalko } 3621459a227SAleksandr Rybalko 3631459a227SAleksandr Rybalko /* 3641459a227SAleksandr Rybalko * start a PMC. 3651459a227SAleksandr Rybalko */ 3661459a227SAleksandr Rybalko 367*39f92a76SMitchell Horne CLASSDEP_FN3(dmc620_start_pmc, int, cpu, int, ri, struct pmc *, pm) 3681459a227SAleksandr Rybalko { 3691459a227SAleksandr Rybalko struct dmc620_descr *desc; 3701459a227SAleksandr Rybalko uint64_t control; 3711459a227SAleksandr Rybalko 3721459a227SAleksandr Rybalko KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 3731459a227SAleksandr Rybalko ("[dmc620,%d] illegal CPU value %d", __LINE__, cpu)); 3741459a227SAleksandr Rybalko KASSERT(ri >= 0, ("[dmc620,%d] row-index %d out of range", __LINE__, 3751459a227SAleksandr Rybalko ri)); 3761459a227SAleksandr Rybalko 3771459a227SAleksandr Rybalko desc = dmc620desc(class, cpu, ri); 3781459a227SAleksandr Rybalko 3791459a227SAleksandr Rybalko PMCDBG3(MDP, STA, 1, "%s cpu=%d ri=%d", __func__, cpu, ri); 3801459a227SAleksandr Rybalko 3811459a227SAleksandr Rybalko pmu_dmc620_wr4(desc->pd_rw_arg, cntr(class, ri), 3821459a227SAleksandr Rybalko DMC620_COUNTER_MASK_LO, pm->pm_md.pm_dmc620.pm_mask & 0xffffffff); 3831459a227SAleksandr Rybalko pmu_dmc620_wr4(desc->pd_rw_arg, cntr(class, ri), 3841459a227SAleksandr Rybalko DMC620_COUNTER_MASK_HI, pm->pm_md.pm_dmc620.pm_mask >> 32); 3851459a227SAleksandr Rybalko pmu_dmc620_wr4(desc->pd_rw_arg, cntr(class, ri), 3861459a227SAleksandr Rybalko DMC620_COUNTER_MATCH_LO, pm->pm_md.pm_dmc620.pm_match & 0xffffffff); 3871459a227SAleksandr Rybalko pmu_dmc620_wr4(desc->pd_rw_arg, cntr(class, ri), 3881459a227SAleksandr Rybalko DMC620_COUNTER_MATCH_HI, pm->pm_md.pm_dmc620.pm_match >> 32); 3891459a227SAleksandr Rybalko /* turn on the PMC ENABLE bit */ 3901459a227SAleksandr Rybalko control = pm->pm_md.pm_dmc620.pm_control | DMC620_COUNTER_CONTROL_ENABLE; 3911459a227SAleksandr Rybalko 3921459a227SAleksandr Rybalko PMCDBG2(MDP, STA, 2, "%s control=0x%x", __func__, control); 3931459a227SAleksandr Rybalko 3941459a227SAleksandr Rybalko pmu_dmc620_wr4(desc->pd_rw_arg, cntr(class, ri), 3951459a227SAleksandr Rybalko DMC620_COUNTER_CONTROL, control); 3961459a227SAleksandr Rybalko return (0); 3971459a227SAleksandr Rybalko } 3981459a227SAleksandr Rybalko 3991459a227SAleksandr Rybalko /* 4001459a227SAleksandr Rybalko * Stop a PMC. 4011459a227SAleksandr Rybalko */ 4021459a227SAleksandr Rybalko 403*39f92a76SMitchell Horne CLASSDEP_FN3(dmc620_stop_pmc, int, cpu, int, ri, struct pmc *, pm) 4041459a227SAleksandr Rybalko { 4051459a227SAleksandr Rybalko struct dmc620_descr *desc; 4061459a227SAleksandr Rybalko uint64_t control; 4071459a227SAleksandr Rybalko 4081459a227SAleksandr Rybalko KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 4091459a227SAleksandr Rybalko ("[dmc620,%d] illegal CPU value %d", __LINE__, cpu)); 4101459a227SAleksandr Rybalko KASSERT(ri >= 0, ("[dmc620,%d] row-index %d out of range", __LINE__, 4111459a227SAleksandr Rybalko ri)); 4121459a227SAleksandr Rybalko 4131459a227SAleksandr Rybalko desc = dmc620desc(class, cpu, ri); 4141459a227SAleksandr Rybalko 4151459a227SAleksandr Rybalko PMCDBG2(MDP, STO, 1, "%s ri=%d", __func__, ri); 4161459a227SAleksandr Rybalko 4171459a227SAleksandr Rybalko /* turn off the PMC ENABLE bit */ 4181459a227SAleksandr Rybalko control = pm->pm_md.pm_dmc620.pm_control & ~DMC620_COUNTER_CONTROL_ENABLE; 4191459a227SAleksandr Rybalko pmu_dmc620_wr4(desc->pd_rw_arg, cntr(class, ri), 4201459a227SAleksandr Rybalko DMC620_COUNTER_CONTROL, control); 4211459a227SAleksandr Rybalko 4221459a227SAleksandr Rybalko return (0); 4231459a227SAleksandr Rybalko } 4241459a227SAleksandr Rybalko 4251459a227SAleksandr Rybalko /* 4261459a227SAleksandr Rybalko * describe a PMC 4271459a227SAleksandr Rybalko */ 4281459a227SAleksandr Rybalko CLASSDEP_FN4(dmc620_describe, int, cpu, int, ri, struct pmc_info *, pi, 4291459a227SAleksandr Rybalko struct pmc **, ppmc) 4301459a227SAleksandr Rybalko { 43131610e34SMitchell Horne struct pmc_descr *pd; 4321459a227SAleksandr Rybalko struct pmc_hw *phw; 4331459a227SAleksandr Rybalko 4341459a227SAleksandr Rybalko KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 4351459a227SAleksandr Rybalko ("[dmc620,%d] illegal CPU %d", __LINE__, cpu)); 4361459a227SAleksandr Rybalko KASSERT(ri >= 0, ("[dmc620,%d] row-index %d out of range", __LINE__, 4371459a227SAleksandr Rybalko ri)); 4381459a227SAleksandr Rybalko 4391459a227SAleksandr Rybalko phw = dmc620desc(class, cpu, ri)->pd_phw; 44031610e34SMitchell Horne pd = &dmc620desc(class, cpu, ri)->pd_descr; 4411459a227SAleksandr Rybalko 44231610e34SMitchell Horne strlcpy(pi->pm_name, pd->pd_name, sizeof(pi->pm_name)); 44331610e34SMitchell Horne pi->pm_class = pd->pd_class; 4441459a227SAleksandr Rybalko 4451459a227SAleksandr Rybalko if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) { 4461459a227SAleksandr Rybalko pi->pm_enabled = TRUE; 4471459a227SAleksandr Rybalko *ppmc = phw->phw_pmc; 4481459a227SAleksandr Rybalko } else { 4491459a227SAleksandr Rybalko pi->pm_enabled = FALSE; 4501459a227SAleksandr Rybalko *ppmc = NULL; 4511459a227SAleksandr Rybalko } 4521459a227SAleksandr Rybalko 4531459a227SAleksandr Rybalko return (0); 4541459a227SAleksandr Rybalko } 4551459a227SAleksandr Rybalko 4561459a227SAleksandr Rybalko /* 4571459a227SAleksandr Rybalko * processor dependent initialization. 4581459a227SAleksandr Rybalko */ 4591459a227SAleksandr Rybalko 4601459a227SAleksandr Rybalko CLASSDEP_FN2(dmc620_pcpu_init, struct pmc_mdep *, md, int, cpu) 4611459a227SAleksandr Rybalko { 4621459a227SAleksandr Rybalko int first_ri, n, npmc; 4631459a227SAleksandr Rybalko struct pmc_hw *phw; 4641459a227SAleksandr Rybalko struct pmc_cpu *pc; 4651459a227SAleksandr Rybalko int mdep_class; 4661459a227SAleksandr Rybalko 4671459a227SAleksandr Rybalko mdep_class = class2mdep(class); 4681459a227SAleksandr Rybalko KASSERT(mdep_class != -1, ("[dmc620,%d] wrong class %d", __LINE__, 4691459a227SAleksandr Rybalko class)); 4701459a227SAleksandr Rybalko KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 4711459a227SAleksandr Rybalko ("[dmc620,%d] insane cpu number %d", __LINE__, cpu)); 4721459a227SAleksandr Rybalko 4731459a227SAleksandr Rybalko PMCDBG1(MDP, INI, 1, "dmc620-init cpu=%d", cpu); 4741459a227SAleksandr Rybalko 4751459a227SAleksandr Rybalko /* 4761459a227SAleksandr Rybalko * Set the content of the hardware descriptors to a known 4771459a227SAleksandr Rybalko * state and initialize pointers in the MI per-cpu descriptor. 4781459a227SAleksandr Rybalko */ 4791459a227SAleksandr Rybalko 4801459a227SAleksandr Rybalko pc = pmc_pcpu[cpu]; 4811459a227SAleksandr Rybalko first_ri = md->pmd_classdep[mdep_class].pcd_ri; 4821459a227SAleksandr Rybalko npmc = md->pmd_classdep[mdep_class].pcd_num; 4831459a227SAleksandr Rybalko 4841459a227SAleksandr Rybalko for (n = 0; n < npmc; n++, phw++) { 4851459a227SAleksandr Rybalko phw = dmc620desc(class, cpu, n)->pd_phw; 4861459a227SAleksandr Rybalko phw->phw_state = PMC_PHW_CPU_TO_STATE(cpu) | 4871459a227SAleksandr Rybalko PMC_PHW_INDEX_TO_STATE(n); 4881459a227SAleksandr Rybalko /* Set enabled only if unit present. */ 4891459a227SAleksandr Rybalko if (dmc620_pmcs[class_ri2unit(class, n)].arg != NULL) 4901459a227SAleksandr Rybalko phw->phw_state |= PMC_PHW_FLAG_IS_ENABLED; 4911459a227SAleksandr Rybalko phw->phw_pmc = NULL; 4921459a227SAleksandr Rybalko pc->pc_hwpmcs[n + first_ri] = phw; 4931459a227SAleksandr Rybalko } 4941459a227SAleksandr Rybalko return (0); 4951459a227SAleksandr Rybalko } 4961459a227SAleksandr Rybalko 4971459a227SAleksandr Rybalko /* 4981459a227SAleksandr Rybalko * processor dependent cleanup prior to the KLD 4991459a227SAleksandr Rybalko * being unloaded 5001459a227SAleksandr Rybalko */ 5011459a227SAleksandr Rybalko 5021459a227SAleksandr Rybalko CLASSDEP_FN2(dmc620_pcpu_fini, struct pmc_mdep *, md, int, cpu) 5031459a227SAleksandr Rybalko { 5041459a227SAleksandr Rybalko 5051459a227SAleksandr Rybalko return (0); 5061459a227SAleksandr Rybalko } 5071459a227SAleksandr Rybalko 5081459a227SAleksandr Rybalko int 5091459a227SAleksandr Rybalko dmc620_intr(struct trapframe *tf, int class, int unit, int i) 5101459a227SAleksandr Rybalko { 511d78bef0eSBjoern A. Zeeb struct pmc_cpu *pc __diagused; 5121459a227SAleksandr Rybalko struct pmc_hw *phw; 5131459a227SAleksandr Rybalko struct pmc *pm; 5141459a227SAleksandr Rybalko int error, cpu, ri; 5151459a227SAleksandr Rybalko 5161459a227SAleksandr Rybalko ri = i + unit * ((class == PMC_CLASS_DMC620_PMU_CD2) ? 5171459a227SAleksandr Rybalko DMC620_CLKDIV2_COUNTERS_N : DMC620_CLK_COUNTERS_N); 5181459a227SAleksandr Rybalko cpu = curcpu; 5191459a227SAleksandr Rybalko KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 5201459a227SAleksandr Rybalko ("[dmc620,%d] CPU %d out of range", __LINE__, cpu)); 5211459a227SAleksandr Rybalko pc = pmc_pcpu[cpu]; 5221459a227SAleksandr Rybalko KASSERT(pc != NULL, ("pc != NULL")); 5231459a227SAleksandr Rybalko 5241459a227SAleksandr Rybalko phw = dmc620desc(class, cpu, ri)->pd_phw; 5251459a227SAleksandr Rybalko KASSERT(phw != NULL, ("phw != NULL")); 5261459a227SAleksandr Rybalko pm = phw->phw_pmc; 5271459a227SAleksandr Rybalko if (pm == NULL) 5281459a227SAleksandr Rybalko return (0); 5291459a227SAleksandr Rybalko 5301459a227SAleksandr Rybalko if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { 5311459a227SAleksandr Rybalko /* Always CPU0. */ 5321459a227SAleksandr Rybalko pm->pm_pcpu_state[0].pps_overflowcnt += 1; 5331459a227SAleksandr Rybalko return (0); 5341459a227SAleksandr Rybalko } 5351459a227SAleksandr Rybalko 5361459a227SAleksandr Rybalko if (pm->pm_state != PMC_STATE_RUNNING) 5371459a227SAleksandr Rybalko return (0); 5381459a227SAleksandr Rybalko 5391459a227SAleksandr Rybalko error = pmc_process_interrupt(PMC_HR, pm, tf); 5401459a227SAleksandr Rybalko if (error) 541*39f92a76SMitchell Horne dmc620_stop_pmc(class, cpu, ri, pm); 5421459a227SAleksandr Rybalko 5431459a227SAleksandr Rybalko /* Reload sampling count */ 544*39f92a76SMitchell Horne dmc620_write_pmc(class, cpu, ri, pm, pm->pm_sc.pm_reloadcount); 5451459a227SAleksandr Rybalko 5461459a227SAleksandr Rybalko return (0); 5471459a227SAleksandr Rybalko } 5481459a227SAleksandr Rybalko 5491459a227SAleksandr Rybalko /* 5501459a227SAleksandr Rybalko * Initialize ourselves. 5511459a227SAleksandr Rybalko */ 5521459a227SAleksandr Rybalko 5531459a227SAleksandr Rybalko int 5541459a227SAleksandr Rybalko pmc_dmc620_initialize_cd2(struct pmc_mdep *md) 5551459a227SAleksandr Rybalko { 5561459a227SAleksandr Rybalko struct pmc_classdep *pcd; 5571459a227SAleksandr Rybalko int i, npmc, unit; 5581459a227SAleksandr Rybalko 5591459a227SAleksandr Rybalko KASSERT(md != NULL, ("[dmc620,%d] md is NULL", __LINE__)); 5601459a227SAleksandr Rybalko KASSERT(dmc620_npmcs <= DMC620_UNIT_MAX, 5611459a227SAleksandr Rybalko ("[dmc620,%d] dmc620_npmcs too big", __LINE__)); 5621459a227SAleksandr Rybalko 5631459a227SAleksandr Rybalko PMCDBG0(MDP,INI,1, "dmc620-initialize"); 5641459a227SAleksandr Rybalko 5651459a227SAleksandr Rybalko npmc = DMC620_CLKDIV2_COUNTERS_N * dmc620_npmcs; 5661459a227SAleksandr Rybalko pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_DMC620_CD2]; 5671459a227SAleksandr Rybalko 5681459a227SAleksandr Rybalko pcd->pcd_caps = PMC_CAP_SYSTEM | PMC_CAP_READ | 5691459a227SAleksandr Rybalko PMC_CAP_WRITE | PMC_CAP_INVERT | PMC_CAP_QUALIFIER | 5701459a227SAleksandr Rybalko PMC_CAP_INTERRUPT | PMC_CAP_DOMWIDE; 5711459a227SAleksandr Rybalko pcd->pcd_class = PMC_CLASS_DMC620_PMU_CD2; 5721459a227SAleksandr Rybalko pcd->pcd_num = npmc; 5731459a227SAleksandr Rybalko pcd->pcd_ri = md->pmd_npmc; 5741459a227SAleksandr Rybalko pcd->pcd_width = 32; 5751459a227SAleksandr Rybalko 5761459a227SAleksandr Rybalko pcd->pcd_allocate_pmc = dmc620_allocate_pmc_cd2; 5771459a227SAleksandr Rybalko pcd->pcd_config_pmc = dmc620_config_pmc_cd2; 5781459a227SAleksandr Rybalko pcd->pcd_describe = dmc620_describe_cd2; 5791459a227SAleksandr Rybalko pcd->pcd_get_config = dmc620_get_config_cd2; 5801459a227SAleksandr Rybalko pcd->pcd_get_msr = NULL; 5811459a227SAleksandr Rybalko pcd->pcd_pcpu_fini = dmc620_pcpu_fini_cd2; 5821459a227SAleksandr Rybalko pcd->pcd_pcpu_init = dmc620_pcpu_init_cd2; 5831459a227SAleksandr Rybalko pcd->pcd_read_pmc = dmc620_read_pmc_cd2; 5841459a227SAleksandr Rybalko pcd->pcd_release_pmc = dmc620_release_pmc_cd2; 5851459a227SAleksandr Rybalko pcd->pcd_start_pmc = dmc620_start_pmc_cd2; 5861459a227SAleksandr Rybalko pcd->pcd_stop_pmc = dmc620_stop_pmc_cd2; 5871459a227SAleksandr Rybalko pcd->pcd_write_pmc = dmc620_write_pmc_cd2; 5881459a227SAleksandr Rybalko 5891459a227SAleksandr Rybalko md->pmd_npmc += npmc; 5901459a227SAleksandr Rybalko dmc620_pmcdesc[0] = malloc(sizeof(struct dmc620_descr *) * npmc * 5911459a227SAleksandr Rybalko DMC620_PMU_DEFAULT_UNITS_N, M_PMC, M_WAITOK|M_ZERO); 5921459a227SAleksandr Rybalko for (i = 0; i < npmc; i++) { 5931459a227SAleksandr Rybalko dmc620_pmcdesc[0][i] = malloc(sizeof(struct dmc620_descr), 5941459a227SAleksandr Rybalko M_PMC, M_WAITOK|M_ZERO); 5951459a227SAleksandr Rybalko 5961459a227SAleksandr Rybalko unit = i / DMC620_CLKDIV2_COUNTERS_N; 5971459a227SAleksandr Rybalko KASSERT(unit >= 0, ("unit >= 0")); 5981459a227SAleksandr Rybalko KASSERT(dmc620_pmcs[unit].arg != NULL, ("arg != NULL")); 5991459a227SAleksandr Rybalko 6001459a227SAleksandr Rybalko dmc620_pmcdesc[0][i]->pd_rw_arg = dmc620_pmcs[unit].arg; 6011459a227SAleksandr Rybalko dmc620_pmcdesc[0][i]->pd_descr.pd_class = 6021459a227SAleksandr Rybalko PMC_CLASS_DMC620_PMU_CD2; 6031459a227SAleksandr Rybalko dmc620_pmcdesc[0][i]->pd_descr.pd_caps = pcd->pcd_caps; 6041459a227SAleksandr Rybalko dmc620_pmcdesc[0][i]->pd_phw = malloc(sizeof(struct pmc_hw), 6051459a227SAleksandr Rybalko M_PMC, M_WAITOK|M_ZERO); 6061459a227SAleksandr Rybalko snprintf(dmc620_pmcdesc[0][i]->pd_descr.pd_name, 63, 6071459a227SAleksandr Rybalko "DMC620_CD2_%d", i); 6081459a227SAleksandr Rybalko } 6091459a227SAleksandr Rybalko 6101459a227SAleksandr Rybalko return (0); 6111459a227SAleksandr Rybalko } 6121459a227SAleksandr Rybalko 6131459a227SAleksandr Rybalko int 6141459a227SAleksandr Rybalko pmc_dmc620_initialize_c(struct pmc_mdep *md) 6151459a227SAleksandr Rybalko { 6161459a227SAleksandr Rybalko struct pmc_classdep *pcd; 6171459a227SAleksandr Rybalko int i, npmc, unit; 6181459a227SAleksandr Rybalko 6191459a227SAleksandr Rybalko KASSERT(md != NULL, ("[dmc620,%d] md is NULL", __LINE__)); 6201459a227SAleksandr Rybalko KASSERT(dmc620_npmcs <= DMC620_UNIT_MAX, 6211459a227SAleksandr Rybalko ("[dmc620,%d] dmc620_npmcs too big", __LINE__)); 6221459a227SAleksandr Rybalko 6231459a227SAleksandr Rybalko PMCDBG0(MDP,INI,1, "dmc620-initialize"); 6241459a227SAleksandr Rybalko 6251459a227SAleksandr Rybalko npmc = DMC620_CLK_COUNTERS_N * dmc620_npmcs; 6261459a227SAleksandr Rybalko pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_DMC620_C]; 6271459a227SAleksandr Rybalko 6281459a227SAleksandr Rybalko pcd->pcd_caps = PMC_CAP_SYSTEM | PMC_CAP_READ | 6291459a227SAleksandr Rybalko PMC_CAP_WRITE | PMC_CAP_INVERT | PMC_CAP_QUALIFIER | 6301459a227SAleksandr Rybalko PMC_CAP_INTERRUPT | PMC_CAP_DOMWIDE; 6311459a227SAleksandr Rybalko pcd->pcd_class = PMC_CLASS_DMC620_PMU_C; 6321459a227SAleksandr Rybalko pcd->pcd_num = npmc; 6331459a227SAleksandr Rybalko pcd->pcd_ri = md->pmd_npmc; 6341459a227SAleksandr Rybalko pcd->pcd_width = 32; 6351459a227SAleksandr Rybalko 6361459a227SAleksandr Rybalko pcd->pcd_allocate_pmc = dmc620_allocate_pmc_c; 6371459a227SAleksandr Rybalko pcd->pcd_config_pmc = dmc620_config_pmc_c; 6381459a227SAleksandr Rybalko pcd->pcd_describe = dmc620_describe_c; 6391459a227SAleksandr Rybalko pcd->pcd_get_config = dmc620_get_config_c; 6401459a227SAleksandr Rybalko pcd->pcd_get_msr = NULL; 6411459a227SAleksandr Rybalko pcd->pcd_pcpu_fini = dmc620_pcpu_fini_c; 6421459a227SAleksandr Rybalko pcd->pcd_pcpu_init = dmc620_pcpu_init_c; 6431459a227SAleksandr Rybalko pcd->pcd_read_pmc = dmc620_read_pmc_c; 6441459a227SAleksandr Rybalko pcd->pcd_release_pmc = dmc620_release_pmc_c; 6451459a227SAleksandr Rybalko pcd->pcd_start_pmc = dmc620_start_pmc_c; 6461459a227SAleksandr Rybalko pcd->pcd_stop_pmc = dmc620_stop_pmc_c; 6471459a227SAleksandr Rybalko pcd->pcd_write_pmc = dmc620_write_pmc_c; 6481459a227SAleksandr Rybalko 6491459a227SAleksandr Rybalko md->pmd_npmc += npmc; 6501459a227SAleksandr Rybalko dmc620_pmcdesc[1] = malloc(sizeof(struct dmc620_descr *) * npmc * 6511459a227SAleksandr Rybalko DMC620_PMU_DEFAULT_UNITS_N, M_PMC, M_WAITOK|M_ZERO); 6521459a227SAleksandr Rybalko for (i = 0; i < npmc; i++) { 6531459a227SAleksandr Rybalko dmc620_pmcdesc[1][i] = malloc(sizeof(struct dmc620_descr), 6541459a227SAleksandr Rybalko M_PMC, M_WAITOK|M_ZERO); 6551459a227SAleksandr Rybalko 6561459a227SAleksandr Rybalko unit = i / DMC620_CLK_COUNTERS_N; 6571459a227SAleksandr Rybalko KASSERT(unit >= 0, ("unit >= 0")); 6581459a227SAleksandr Rybalko KASSERT(dmc620_pmcs[unit].arg != NULL, ("arg != NULL")); 6591459a227SAleksandr Rybalko 6601459a227SAleksandr Rybalko dmc620_pmcdesc[1][i]->pd_rw_arg = dmc620_pmcs[unit].arg; 6611459a227SAleksandr Rybalko dmc620_pmcdesc[1][i]->pd_descr.pd_class = PMC_CLASS_DMC620_PMU_C; 6621459a227SAleksandr Rybalko dmc620_pmcdesc[1][i]->pd_descr.pd_caps = pcd->pcd_caps; 6631459a227SAleksandr Rybalko dmc620_pmcdesc[1][i]->pd_phw = malloc(sizeof(struct pmc_hw), 6641459a227SAleksandr Rybalko M_PMC, M_WAITOK|M_ZERO); 6651459a227SAleksandr Rybalko snprintf(dmc620_pmcdesc[1][i]->pd_descr.pd_name, 63, 6661459a227SAleksandr Rybalko "DMC620_C_%d", i); 6671459a227SAleksandr Rybalko } 6681459a227SAleksandr Rybalko 6691459a227SAleksandr Rybalko return (0); 6701459a227SAleksandr Rybalko } 6711459a227SAleksandr Rybalko 6721459a227SAleksandr Rybalko void 6731459a227SAleksandr Rybalko pmc_dmc620_finalize_cd2(struct pmc_mdep *md) 6741459a227SAleksandr Rybalko { 6751459a227SAleksandr Rybalko struct pmc_classdep *pcd; 6761459a227SAleksandr Rybalko int i, npmc; 6771459a227SAleksandr Rybalko 6781459a227SAleksandr Rybalko KASSERT(md->pmd_classdep[PMC_MDEP_CLASS_INDEX_DMC620_CD2].pcd_class == 6791459a227SAleksandr Rybalko PMC_CLASS_DMC620_PMU_CD2, ("[dmc620,%d] pmc class mismatch", 6801459a227SAleksandr Rybalko __LINE__)); 6811459a227SAleksandr Rybalko 6821459a227SAleksandr Rybalko pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_DMC620_CD2]; 6831459a227SAleksandr Rybalko 6841459a227SAleksandr Rybalko npmc = pcd->pcd_num; 6851459a227SAleksandr Rybalko for (i = 0; i < npmc; i++) { 6861459a227SAleksandr Rybalko free(dmc620_pmcdesc[0][i]->pd_phw, M_PMC); 6871459a227SAleksandr Rybalko free(dmc620_pmcdesc[0][i], M_PMC); 6881459a227SAleksandr Rybalko } 6891459a227SAleksandr Rybalko free(dmc620_pmcdesc[0], M_PMC); 6901459a227SAleksandr Rybalko dmc620_pmcdesc[0] = NULL; 6911459a227SAleksandr Rybalko } 6921459a227SAleksandr Rybalko 6931459a227SAleksandr Rybalko void 6941459a227SAleksandr Rybalko pmc_dmc620_finalize_c(struct pmc_mdep *md) 6951459a227SAleksandr Rybalko { 6961459a227SAleksandr Rybalko struct pmc_classdep *pcd; 6971459a227SAleksandr Rybalko int i, npmc; 6981459a227SAleksandr Rybalko 6991459a227SAleksandr Rybalko KASSERT(md->pmd_classdep[PMC_MDEP_CLASS_INDEX_DMC620_C].pcd_class == 7001459a227SAleksandr Rybalko PMC_CLASS_DMC620_PMU_C, ("[dmc620,%d] pmc class mismatch", 7011459a227SAleksandr Rybalko __LINE__)); 7021459a227SAleksandr Rybalko 7031459a227SAleksandr Rybalko pcd = &md->pmd_classdep[PMC_MDEP_CLASS_INDEX_DMC620_C]; 7041459a227SAleksandr Rybalko 7051459a227SAleksandr Rybalko npmc = pcd->pcd_num; 7061459a227SAleksandr Rybalko for (i = 0; i < npmc; i++) { 7071459a227SAleksandr Rybalko free(dmc620_pmcdesc[1][i]->pd_phw, M_PMC); 7081459a227SAleksandr Rybalko free(dmc620_pmcdesc[1][i], M_PMC); 7091459a227SAleksandr Rybalko } 7101459a227SAleksandr Rybalko free(dmc620_pmcdesc[1], M_PMC); 7111459a227SAleksandr Rybalko dmc620_pmcdesc[1] = NULL; 7121459a227SAleksandr Rybalko } 713