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