^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Lin Huang <hl@rock-chips.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/devfreq-event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <soc/rockchip/rk3399_grf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define PX30_PMUGRF_OS_REG2 0x208
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define PX30_PMUGRF_OS_REG3 0x20c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define RK3588_PMUGRF_OS_REG(n) (0x200 + (n) * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define RK3128_GRF_SOC_CON0 0x140
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define RK3128_GRF_OS_REG1 0x1cc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define RK3128_GRF_DFI_WRNUM 0x220
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define RK3128_GRF_DFI_RDNUM 0x224
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define RK3128_GRF_DFI_TIMERVAL 0x22c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define RK3128_DDR_MONITOR_EN ((1 << (16 + 6)) + (1 << 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define RK3128_DDR_MONITOR_DISB ((1 << (16 + 6)) + (0 << 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define RK3288_PMU_SYS_REG2 0x9c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define RK3288_GRF_SOC_CON4 0x254
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define RK3288_GRF_SOC_STATUS(n) (0x280 + (n) * 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define RK3288_DFI_EN (0x30003 << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define RK3288_DFI_DIS (0x30000 << 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define RK3288_LPDDR_SEL (0x10001 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define RK3288_DDR3_SEL (0x10000 << 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define RK3328_GRF_OS_REG2 0x5d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define RK3368_GRF_DDRC0_CON0 0x600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define RK3368_GRF_SOC_STATUS5 0x494
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define RK3368_GRF_SOC_STATUS6 0x498
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define RK3368_GRF_SOC_STATUS8 0x4a0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define RK3368_GRF_SOC_STATUS9 0x4a4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define RK3368_GRF_SOC_STATUS10 0x4a8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define RK3368_DFI_EN (0x30003 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define RK3368_DFI_DIS (0x30000 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define MAX_DMC_NUM_CH 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define READ_DRAMTYPE_INFO(n) (((n) >> 13) & 0x7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define READ_CH_INFO(n) (((n) >> 28) & 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define READ_DRAMTYPE_INFO_V3(n, m) ((((n) >> 13) & 0x7) | ((((m) >> 12) & 0x3) << 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define READ_SYSREG_VERSION(m) (((m) >> 28) & 0xf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define READ_LP5_BANK_MODE(m) (((m) >> 1) & 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define READ_LP5_CKR(m) (((m) >> 0) & 0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* DDRMON_CTRL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define DDRMON_CTRL 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define CLR_DDRMON_CTRL (0xffff0000 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define LPDDR5_BANK_MODE(m) ((0x30000 | ((m) & 0x3)) << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define LPDDR5_EN (0x10001 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define DDR4_EN (0x10001 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define LPDDR4_EN (0x10001 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define HARDWARE_EN (0x10001 << 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define LPDDR2_3_EN (0x10001 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define SOFTWARE_EN (0x10001 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define SOFTWARE_DIS (0x10000 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define TIME_CNT_EN (0x10001 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define DDRMON_CH0_COUNT_NUM 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define DDRMON_CH0_DFI_ACCESS_NUM 0x2c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define DDRMON_CH1_COUNT_NUM 0x3c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define DDRMON_CH1_DFI_ACCESS_NUM 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* pmu grf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define PMUGRF_OS_REG2 0x308
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) DDR4 = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) DDR3 = 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) LPDDR2 = 5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) LPDDR3 = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) LPDDR4 = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) LPDDR4X = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) LPDDR5 = 9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) DDR5 = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) UNUSED = 0xFF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct dmc_usage {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) u64 access;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) u64 total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * The dfi controller can monitor DDR load. It has an upper and lower threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * for the operating points. Whenever the usage leaves these bounds an event is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * generated to indicate the DDR frequency should be changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct rockchip_dfi {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct devfreq_event_dev *edev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct devfreq_event_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct dmc_usage ch_usage[MAX_DMC_NUM_CH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct regmap *regmap_pmu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct regmap *regmap_grf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct regmap *regmap_pmugrf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) u32 dram_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) u32 mon_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) u32 count_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u32 dram_dynamic_info_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* 0: BG mode, 1: 16 Bank mode, 2: 8 bank mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u32 lp5_bank_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* 0: clk:dqs = 1:2, 1: 1:4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u32 lp5_ckr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * available mask, 1: available, 0: not available
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * each bit represent a channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) u32 ch_msk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static void rk3128_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) regmap_write(info->regmap_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) RK3128_GRF_SOC_CON0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) RK3128_DDR_MONITOR_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static void rk3128_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) regmap_write(info->regmap_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) RK3128_GRF_SOC_CON0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) RK3128_DDR_MONITOR_DISB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static int rk3128_dfi_disable(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) rk3128_dfi_stop_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static int rk3128_dfi_enable(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) rk3128_dfi_start_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static int rk3128_dfi_set_event(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static int rk3128_dfi_get_event(struct devfreq_event_dev *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct devfreq_event_data *edata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) u32 dfi_wr, dfi_rd, dfi_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) rk3128_dfi_stop_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) regmap_read(info->regmap_grf, RK3128_GRF_DFI_WRNUM, &dfi_wr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) regmap_read(info->regmap_grf, RK3128_GRF_DFI_RDNUM, &dfi_rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) regmap_read(info->regmap_grf, RK3128_GRF_DFI_TIMERVAL, &dfi_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) edata->load_count = (dfi_wr + dfi_rd) * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) edata->total_count = dfi_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) rk3128_dfi_start_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static const struct devfreq_event_ops rk3128_dfi_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) .disable = rk3128_dfi_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) .enable = rk3128_dfi_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .get_event = rk3128_dfi_get_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) .set_event = rk3128_dfi_set_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) static void rk3288_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static void rk3288_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static int rk3288_dfi_disable(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) rk3288_dfi_stop_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int rk3288_dfi_enable(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) rk3288_dfi_start_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static int rk3288_dfi_set_event(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static int rk3288_dfi_get_busier_ch(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) u32 tmp, max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u32 i, busier_ch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u32 rd_count, wr_count, total_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) rk3288_dfi_stop_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* Find out which channel is busier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) for (i = 0; i < MAX_DMC_NUM_CH; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (!(info->ch_msk & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) regmap_read(info->regmap_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) RK3288_GRF_SOC_STATUS(11 + i * 4), &wr_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) regmap_read(info->regmap_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) RK3288_GRF_SOC_STATUS(12 + i * 4), &rd_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) regmap_read(info->regmap_grf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) RK3288_GRF_SOC_STATUS(14 + i * 4), &total_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) info->ch_usage[i].access = (wr_count + rd_count) * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) info->ch_usage[i].total = total_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) tmp = info->ch_usage[i].access;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (tmp > max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) busier_ch = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) max = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) rk3288_dfi_start_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return busier_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static int rk3288_dfi_get_event(struct devfreq_event_dev *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) struct devfreq_event_data *edata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) int busier_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) busier_ch = rk3288_dfi_get_busier_ch(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) edata->load_count = info->ch_usage[busier_ch].access;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) edata->total_count = info->ch_usage[busier_ch].total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static const struct devfreq_event_ops rk3288_dfi_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .disable = rk3288_dfi_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .enable = rk3288_dfi_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) .get_event = rk3288_dfi_get_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .set_event = rk3288_dfi_set_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static void rk3368_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static void rk3368_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_DIS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static int rk3368_dfi_disable(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) rk3368_dfi_stop_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static int rk3368_dfi_enable(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) rk3368_dfi_start_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static int rk3368_dfi_set_event(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) static int rk3368_dfi_get_event(struct devfreq_event_dev *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct devfreq_event_data *edata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) u32 dfi0_wr, dfi0_rd, dfi1_wr, dfi1_rd, dfi_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) rk3368_dfi_stop_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS5, &dfi0_wr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS6, &dfi0_rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS9, &dfi1_wr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS10, &dfi1_rd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS8, &dfi_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) edata->load_count = (dfi0_wr + dfi0_rd + dfi1_wr + dfi1_rd) * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) edata->total_count = dfi_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) rk3368_dfi_start_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static const struct devfreq_event_ops rk3368_dfi_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) .disable = rk3368_dfi_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) .enable = rk3368_dfi_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) .get_event = rk3368_dfi_get_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) .set_event = rk3368_dfi_set_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) void __iomem *dfi_regs = info->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) u32 mon_idx = 0, val_6 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (info->mon_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) mon_idx = info->mon_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (info->dram_dynamic_info_reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) regmap_read(info->regmap_pmugrf, info->dram_dynamic_info_reg, &val_6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (info->dram_type == LPDDR5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) info->lp5_bank_mode = READ_LP5_BANK_MODE(val_6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) info->lp5_ckr = READ_LP5_CKR(val_6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) for (i = 0; i < MAX_DMC_NUM_CH; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (!(info->ch_msk & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) /* clear DDRMON_CTRL setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + i * mon_idx + DDRMON_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /* set ddr type to dfi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (info->dram_type == LPDDR3 || info->dram_type == LPDDR2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) writel_relaxed(LPDDR2_3_EN, dfi_regs + i * mon_idx + DDRMON_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) else if (info->dram_type == LPDDR4 || info->dram_type == LPDDR4X)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) writel_relaxed(LPDDR4_EN, dfi_regs + i * mon_idx + DDRMON_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) else if (info->dram_type == DDR4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) writel_relaxed(DDR4_EN, dfi_regs + i * mon_idx + DDRMON_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) else if (info->dram_type == LPDDR5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) writel_relaxed(LPDDR5_EN | LPDDR5_BANK_MODE(info->lp5_bank_mode),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) dfi_regs + i * mon_idx + DDRMON_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* enable count, use software mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) writel_relaxed(SOFTWARE_EN, dfi_regs + i * mon_idx + DDRMON_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) static void rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) void __iomem *dfi_regs = info->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) u32 mon_idx = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (info->mon_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) mon_idx = info->mon_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) for (i = 0; i < MAX_DMC_NUM_CH; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (!(info->ch_msk & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) writel_relaxed(SOFTWARE_DIS, dfi_regs + i * mon_idx + DDRMON_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static int rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) u32 tmp, max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) u32 i, busier_ch = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) void __iomem *dfi_regs = info->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) u32 mon_idx = 0x20, count_rate = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) rockchip_dfi_stop_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (info->mon_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) mon_idx = info->mon_idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (info->count_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) count_rate = info->count_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /* Find out which channel is busier */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) for (i = 0; i < MAX_DMC_NUM_CH; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (!(info->ch_msk & BIT(i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* rk3588 counter is dfi clk rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) info->ch_usage[i].total = readl_relaxed(dfi_regs +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) DDRMON_CH0_COUNT_NUM + i * mon_idx) * count_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* LPDDR5 LPDDR4 and LPDDR4X BL = 16,other DDR type BL = 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) tmp = readl_relaxed(dfi_regs +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) DDRMON_CH0_DFI_ACCESS_NUM + i * mon_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (info->dram_type == LPDDR4 || info->dram_type == LPDDR4X)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) tmp *= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) else if (info->dram_type == LPDDR5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) tmp *= 16 / (4 << info->lp5_ckr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) tmp *= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) info->ch_usage[i].access = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (tmp > max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) busier_ch = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) max = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) rockchip_dfi_start_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return busier_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static int rockchip_dfi_disable(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) rockchip_dfi_stop_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (info->clk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) clk_disable_unprepare(info->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) static int rockchip_dfi_enable(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (info->clk) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) ret = clk_prepare_enable(info->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) dev_err(&edev->dev, "failed to enable dfi clk: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) rockchip_dfi_start_hardware_counter(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) static int rockchip_dfi_set_event(struct devfreq_event_dev *edev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) static int rockchip_dfi_get_event(struct devfreq_event_dev *edev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) struct devfreq_event_data *edata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) int busier_ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) busier_ch = rockchip_dfi_get_busier_ch(edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) edata->load_count = info->ch_usage[busier_ch].access;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) edata->total_count = info->ch_usage[busier_ch].total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) static const struct devfreq_event_ops rockchip_dfi_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) .disable = rockchip_dfi_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) .enable = rockchip_dfi_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) .get_event = rockchip_dfi_get_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) .set_event = rockchip_dfi_set_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) static __maybe_unused __init int rk3588_dfi_init(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) struct rockchip_dfi *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) struct devfreq_event_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) u32 val_2, val_3, val_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) data->regs = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (IS_ERR(data->regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return PTR_ERR(data->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) data->regmap_pmugrf = syscon_regmap_lookup_by_phandle(np, "rockchip,pmu_grf");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (IS_ERR(data->regmap_pmugrf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return PTR_ERR(data->regmap_pmugrf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) regmap_read(data->regmap_pmugrf, RK3588_PMUGRF_OS_REG(2), &val_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) regmap_read(data->regmap_pmugrf, RK3588_PMUGRF_OS_REG(3), &val_3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) regmap_read(data->regmap_pmugrf, RK3588_PMUGRF_OS_REG(4), &val_4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (READ_SYSREG_VERSION(val_3) >= 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) data->dram_type = READ_DRAMTYPE_INFO_V3(val_2, val_3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) data->dram_type = READ_DRAMTYPE_INFO(val_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) data->mon_idx = 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) data->count_rate = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) data->dram_dynamic_info_reg = RK3588_PMUGRF_OS_REG(6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) data->ch_msk = READ_CH_INFO(val_2) | READ_CH_INFO(val_4) << 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) data->clk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) desc->ops = &rockchip_dfi_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) static __maybe_unused __init int px30_dfi_init(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) struct rockchip_dfi *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) struct devfreq_event_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) struct device_node *np = pdev->dev.of_node, *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) u32 val_2, val_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) data->regs = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (IS_ERR(data->regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) return PTR_ERR(data->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) node = of_parse_phandle(np, "rockchip,pmugrf", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) data->regmap_pmugrf = syscon_node_to_regmap(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (IS_ERR(data->regmap_pmugrf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return PTR_ERR(data->regmap_pmugrf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) regmap_read(data->regmap_pmugrf, PX30_PMUGRF_OS_REG2, &val_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) regmap_read(data->regmap_pmugrf, PX30_PMUGRF_OS_REG3, &val_3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (READ_SYSREG_VERSION(val_3) >= 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) data->dram_type = READ_DRAMTYPE_INFO_V3(val_2, val_3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) data->dram_type = READ_DRAMTYPE_INFO(val_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) data->ch_msk = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) data->clk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) desc->ops = &rockchip_dfi_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) static __maybe_unused __init int rk3128_dfi_init(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct rockchip_dfi *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) struct devfreq_event_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) struct device_node *np = pdev->dev.of_node, *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) node = of_parse_phandle(np, "rockchip,grf", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) data->regmap_grf = syscon_node_to_regmap(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (IS_ERR(data->regmap_grf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return PTR_ERR(data->regmap_grf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) desc->ops = &rk3128_dfi_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) static __maybe_unused __init int rk3288_dfi_init(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) struct rockchip_dfi *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) struct devfreq_event_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) struct device_node *np = pdev->dev.of_node, *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) node = of_parse_phandle(np, "rockchip,pmu", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) data->regmap_pmu = syscon_node_to_regmap(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (IS_ERR(data->regmap_pmu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return PTR_ERR(data->regmap_pmu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) node = of_parse_phandle(np, "rockchip,grf", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) data->regmap_grf = syscon_node_to_regmap(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (IS_ERR(data->regmap_grf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return PTR_ERR(data->regmap_grf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) regmap_read(data->regmap_pmu, RK3288_PMU_SYS_REG2, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) data->dram_type = READ_DRAMTYPE_INFO(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) data->ch_msk = READ_CH_INFO(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (data->dram_type == DDR3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) RK3288_DDR3_SEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) RK3288_LPDDR_SEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) desc->ops = &rk3288_dfi_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) static __maybe_unused __init int rk3368_dfi_init(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) struct rockchip_dfi *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) struct devfreq_event_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (!dev->parent || !dev->parent->of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) data->regmap_grf = syscon_node_to_regmap(dev->parent->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (IS_ERR(data->regmap_grf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) return PTR_ERR(data->regmap_grf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) desc->ops = &rk3368_dfi_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) static __maybe_unused __init int rockchip_dfi_init(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) struct rockchip_dfi *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) struct devfreq_event_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) struct device_node *np = pdev->dev.of_node, *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) data->regs = devm_platform_ioremap_resource(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (IS_ERR(data->regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return PTR_ERR(data->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) data->clk = devm_clk_get(dev, "pclk_ddr_mon");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (IS_ERR(data->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) dev_err(dev, "Cannot get the clk dmc_clk\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return PTR_ERR(data->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) /* try to find the optional reference to the pmu syscon */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) node = of_parse_phandle(np, "rockchip,pmu", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) data->regmap_pmu = syscon_node_to_regmap(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) of_node_put(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (IS_ERR(data->regmap_pmu))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return PTR_ERR(data->regmap_pmu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) regmap_read(data->regmap_pmu, PMUGRF_OS_REG2, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) data->dram_type = READ_DRAMTYPE_INFO(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) data->ch_msk = READ_CH_INFO(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) desc->ops = &rockchip_dfi_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) static __maybe_unused __init int rk3328_dfi_init(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct rockchip_dfi *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) struct devfreq_event_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) struct device_node *np = pdev->dev.of_node, *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) data->regs = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (IS_ERR(data->regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) return PTR_ERR(data->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) node = of_parse_phandle(np, "rockchip,grf", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) data->regmap_grf = syscon_node_to_regmap(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (IS_ERR(data->regmap_grf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return PTR_ERR(data->regmap_grf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) regmap_read(data->regmap_grf, RK3328_GRF_OS_REG2, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) data->dram_type = READ_DRAMTYPE_INFO(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) data->ch_msk = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) data->clk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) desc->ops = &rockchip_dfi_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) static const struct of_device_id rockchip_dfi_id_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) #ifdef CONFIG_CPU_PX30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) { .compatible = "rockchip,px30-dfi", .data = px30_dfi_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) #ifdef CONFIG_CPU_RK1808
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) { .compatible = "rockchip,rk1808-dfi", .data = px30_dfi_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) #ifdef CONFIG_CPU_RK312X
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) { .compatible = "rockchip,rk3128-dfi", .data = rk3128_dfi_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) #ifdef CONFIG_CPU_RK3288
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) { .compatible = "rockchip,rk3288-dfi", .data = rk3288_dfi_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) #ifdef CONFIG_CPU_RK3328
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) { .compatible = "rockchip,rk3328-dfi", .data = rk3328_dfi_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) #ifdef CONFIG_CPU_RK3368
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) { .compatible = "rockchip,rk3368-dfi", .data = rk3368_dfi_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) #ifdef CONFIG_CPU_RK3399
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) { .compatible = "rockchip,rk3399-dfi", .data = rockchip_dfi_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) #ifdef CONFIG_CPU_RK3568
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) { .compatible = "rockchip,rk3568-dfi", .data = px30_dfi_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) #ifdef CONFIG_CPU_RK3588
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) { .compatible = "rockchip,rk3588-dfi", .data = rk3588_dfi_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) #ifdef CONFIG_CPU_RV1126
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) { .compatible = "rockchip,rv1126-dfi", .data = px30_dfi_init },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) static int rockchip_dfi_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) struct rockchip_dfi *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct devfreq_event_desc *desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) int (*init)(struct platform_device *pdev, struct rockchip_dfi *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) struct devfreq_event_desc *desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (!desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) match = of_match_node(rockchip_dfi_id_match, pdev->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (match) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) init = match->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (init) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (init(pdev, data, desc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) desc->driver_data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) desc->name = np->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) data->edev = devm_devfreq_event_add_edev(dev, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (IS_ERR(data->edev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) dev_err(dev, "failed to add devfreq-event device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) return PTR_ERR(data->edev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) data->desc = desc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) data->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) platform_set_drvdata(pdev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) static struct platform_driver rockchip_dfi_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) .probe = rockchip_dfi_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) .name = "rockchip-dfi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) .of_match_table = rockchip_dfi_id_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) module_platform_driver(rockchip_dfi_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) MODULE_AUTHOR("Lin Huang <hl@rock-chips.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) MODULE_DESCRIPTION("Rockchip DFI driver");