1*2016e211SJiucheng Xu // SPDX-License-Identifier: GPL-2.0 2*2016e211SJiucheng Xu /* 3*2016e211SJiucheng Xu * Copyright (c) 2022 Amlogic, Inc. All rights reserved. 4*2016e211SJiucheng Xu */ 5*2016e211SJiucheng Xu 6*2016e211SJiucheng Xu #include <linux/err.h> 7*2016e211SJiucheng Xu #include <linux/kernel.h> 8*2016e211SJiucheng Xu #include <linux/module.h> 9*2016e211SJiucheng Xu #include <linux/of.h> 10*2016e211SJiucheng Xu #include <linux/perf_event.h> 11*2016e211SJiucheng Xu #include <linux/platform_device.h> 12*2016e211SJiucheng Xu #include <linux/printk.h> 13*2016e211SJiucheng Xu #include <linux/types.h> 14*2016e211SJiucheng Xu #include <linux/version.h> 15*2016e211SJiucheng Xu 16*2016e211SJiucheng Xu #include <soc/amlogic/meson_ddr_pmu.h> 17*2016e211SJiucheng Xu 18*2016e211SJiucheng Xu #define PORT_MAJOR 32 19*2016e211SJiucheng Xu #define DEFAULT_XTAL_FREQ 24000000UL 20*2016e211SJiucheng Xu 21*2016e211SJiucheng Xu #define DMC_QOS_IRQ BIT(30) 22*2016e211SJiucheng Xu 23*2016e211SJiucheng Xu /* DMC bandwidth monitor register address offset */ 24*2016e211SJiucheng Xu #define DMC_MON_G12_CTRL0 (0x20 << 2) 25*2016e211SJiucheng Xu #define DMC_MON_G12_CTRL1 (0x21 << 2) 26*2016e211SJiucheng Xu #define DMC_MON_G12_CTRL2 (0x22 << 2) 27*2016e211SJiucheng Xu #define DMC_MON_G12_CTRL3 (0x23 << 2) 28*2016e211SJiucheng Xu #define DMC_MON_G12_CTRL4 (0x24 << 2) 29*2016e211SJiucheng Xu #define DMC_MON_G12_CTRL5 (0x25 << 2) 30*2016e211SJiucheng Xu #define DMC_MON_G12_CTRL6 (0x26 << 2) 31*2016e211SJiucheng Xu #define DMC_MON_G12_CTRL7 (0x27 << 2) 32*2016e211SJiucheng Xu #define DMC_MON_G12_CTRL8 (0x28 << 2) 33*2016e211SJiucheng Xu 34*2016e211SJiucheng Xu #define DMC_MON_G12_ALL_REQ_CNT (0x29 << 2) 35*2016e211SJiucheng Xu #define DMC_MON_G12_ALL_GRANT_CNT (0x2a << 2) 36*2016e211SJiucheng Xu #define DMC_MON_G12_ONE_GRANT_CNT (0x2b << 2) 37*2016e211SJiucheng Xu #define DMC_MON_G12_SEC_GRANT_CNT (0x2c << 2) 38*2016e211SJiucheng Xu #define DMC_MON_G12_THD_GRANT_CNT (0x2d << 2) 39*2016e211SJiucheng Xu #define DMC_MON_G12_FOR_GRANT_CNT (0x2e << 2) 40*2016e211SJiucheng Xu #define DMC_MON_G12_TIMER (0x2f << 2) 41*2016e211SJiucheng Xu 42*2016e211SJiucheng Xu /* Each bit represent a axi line */ 43*2016e211SJiucheng Xu PMU_FORMAT_ATTR(event, "config:0-7"); 44*2016e211SJiucheng Xu PMU_FORMAT_ATTR(arm, "config1:0"); 45*2016e211SJiucheng Xu PMU_FORMAT_ATTR(gpu, "config1:1"); 46*2016e211SJiucheng Xu PMU_FORMAT_ATTR(pcie, "config1:2"); 47*2016e211SJiucheng Xu PMU_FORMAT_ATTR(hdcp, "config1:3"); 48*2016e211SJiucheng Xu PMU_FORMAT_ATTR(hevc_front, "config1:4"); 49*2016e211SJiucheng Xu PMU_FORMAT_ATTR(usb3_0, "config1:6"); 50*2016e211SJiucheng Xu PMU_FORMAT_ATTR(device, "config1:7"); 51*2016e211SJiucheng Xu PMU_FORMAT_ATTR(hevc_back, "config1:8"); 52*2016e211SJiucheng Xu PMU_FORMAT_ATTR(h265enc, "config1:9"); 53*2016e211SJiucheng Xu PMU_FORMAT_ATTR(vpu_read1, "config1:16"); 54*2016e211SJiucheng Xu PMU_FORMAT_ATTR(vpu_read2, "config1:17"); 55*2016e211SJiucheng Xu PMU_FORMAT_ATTR(vpu_read3, "config1:18"); 56*2016e211SJiucheng Xu PMU_FORMAT_ATTR(vpu_write1, "config1:19"); 57*2016e211SJiucheng Xu PMU_FORMAT_ATTR(vpu_write2, "config1:20"); 58*2016e211SJiucheng Xu PMU_FORMAT_ATTR(vdec, "config1:21"); 59*2016e211SJiucheng Xu PMU_FORMAT_ATTR(hcodec, "config1:22"); 60*2016e211SJiucheng Xu PMU_FORMAT_ATTR(ge2d, "config1:23"); 61*2016e211SJiucheng Xu 62*2016e211SJiucheng Xu PMU_FORMAT_ATTR(spicc1, "config1:32"); 63*2016e211SJiucheng Xu PMU_FORMAT_ATTR(usb0, "config1:33"); 64*2016e211SJiucheng Xu PMU_FORMAT_ATTR(dma, "config1:34"); 65*2016e211SJiucheng Xu PMU_FORMAT_ATTR(arb0, "config1:35"); 66*2016e211SJiucheng Xu PMU_FORMAT_ATTR(sd_emmc_b, "config1:36"); 67*2016e211SJiucheng Xu PMU_FORMAT_ATTR(usb1, "config1:37"); 68*2016e211SJiucheng Xu PMU_FORMAT_ATTR(audio, "config1:38"); 69*2016e211SJiucheng Xu PMU_FORMAT_ATTR(aififo, "config1:39"); 70*2016e211SJiucheng Xu PMU_FORMAT_ATTR(parser, "config1:41"); 71*2016e211SJiucheng Xu PMU_FORMAT_ATTR(ao_cpu, "config1:42"); 72*2016e211SJiucheng Xu PMU_FORMAT_ATTR(sd_emmc_c, "config1:43"); 73*2016e211SJiucheng Xu PMU_FORMAT_ATTR(spicc2, "config1:44"); 74*2016e211SJiucheng Xu PMU_FORMAT_ATTR(ethernet, "config1:45"); 75*2016e211SJiucheng Xu PMU_FORMAT_ATTR(sana, "config1:46"); 76*2016e211SJiucheng Xu 77*2016e211SJiucheng Xu /* for sm1 and g12b */ 78*2016e211SJiucheng Xu PMU_FORMAT_ATTR(nna, "config1:10"); 79*2016e211SJiucheng Xu 80*2016e211SJiucheng Xu /* for g12b only */ 81*2016e211SJiucheng Xu PMU_FORMAT_ATTR(gdc, "config1:11"); 82*2016e211SJiucheng Xu PMU_FORMAT_ATTR(mipi_isp, "config1:12"); 83*2016e211SJiucheng Xu PMU_FORMAT_ATTR(arm1, "config1:13"); 84*2016e211SJiucheng Xu PMU_FORMAT_ATTR(sd_emmc_a, "config1:40"); 85*2016e211SJiucheng Xu 86*2016e211SJiucheng Xu static struct attribute *g12_pmu_format_attrs[] = { 87*2016e211SJiucheng Xu &format_attr_event.attr, 88*2016e211SJiucheng Xu &format_attr_arm.attr, 89*2016e211SJiucheng Xu &format_attr_gpu.attr, 90*2016e211SJiucheng Xu &format_attr_nna.attr, 91*2016e211SJiucheng Xu &format_attr_gdc.attr, 92*2016e211SJiucheng Xu &format_attr_arm1.attr, 93*2016e211SJiucheng Xu &format_attr_mipi_isp.attr, 94*2016e211SJiucheng Xu &format_attr_sd_emmc_a.attr, 95*2016e211SJiucheng Xu &format_attr_pcie.attr, 96*2016e211SJiucheng Xu &format_attr_hdcp.attr, 97*2016e211SJiucheng Xu &format_attr_hevc_front.attr, 98*2016e211SJiucheng Xu &format_attr_usb3_0.attr, 99*2016e211SJiucheng Xu &format_attr_device.attr, 100*2016e211SJiucheng Xu &format_attr_hevc_back.attr, 101*2016e211SJiucheng Xu &format_attr_h265enc.attr, 102*2016e211SJiucheng Xu &format_attr_vpu_read1.attr, 103*2016e211SJiucheng Xu &format_attr_vpu_read2.attr, 104*2016e211SJiucheng Xu &format_attr_vpu_read3.attr, 105*2016e211SJiucheng Xu &format_attr_vpu_write1.attr, 106*2016e211SJiucheng Xu &format_attr_vpu_write2.attr, 107*2016e211SJiucheng Xu &format_attr_vdec.attr, 108*2016e211SJiucheng Xu &format_attr_hcodec.attr, 109*2016e211SJiucheng Xu &format_attr_ge2d.attr, 110*2016e211SJiucheng Xu &format_attr_spicc1.attr, 111*2016e211SJiucheng Xu &format_attr_usb0.attr, 112*2016e211SJiucheng Xu &format_attr_dma.attr, 113*2016e211SJiucheng Xu &format_attr_arb0.attr, 114*2016e211SJiucheng Xu &format_attr_sd_emmc_b.attr, 115*2016e211SJiucheng Xu &format_attr_usb1.attr, 116*2016e211SJiucheng Xu &format_attr_audio.attr, 117*2016e211SJiucheng Xu &format_attr_aififo.attr, 118*2016e211SJiucheng Xu &format_attr_parser.attr, 119*2016e211SJiucheng Xu &format_attr_ao_cpu.attr, 120*2016e211SJiucheng Xu &format_attr_sd_emmc_c.attr, 121*2016e211SJiucheng Xu &format_attr_spicc2.attr, 122*2016e211SJiucheng Xu &format_attr_ethernet.attr, 123*2016e211SJiucheng Xu &format_attr_sana.attr, 124*2016e211SJiucheng Xu NULL, 125*2016e211SJiucheng Xu }; 126*2016e211SJiucheng Xu 127*2016e211SJiucheng Xu /* calculate ddr clock */ 128*2016e211SJiucheng Xu static unsigned long dmc_g12_get_freq_quick(struct dmc_info *info) 129*2016e211SJiucheng Xu { 130*2016e211SJiucheng Xu unsigned int val; 131*2016e211SJiucheng Xu unsigned int n, m, od1; 132*2016e211SJiucheng Xu unsigned int od_div = 0xfff; 133*2016e211SJiucheng Xu unsigned long freq = 0; 134*2016e211SJiucheng Xu 135*2016e211SJiucheng Xu val = readl(info->pll_reg); 136*2016e211SJiucheng Xu val = val & 0xfffff; 137*2016e211SJiucheng Xu switch ((val >> 16) & 7) { 138*2016e211SJiucheng Xu case 0: 139*2016e211SJiucheng Xu od_div = 2; 140*2016e211SJiucheng Xu break; 141*2016e211SJiucheng Xu 142*2016e211SJiucheng Xu case 1: 143*2016e211SJiucheng Xu od_div = 3; 144*2016e211SJiucheng Xu break; 145*2016e211SJiucheng Xu 146*2016e211SJiucheng Xu case 2: 147*2016e211SJiucheng Xu od_div = 4; 148*2016e211SJiucheng Xu break; 149*2016e211SJiucheng Xu 150*2016e211SJiucheng Xu case 3: 151*2016e211SJiucheng Xu od_div = 6; 152*2016e211SJiucheng Xu break; 153*2016e211SJiucheng Xu 154*2016e211SJiucheng Xu case 4: 155*2016e211SJiucheng Xu od_div = 8; 156*2016e211SJiucheng Xu break; 157*2016e211SJiucheng Xu 158*2016e211SJiucheng Xu default: 159*2016e211SJiucheng Xu break; 160*2016e211SJiucheng Xu } 161*2016e211SJiucheng Xu 162*2016e211SJiucheng Xu m = val & 0x1ff; 163*2016e211SJiucheng Xu n = ((val >> 10) & 0x1f); 164*2016e211SJiucheng Xu od1 = (((val >> 19) & 0x1)) == 1 ? 2 : 1; 165*2016e211SJiucheng Xu freq = DEFAULT_XTAL_FREQ / 1000; /* avoid overflow */ 166*2016e211SJiucheng Xu if (n) 167*2016e211SJiucheng Xu freq = ((((freq * m) / n) >> od1) / od_div) * 1000; 168*2016e211SJiucheng Xu 169*2016e211SJiucheng Xu return freq; 170*2016e211SJiucheng Xu } 171*2016e211SJiucheng Xu 172*2016e211SJiucheng Xu #ifdef DEBUG 173*2016e211SJiucheng Xu static void g12_dump_reg(struct dmc_info *db) 174*2016e211SJiucheng Xu { 175*2016e211SJiucheng Xu int s = 0, i; 176*2016e211SJiucheng Xu unsigned int r; 177*2016e211SJiucheng Xu 178*2016e211SJiucheng Xu for (i = 0; i < 9; i++) { 179*2016e211SJiucheng Xu r = readl(db->ddr_reg[0] + (DMC_MON_G12_CTRL0 + (i << 2))); 180*2016e211SJiucheng Xu pr_notice("DMC_MON_CTRL%d: %08x\n", i, r); 181*2016e211SJiucheng Xu } 182*2016e211SJiucheng Xu r = readl(db->ddr_reg[0] + DMC_MON_G12_ALL_REQ_CNT); 183*2016e211SJiucheng Xu pr_notice("DMC_MON_ALL_REQ_CNT: %08x\n", r); 184*2016e211SJiucheng Xu r = readl(db->ddr_reg[0] + DMC_MON_G12_ALL_GRANT_CNT); 185*2016e211SJiucheng Xu pr_notice("DMC_MON_ALL_GRANT_CNT:%08x\n", r); 186*2016e211SJiucheng Xu r = readl(db->ddr_reg[0] + DMC_MON_G12_ONE_GRANT_CNT); 187*2016e211SJiucheng Xu pr_notice("DMC_MON_ONE_GRANT_CNT:%08x\n", r); 188*2016e211SJiucheng Xu r = readl(db->ddr_reg[0] + DMC_MON_G12_SEC_GRANT_CNT); 189*2016e211SJiucheng Xu pr_notice("DMC_MON_SEC_GRANT_CNT:%08x\n", r); 190*2016e211SJiucheng Xu r = readl(db->ddr_reg[0] + DMC_MON_G12_THD_GRANT_CNT); 191*2016e211SJiucheng Xu pr_notice("DMC_MON_THD_GRANT_CNT:%08x\n", r); 192*2016e211SJiucheng Xu r = readl(db->ddr_reg[0] + DMC_MON_G12_FOR_GRANT_CNT); 193*2016e211SJiucheng Xu pr_notice("DMC_MON_FOR_GRANT_CNT:%08x\n", r); 194*2016e211SJiucheng Xu r = readl(db->ddr_reg[0] + DMC_MON_G12_TIMER); 195*2016e211SJiucheng Xu pr_notice("DMC_MON_TIMER: %08x\n", r); 196*2016e211SJiucheng Xu } 197*2016e211SJiucheng Xu #endif 198*2016e211SJiucheng Xu 199*2016e211SJiucheng Xu static void dmc_g12_counter_enable(struct dmc_info *info) 200*2016e211SJiucheng Xu { 201*2016e211SJiucheng Xu unsigned int val; 202*2016e211SJiucheng Xu unsigned long clock_count = dmc_g12_get_freq_quick(info) / 10; /* 100ms */ 203*2016e211SJiucheng Xu 204*2016e211SJiucheng Xu writel(clock_count, info->ddr_reg[0] + DMC_MON_G12_TIMER); 205*2016e211SJiucheng Xu 206*2016e211SJiucheng Xu val = readl(info->ddr_reg[0] + DMC_MON_G12_CTRL0); 207*2016e211SJiucheng Xu 208*2016e211SJiucheng Xu /* enable all channel */ 209*2016e211SJiucheng Xu val = BIT(31) | /* enable bit */ 210*2016e211SJiucheng Xu BIT(20) | /* use timer */ 211*2016e211SJiucheng Xu 0x0f; /* 4 channels */ 212*2016e211SJiucheng Xu 213*2016e211SJiucheng Xu writel(val, info->ddr_reg[0] + DMC_MON_G12_CTRL0); 214*2016e211SJiucheng Xu 215*2016e211SJiucheng Xu #ifdef DEBUG 216*2016e211SJiucheng Xu g12_dump_reg(info); 217*2016e211SJiucheng Xu #endif 218*2016e211SJiucheng Xu } 219*2016e211SJiucheng Xu 220*2016e211SJiucheng Xu static void dmc_g12_config_fiter(struct dmc_info *info, 221*2016e211SJiucheng Xu int port, int channel) 222*2016e211SJiucheng Xu { 223*2016e211SJiucheng Xu u32 val; 224*2016e211SJiucheng Xu u32 rp[MAX_CHANNEL_NUM] = {DMC_MON_G12_CTRL1, DMC_MON_G12_CTRL3, 225*2016e211SJiucheng Xu DMC_MON_G12_CTRL5, DMC_MON_G12_CTRL7}; 226*2016e211SJiucheng Xu u32 rs[MAX_CHANNEL_NUM] = {DMC_MON_G12_CTRL2, DMC_MON_G12_CTRL4, 227*2016e211SJiucheng Xu DMC_MON_G12_CTRL6, DMC_MON_G12_CTRL8}; 228*2016e211SJiucheng Xu int subport = -1; 229*2016e211SJiucheng Xu 230*2016e211SJiucheng Xu /* clear all port mask */ 231*2016e211SJiucheng Xu if (port < 0) { 232*2016e211SJiucheng Xu writel(0, info->ddr_reg[0] + rp[channel]); 233*2016e211SJiucheng Xu writel(0, info->ddr_reg[0] + rs[channel]); 234*2016e211SJiucheng Xu return; 235*2016e211SJiucheng Xu } 236*2016e211SJiucheng Xu 237*2016e211SJiucheng Xu if (port >= PORT_MAJOR) 238*2016e211SJiucheng Xu subport = port - PORT_MAJOR; 239*2016e211SJiucheng Xu 240*2016e211SJiucheng Xu if (subport < 0) { 241*2016e211SJiucheng Xu val = readl(info->ddr_reg[0] + rp[channel]); 242*2016e211SJiucheng Xu val |= (1 << port); 243*2016e211SJiucheng Xu writel(val, info->ddr_reg[0] + rp[channel]); 244*2016e211SJiucheng Xu val = 0xffff; 245*2016e211SJiucheng Xu writel(val, info->ddr_reg[0] + rs[channel]); 246*2016e211SJiucheng Xu } else { 247*2016e211SJiucheng Xu val = BIT(23); /* select device */ 248*2016e211SJiucheng Xu writel(val, info->ddr_reg[0] + rp[channel]); 249*2016e211SJiucheng Xu val = readl(info->ddr_reg[0] + rs[channel]); 250*2016e211SJiucheng Xu val |= (1 << subport); 251*2016e211SJiucheng Xu writel(val, info->ddr_reg[0] + rs[channel]); 252*2016e211SJiucheng Xu } 253*2016e211SJiucheng Xu } 254*2016e211SJiucheng Xu 255*2016e211SJiucheng Xu static void dmc_g12_set_axi_filter(struct dmc_info *info, int axi_id, int channel) 256*2016e211SJiucheng Xu { 257*2016e211SJiucheng Xu if (channel > info->hw_info->chann_nr) 258*2016e211SJiucheng Xu return; 259*2016e211SJiucheng Xu 260*2016e211SJiucheng Xu dmc_g12_config_fiter(info, axi_id, channel); 261*2016e211SJiucheng Xu } 262*2016e211SJiucheng Xu 263*2016e211SJiucheng Xu static void dmc_g12_counter_disable(struct dmc_info *info) 264*2016e211SJiucheng Xu { 265*2016e211SJiucheng Xu int i; 266*2016e211SJiucheng Xu 267*2016e211SJiucheng Xu /* clear timer */ 268*2016e211SJiucheng Xu writel(0, info->ddr_reg[0] + DMC_MON_G12_CTRL0); 269*2016e211SJiucheng Xu writel(0, info->ddr_reg[0] + DMC_MON_G12_TIMER); 270*2016e211SJiucheng Xu 271*2016e211SJiucheng Xu writel(0, info->ddr_reg[0] + DMC_MON_G12_ALL_REQ_CNT); 272*2016e211SJiucheng Xu writel(0, info->ddr_reg[0] + DMC_MON_G12_ALL_GRANT_CNT); 273*2016e211SJiucheng Xu writel(0, info->ddr_reg[0] + DMC_MON_G12_ONE_GRANT_CNT); 274*2016e211SJiucheng Xu writel(0, info->ddr_reg[0] + DMC_MON_G12_SEC_GRANT_CNT); 275*2016e211SJiucheng Xu writel(0, info->ddr_reg[0] + DMC_MON_G12_THD_GRANT_CNT); 276*2016e211SJiucheng Xu writel(0, info->ddr_reg[0] + DMC_MON_G12_FOR_GRANT_CNT); 277*2016e211SJiucheng Xu 278*2016e211SJiucheng Xu /* clear port channel mapping */ 279*2016e211SJiucheng Xu for (i = 0; i < info->hw_info->chann_nr; i++) 280*2016e211SJiucheng Xu dmc_g12_config_fiter(info, -1, i); 281*2016e211SJiucheng Xu } 282*2016e211SJiucheng Xu 283*2016e211SJiucheng Xu static void dmc_g12_get_counters(struct dmc_info *info, 284*2016e211SJiucheng Xu struct dmc_counter *counter) 285*2016e211SJiucheng Xu { 286*2016e211SJiucheng Xu int i; 287*2016e211SJiucheng Xu unsigned int reg; 288*2016e211SJiucheng Xu 289*2016e211SJiucheng Xu counter->all_cnt = readl(info->ddr_reg[0] + DMC_MON_G12_ALL_GRANT_CNT); 290*2016e211SJiucheng Xu counter->all_req = readl(info->ddr_reg[0] + DMC_MON_G12_ALL_REQ_CNT); 291*2016e211SJiucheng Xu 292*2016e211SJiucheng Xu for (i = 0; i < info->hw_info->chann_nr; i++) { 293*2016e211SJiucheng Xu reg = DMC_MON_G12_ONE_GRANT_CNT + (i << 2); 294*2016e211SJiucheng Xu counter->channel_cnt[i] = readl(info->ddr_reg[0] + reg); 295*2016e211SJiucheng Xu } 296*2016e211SJiucheng Xu } 297*2016e211SJiucheng Xu 298*2016e211SJiucheng Xu static int dmc_g12_irq_handler(struct dmc_info *info, 299*2016e211SJiucheng Xu struct dmc_counter *counter) 300*2016e211SJiucheng Xu { 301*2016e211SJiucheng Xu unsigned int val; 302*2016e211SJiucheng Xu int ret = -EINVAL; 303*2016e211SJiucheng Xu 304*2016e211SJiucheng Xu val = readl(info->ddr_reg[0] + DMC_MON_G12_CTRL0); 305*2016e211SJiucheng Xu if (val & DMC_QOS_IRQ) { 306*2016e211SJiucheng Xu dmc_g12_get_counters(info, counter); 307*2016e211SJiucheng Xu /* clear irq flags */ 308*2016e211SJiucheng Xu writel(val, info->ddr_reg[0] + DMC_MON_G12_CTRL0); 309*2016e211SJiucheng Xu ret = 0; 310*2016e211SJiucheng Xu } 311*2016e211SJiucheng Xu return ret; 312*2016e211SJiucheng Xu } 313*2016e211SJiucheng Xu 314*2016e211SJiucheng Xu static const struct dmc_hw_info g12a_dmc_info = { 315*2016e211SJiucheng Xu .enable = dmc_g12_counter_enable, 316*2016e211SJiucheng Xu .disable = dmc_g12_counter_disable, 317*2016e211SJiucheng Xu .irq_handler = dmc_g12_irq_handler, 318*2016e211SJiucheng Xu .get_counters = dmc_g12_get_counters, 319*2016e211SJiucheng Xu .set_axi_filter = dmc_g12_set_axi_filter, 320*2016e211SJiucheng Xu 321*2016e211SJiucheng Xu .dmc_nr = 1, 322*2016e211SJiucheng Xu .chann_nr = 4, 323*2016e211SJiucheng Xu .capability = {0X7EFF00FF03DF, 0}, 324*2016e211SJiucheng Xu .fmt_attr = g12_pmu_format_attrs, 325*2016e211SJiucheng Xu }; 326*2016e211SJiucheng Xu 327*2016e211SJiucheng Xu static const struct dmc_hw_info g12b_dmc_info = { 328*2016e211SJiucheng Xu .enable = dmc_g12_counter_enable, 329*2016e211SJiucheng Xu .disable = dmc_g12_counter_disable, 330*2016e211SJiucheng Xu .irq_handler = dmc_g12_irq_handler, 331*2016e211SJiucheng Xu .get_counters = dmc_g12_get_counters, 332*2016e211SJiucheng Xu .set_axi_filter = dmc_g12_set_axi_filter, 333*2016e211SJiucheng Xu 334*2016e211SJiucheng Xu .dmc_nr = 1, 335*2016e211SJiucheng Xu .chann_nr = 4, 336*2016e211SJiucheng Xu .capability = {0X7FFF00FF3FDF, 0}, 337*2016e211SJiucheng Xu .fmt_attr = g12_pmu_format_attrs, 338*2016e211SJiucheng Xu }; 339*2016e211SJiucheng Xu 340*2016e211SJiucheng Xu static const struct dmc_hw_info sm1_dmc_info = { 341*2016e211SJiucheng Xu .enable = dmc_g12_counter_enable, 342*2016e211SJiucheng Xu .disable = dmc_g12_counter_disable, 343*2016e211SJiucheng Xu .irq_handler = dmc_g12_irq_handler, 344*2016e211SJiucheng Xu .get_counters = dmc_g12_get_counters, 345*2016e211SJiucheng Xu .set_axi_filter = dmc_g12_set_axi_filter, 346*2016e211SJiucheng Xu 347*2016e211SJiucheng Xu .dmc_nr = 1, 348*2016e211SJiucheng Xu .chann_nr = 4, 349*2016e211SJiucheng Xu .capability = {0X7EFF00FF07DF, 0}, 350*2016e211SJiucheng Xu .fmt_attr = g12_pmu_format_attrs, 351*2016e211SJiucheng Xu }; 352*2016e211SJiucheng Xu 353*2016e211SJiucheng Xu static int g12_ddr_pmu_probe(struct platform_device *pdev) 354*2016e211SJiucheng Xu { 355*2016e211SJiucheng Xu return meson_ddr_pmu_create(pdev); 356*2016e211SJiucheng Xu } 357*2016e211SJiucheng Xu 358*2016e211SJiucheng Xu static int g12_ddr_pmu_remove(struct platform_device *pdev) 359*2016e211SJiucheng Xu { 360*2016e211SJiucheng Xu meson_ddr_pmu_remove(pdev); 361*2016e211SJiucheng Xu 362*2016e211SJiucheng Xu return 0; 363*2016e211SJiucheng Xu } 364*2016e211SJiucheng Xu 365*2016e211SJiucheng Xu static const struct of_device_id meson_ddr_pmu_dt_match[] = { 366*2016e211SJiucheng Xu { 367*2016e211SJiucheng Xu .compatible = "amlogic,g12a-ddr-pmu", 368*2016e211SJiucheng Xu .data = &g12a_dmc_info, 369*2016e211SJiucheng Xu }, 370*2016e211SJiucheng Xu { 371*2016e211SJiucheng Xu .compatible = "amlogic,g12b-ddr-pmu", 372*2016e211SJiucheng Xu .data = &g12b_dmc_info, 373*2016e211SJiucheng Xu }, 374*2016e211SJiucheng Xu { 375*2016e211SJiucheng Xu .compatible = "amlogic,sm1-ddr-pmu", 376*2016e211SJiucheng Xu .data = &sm1_dmc_info, 377*2016e211SJiucheng Xu }, 378*2016e211SJiucheng Xu {} 379*2016e211SJiucheng Xu }; 380*2016e211SJiucheng Xu 381*2016e211SJiucheng Xu static struct platform_driver g12_ddr_pmu_driver = { 382*2016e211SJiucheng Xu .probe = g12_ddr_pmu_probe, 383*2016e211SJiucheng Xu .remove = g12_ddr_pmu_remove, 384*2016e211SJiucheng Xu 385*2016e211SJiucheng Xu .driver = { 386*2016e211SJiucheng Xu .name = "meson-g12-ddr-pmu", 387*2016e211SJiucheng Xu .of_match_table = meson_ddr_pmu_dt_match, 388*2016e211SJiucheng Xu }, 389*2016e211SJiucheng Xu }; 390*2016e211SJiucheng Xu 391*2016e211SJiucheng Xu module_platform_driver(g12_ddr_pmu_driver); 392*2016e211SJiucheng Xu MODULE_AUTHOR("Jiucheng Xu"); 393*2016e211SJiucheng Xu MODULE_LICENSE("GPL"); 394*2016e211SJiucheng Xu MODULE_DESCRIPTION("Amlogic G12 series SoC DDR PMU"); 395