^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2020, Rockchip Electronics Co., Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/nospec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/rockchip/rockchip_sip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <soc/rockchip/rockchip_sip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "rockchip_dmc_timing.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * DMCDBG share memory request 4KB for delivery parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define DMCDBG_PAGE_NUMS (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define DMCDBG_SHARE_MEM_SIZE ((DMCDBG_PAGE_NUMS) * 4096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define PROC_DMCDBG_DIR_NAME "dmcdbg"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define PROC_DMCDBG_DRAM_INFO "dmcinfo"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define PROC_DMCDBG_POWERSAVE "powersave"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define PROC_DMCDBG_DRVODT "drvodt"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define PROC_DMCDBG_DESKEW "deskew"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define PROC_DMCDBG_REGS_INFO "regsinfo"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define DDRDBG_FUNC_GET_VERSION (0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define DDRDBG_FUNC_GET_SUPPORTED (0x02)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define DDRDBG_FUNC_GET_DRAM_INFO (0x03)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define DDRDBG_FUNC_GET_DESKEW_INFO (0x04)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define DDRDBG_FUNC_UPDATE_DESKEW (0x05)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define DDRDBG_FUNC_DATA_TRAINING (0x06)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define DDRDBG_FUNC_UPDATE_DESKEW_TR (0x07)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define DDRDBG_FUNC_GET_POWERSAVE_INFO (0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define DDRDBG_FUNC_UPDATE_POWERSAVE (0x09)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define DDRDBG_FUNC_GET_DRVODT_INFO (0x0a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define DDRDBG_FUNC_UPDATE_DRVODT (0x0b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define DDRDBG_FUNC_GET_REGISTERS_INFO (0x0c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define DRV_ODT_UNKNOWN (0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define DRV_ODT_UNSUSPEND_FIX (0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define DRV_ODT_SUSPEND_FIX (0x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define REGS_NAME_LEN_MAX (20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define SKEW_GROUP_NUM_MAX (6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define SKEW_TIMING_NUM_MAX (50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct rockchip_dmcdbg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct proc_dir_entry *proc_dmcdbg_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct dram_cap_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned int rank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned int col;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned int bank;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned int buswidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned int die_buswidth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) unsigned int row_3_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) unsigned int cs0_row;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned int cs1_row;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) unsigned int cs0_high16bit_row;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) unsigned int cs1_high16bit_row;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) unsigned int bankgroup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct dram_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) unsigned int version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) char dramtype[10];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned int dramfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned int channel_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct dram_cap_info ch[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) static const char * const power_save_msg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) "auto power down enable",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) "auto power down idle cycle",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) "auto self refresh enable",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) "auto self refresh idle cycle",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) "self refresh with clock gate idle cycle",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) "self refresh and power down lite idle cycle",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) "standby idle cycle",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct power_save_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned int pd_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned int pd_idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned int sr_en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) unsigned int sr_idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) unsigned int sr_mc_gate_idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) unsigned int srpd_lite_idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) unsigned int standby_idle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static const char * const drv_odt_msg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) "dram side drv pull-up",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) "dram side drv pull-down",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) "dram side dq odt pull-up",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) "dram side dq odt pull-down",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) "dram side ca odt pull-up",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) "dram side ca odt pull-down",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) "soc side ca drv pull-up",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) "soc side ca drv pull-down",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) "soc side ck drv pull-up",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) "soc side ck drv pull-down",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) "soc side cs drv pull-up",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) "soc side cs drv pull-down",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) "soc side dq drv pull-up",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) "soc side dq drv pull-down",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) "soc side odt pull-up",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) "soc side odt pull-down",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) "phy vref inner",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) "phy vref out",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct drv_odt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) unsigned int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned int ohm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) unsigned int flag;
^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) struct drv_odt_vref {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) unsigned int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) unsigned int percen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) unsigned int flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct drv_odt_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct drv_odt dram_drv_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct drv_odt dram_drv_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct drv_odt dram_dq_odt_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct drv_odt dram_dq_odt_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) struct drv_odt dram_ca_odt_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) struct drv_odt dram_ca_odt_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct drv_odt phy_ca_drv_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct drv_odt phy_ca_drv_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct drv_odt phy_ck_drv_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct drv_odt phy_ck_drv_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct drv_odt phy_cs_drv_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct drv_odt phy_cs_drv_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct drv_odt phy_dq_drv_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct drv_odt phy_dq_drv_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct drv_odt phy_odt_up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) struct drv_odt phy_odt_down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct drv_odt_vref phy_vref_inner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct drv_odt_vref phy_vref_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct dmc_registers {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) char regs_name[REGS_NAME_LEN_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) unsigned int regs_addr;
^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) struct registers_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) unsigned int regs_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct dmc_registers regs[];
^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) struct skew_group {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned int skew_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) unsigned int *p_skew_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) char *p_skew_timing[SKEW_TIMING_NUM_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) char *note;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct rockchip_dmcdbg_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) unsigned int inited_flag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) void __iomem *share_memory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) unsigned int skew_group_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct skew_group skew_group[SKEW_GROUP_NUM_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static struct rockchip_dmcdbg_data dmcdbg_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct skew_info_rv1126 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) unsigned int ca_skew[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) unsigned int cs0_a_skew[44];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) unsigned int cs0_b_skew[44];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) unsigned int cs1_a_skew[44];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) unsigned int cs1_b_skew[44];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static int dmcinfo_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct dram_info *p_dram_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) struct file *fp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) char cur_freq[20] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) char governor[20] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) loff_t pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) res = sip_smc_dram(SHARE_PAGE_TYPE_DDRDBG, DDRDBG_FUNC_GET_DRAM_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) ROCKCHIP_SIP_CONFIG_DRAM_DEBUG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (res.a0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) seq_printf(m, "rockchip_sip_config_dram_debug error:%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (!dmcdbg_data.inited_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) seq_puts(m, "dmcdbg_data no int\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) p_dram_info = (struct dram_info *)dmcdbg_data.share_memory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* dram type information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) "DramType: %s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) p_dram_info->dramtype
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* dram capacity information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) "DramCapacity:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) for (i = 0; i < p_dram_info->channel_num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (p_dram_info->channel_num == 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) "Channel [%d]:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) i
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) "CS Count: %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) "Bus Width: %d bit\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) "Column: %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) "Bank: %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) "CS0_Row: %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) "CS1_Row: %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) "DieBusWidth: %d bit\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) "TotalSize: %d MB\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) p_dram_info->ch[i].rank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) p_dram_info->ch[i].buswidth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) p_dram_info->ch[i].col,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) p_dram_info->ch[i].bank,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) p_dram_info->ch[i].cs0_row,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) p_dram_info->ch[i].cs1_row,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) p_dram_info->ch[i].die_buswidth,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) p_dram_info->ch[i].size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* check devfreq/dmc device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) fp = filp_open("/sys/class/devfreq/dmc/cur_freq", O_RDONLY, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (IS_ERR(fp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) "devfreq/dmc: Disable\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) "DramFreq: %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) p_dram_info->dramfreq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) kernel_read(fp, cur_freq, sizeof(cur_freq), &pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) filp_close(fp, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) fp = filp_open("/sys/class/devfreq/dmc/governor", O_RDONLY, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (IS_ERR(fp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) fp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) kernel_read(fp, governor, sizeof(governor), &pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) filp_close(fp, NULL);
^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) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) "devfreq/dmc: Enable\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) "governor: %s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) "cur_freq: %s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) governor,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) cur_freq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) "NOTE:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) "more information about dmc can get from /sys/class/devfreq/dmc.\n"
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static int dmcinfo_proc_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return single_open(file, dmcinfo_proc_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static const struct file_operations dmcinfo_proc_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) .open = dmcinfo_proc_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) .release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static int proc_dmcinfo_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /* create dmcinfo file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) proc_create(PROC_DMCDBG_DRAM_INFO, 0644, proc_dmcdbg_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) &dmcinfo_proc_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static int powersave_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct power_save_info *p_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) unsigned int *p_uint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) unsigned int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /* get low power information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) res = sip_smc_dram(SHARE_PAGE_TYPE_DDRDBG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) DDRDBG_FUNC_GET_POWERSAVE_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) ROCKCHIP_SIP_CONFIG_DRAM_DEBUG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (res.a0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) seq_printf(m, "rockchip_sip_config_dram_debug error:%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (!dmcdbg_data.inited_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) seq_puts(m, "dmcdbg_data no int\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) p_power = (struct power_save_info *)dmcdbg_data.share_memory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) "low power information:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) "[number]name: value\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) p_uint = (unsigned int *)p_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) for (i = 0; i < ARRAY_SIZE(power_save_msg); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) "[%d]%s: %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) i, power_save_msg[i], *(p_uint + i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) "power save setting:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) "echo number=value > /proc/dmcdbg/powersave\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) "eg: set auto power down enable to 1\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) " echo 0=1 > /proc/dmcdbg/powersave\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) "Support for setting multiple parameters at the same time.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) "echo number=value,number=value,... > /proc/dmcdbg/powersave\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) "eg:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) " echo 0=1,1=32 > /proc/dmcdbg/powersave\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return 0;
^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) static int powersave_proc_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return single_open(file, powersave_proc_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) static ssize_t powersave_proc_write(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) const char __user *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct power_save_info *p_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) unsigned int *p_uint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) char *buf, *cookie_pot, *p_char;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) u32 loop, i, offset, value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) long long_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /* get buffer data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) buf = vzalloc(count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) cookie_pot = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!cookie_pot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (copy_from_user(cookie_pot, buffer, count)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* get power save setting information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) res = sip_smc_dram(SHARE_PAGE_TYPE_DDRDBG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) DDRDBG_FUNC_GET_POWERSAVE_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) ROCKCHIP_SIP_CONFIG_DRAM_DEBUG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (res.a0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) pr_err("rockchip_sip_config_dram_debug error:%lx\n", res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) goto err;
^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) if (!dmcdbg_data.inited_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) pr_err("dmcdbg_data no int\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) ret = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) p_power = (struct power_save_info *)dmcdbg_data.share_memory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) loop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (*(cookie_pot + i) == '=')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) loop++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) p_uint = (unsigned int *)p_power;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) for (i = 0; i < loop; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) p_char = strsep(&cookie_pot, "=");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) ret = kstrtol(p_char, 10, &long_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) offset = long_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (i == (loop - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) p_char = strsep(&cookie_pot, "\0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) p_char = strsep(&cookie_pot, ",");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) ret = kstrtol(p_char, 10, &long_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) value = long_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (offset >= ARRAY_SIZE(power_save_msg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) offset = array_index_nospec(offset, ARRAY_SIZE(power_save_msg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) *(p_uint + offset) = value;
^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) /* update power save setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) res = sip_smc_dram(SHARE_PAGE_TYPE_DDRDBG, DDRDBG_FUNC_UPDATE_POWERSAVE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ROCKCHIP_SIP_CONFIG_DRAM_DEBUG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (res.a0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) pr_err("rockchip_sip_config_dram_debug error:%lx\n", res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ret = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) vfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static const struct file_operations powersave_proc_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) .open = powersave_proc_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) .release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) .write = powersave_proc_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static int proc_powersave_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) /* create dmcinfo file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) proc_create(PROC_DMCDBG_POWERSAVE, 0644, proc_dmcdbg_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) &powersave_proc_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static int drvodt_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) struct drv_odt_info *p_drvodt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) unsigned int *p_uint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /* get drive strength and odt information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) res = sip_smc_dram(SHARE_PAGE_TYPE_DDRDBG, DDRDBG_FUNC_GET_DRVODT_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) ROCKCHIP_SIP_CONFIG_DRAM_DEBUG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (res.a0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) seq_printf(m, "rockchip_sip_config_dram_debug error:%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (!dmcdbg_data.inited_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) seq_puts(m, "dmcdbg_data no int\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) p_drvodt = (struct drv_odt_info *)dmcdbg_data.share_memory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) "drv and odt information:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) "[number]name: value (ohm)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) p_uint = (unsigned int *)p_drvodt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) for (i = 0; i < ARRAY_SIZE(drv_odt_msg); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (*(p_uint + (i * 3)) == DRV_ODT_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) "[%2d]%s: NULL (unknown) %c\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) i, drv_odt_msg[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) (*(p_uint + (i * 3) + 2) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) DRV_ODT_SUSPEND_FIX) ? '\0' : '*'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) else if (*(p_uint + (i * 3) + 1) == DRV_ODT_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) "[%2d]%s: %d (unknown) %c\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) i, drv_odt_msg[i], *(p_uint + (i * 3)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) (*(p_uint + (i * 3) + 2) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) DRV_ODT_SUSPEND_FIX) ? '\0' : '*'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) else if (i < (ARRAY_SIZE(drv_odt_msg) - 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) "[%2d]%s: %d (%d ohm) %c\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) i, drv_odt_msg[i], *(p_uint + (i * 3)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) *(p_uint + (i * 3) + 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) (*(p_uint + (i * 3) + 2) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) DRV_ODT_SUSPEND_FIX) ? '\0' : '*'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) "[%2d]%s: %d (%d %%) %c\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) i, drv_odt_msg[i], *(p_uint + (i * 3)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) *(p_uint + (i * 3) + 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) (*(p_uint + (i * 3) + 2) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) DRV_ODT_SUSPEND_FIX) ? '\0' : '*'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) "drvodt setting:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) "echo number=value > /proc/dmcdbg/drvodt\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) "eg: set soc side ca drv up to 20\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) " echo 6=20 > /proc/dmcdbg/drvodt\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) "Support for setting multiple parameters at the same time.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) "echo number=value,number=value,... > /proc/dmcdbg/drvodt\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) "eg: set soc side ca drv up and down to 20\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) " echo 6=20,7=20 > /proc/dmcdbg/drvodt\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) "Note: Please update both up and down at the same time.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) " (*) mean unsupported setting value\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) static int drvodt_proc_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) return single_open(file, drvodt_proc_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static ssize_t drvodt_proc_write(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) const char __user *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct drv_odt_info *p_drvodt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) unsigned int *p_uint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) char *buf, *cookie_pot, *p_char;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) u32 loop, i, offset, value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) long long_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) /* get buffer data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) buf = vzalloc(count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) cookie_pot = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if (!cookie_pot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (copy_from_user(cookie_pot, buffer, count)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) /* get drv and odt setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) res = sip_smc_dram(SHARE_PAGE_TYPE_DDRDBG, DDRDBG_FUNC_GET_DRVODT_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) ROCKCHIP_SIP_CONFIG_DRAM_DEBUG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (res.a0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) pr_err("rockchip_sip_config_dram_debug error:%lx\n", res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) if (!dmcdbg_data.inited_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) pr_err("dmcdbg_data no int\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) ret = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) p_drvodt = (struct drv_odt_info *)dmcdbg_data.share_memory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) loop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (*(cookie_pot + i) == '=')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) loop++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) p_uint = (unsigned int *)p_drvodt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) for (i = 0; i < loop; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) p_char = strsep(&cookie_pot, "=");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) ret = kstrtol(p_char, 10, &long_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) offset = long_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (i == (loop - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) p_char = strsep(&cookie_pot, "\0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) p_char = strsep(&cookie_pot, ",");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) ret = kstrtol(p_char, 10, &long_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) value = long_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (offset >= ARRAY_SIZE(drv_odt_msg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) offset *= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) offset = array_index_nospec(offset, ARRAY_SIZE(drv_odt_msg) * 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) *(p_uint + offset) = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) /* update power save setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) res = sip_smc_dram(SHARE_PAGE_TYPE_DDRDBG, DDRDBG_FUNC_UPDATE_DRVODT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) ROCKCHIP_SIP_CONFIG_DRAM_DEBUG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (res.a0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) pr_err("rockchip_sip_config_dram_debug error:%lx\n", res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) ret = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) vfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) static const struct file_operations drvodt_proc_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) .open = drvodt_proc_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) .release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) .write = drvodt_proc_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) static int proc_drvodt_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) /* create dmcinfo file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) proc_create(PROC_DMCDBG_DRVODT, 0644, proc_dmcdbg_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) &drvodt_proc_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) static int skew_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) unsigned int *p_uint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) u32 group, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) /* get deskew information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) res = sip_smc_dram(SHARE_PAGE_TYPE_DDRDBG, DDRDBG_FUNC_GET_DESKEW_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) ROCKCHIP_SIP_CONFIG_DRAM_DEBUG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) if (res.a0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) seq_printf(m, "rockchip_sip_config_dram_debug error:%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (!dmcdbg_data.inited_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) seq_puts(m, "dmcdbg_data no int\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) "de-skew information:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) "[group_number]name: value\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) for (group = 0; group < dmcdbg_data.skew_group_num; group++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (dmcdbg_data.skew_group[group].note != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) "%s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) dmcdbg_data.skew_group[group].note
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) p_uint = (unsigned int *)dmcdbg_data.skew_group[group].p_skew_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) for (i = 0; i < dmcdbg_data.skew_group[group].skew_num; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) "[%c%d_%d]%s: %d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) (i < 10) ? ' ' : '\0', group, i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) dmcdbg_data.skew_group[group].p_skew_timing[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) *(p_uint + i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) "de-skew setting:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) "echo group_number=value > /proc/dmcdbg/deskew\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) "eg: set a1_ddr3a14_de-skew to 8\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) " echo 0_1=8 > /proc/dmcdbg/deskew\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) "Support for setting multiple parameters simultaneously.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) "echo group_number=value,group_number=value,... > /proc/dmcdbg/deskew\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) "eg:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) " echo 0_1=8,1_2=8 > /proc/dmcdbg/deskew\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) static int skew_proc_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return single_open(file, skew_proc_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) static ssize_t skew_proc_write(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) const char __user *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) unsigned int *p_uint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) char *buf, *cookie_pot, *p_char;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) u32 loop, i, offset_max, group, offset, value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) long long_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) /* get buffer data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) buf = vzalloc(count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) cookie_pot = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (!cookie_pot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (copy_from_user(cookie_pot, buffer, count)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) ret = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /* get skew setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) res = sip_smc_dram(SHARE_PAGE_TYPE_DDRDBG, DDRDBG_FUNC_GET_DESKEW_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) ROCKCHIP_SIP_CONFIG_DRAM_DEBUG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (res.a0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) pr_err("rockchip_sip_config_dram_debug error:%lx\n", res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (!dmcdbg_data.inited_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) pr_err("dmcdbg_data no int\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) ret = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) loop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (*(cookie_pot + i) == '=')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) loop++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) for (i = 0; i < loop; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) p_char = strsep(&cookie_pot, "_");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) ret = kstrtol(p_char, 10, &long_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) group = long_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) p_char = strsep(&cookie_pot, "=");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) ret = kstrtol(p_char, 10, &long_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) offset = long_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (i == (loop - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) p_char = strsep(&cookie_pot, "\0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) p_char = strsep(&cookie_pot, ",");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) ret = kstrtol(p_char, 10, &long_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) value = long_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (group >= dmcdbg_data.skew_group_num) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) group = array_index_nospec(group, dmcdbg_data.skew_group_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) p_uint = (unsigned int *)dmcdbg_data.skew_group[group].p_skew_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) offset_max = dmcdbg_data.skew_group[group].skew_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (offset >= offset_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) offset = array_index_nospec(offset, offset_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) *(p_uint + offset) = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) /* update power save setting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) res = sip_smc_dram(SHARE_PAGE_TYPE_DDRDBG, DDRDBG_FUNC_UPDATE_DESKEW,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) ROCKCHIP_SIP_CONFIG_DRAM_DEBUG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (res.a0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) pr_err("rockchip_sip_config_dram_debug error:%lx\n", res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) ret = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) vfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static const struct file_operations skew_proc_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) .open = skew_proc_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) .release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) .write = skew_proc_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) static int proc_skew_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) /* create dmcinfo file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) proc_create(PROC_DMCDBG_DESKEW, 0644, proc_dmcdbg_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) &skew_proc_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) static int regsinfo_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) struct registers_info *p_regsinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) res = sip_smc_dram(SHARE_PAGE_TYPE_DDRDBG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) DDRDBG_FUNC_GET_REGISTERS_INFO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) ROCKCHIP_SIP_CONFIG_DRAM_DEBUG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (res.a0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) seq_printf(m, "rockchip_sip_config_dram_debug error:%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) res.a0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) if (!dmcdbg_data.inited_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) seq_puts(m, "dmcdbg_data no int\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) p_regsinfo = (struct registers_info *)dmcdbg_data.share_memory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) "registers base address information:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) "\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) for (i = 0; i < p_regsinfo->regs_num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) "%s=0x%x\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) p_regsinfo->regs[i].regs_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) p_regsinfo->regs[i].regs_addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) static int regsinfo_proc_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) return single_open(file, regsinfo_proc_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) static const struct file_operations regsinfo_proc_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) .open = regsinfo_proc_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) .read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) .llseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) .release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) static int proc_regsinfo_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) /* create dmcinfo file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) proc_create(PROC_DMCDBG_REGS_INFO, 0644, proc_dmcdbg_dir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) ®sinfo_proc_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) static void rv1126_get_skew_parameter(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) struct skew_info_rv1126 *p_skew;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) u32 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /* get skew parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) p_skew = (struct skew_info_rv1126 *)dmcdbg_data.share_memory;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) dmcdbg_data.skew_group_num = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) /* ca_skew parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) dmcdbg_data.skew_group[0].p_skew_info = (unsigned int *)p_skew->ca_skew;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) dmcdbg_data.skew_group[0].skew_num = ARRAY_SIZE(rv1126_dts_ca_timing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) for (i = 0; i < dmcdbg_data.skew_group[0].skew_num; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) dmcdbg_data.skew_group[0].p_skew_timing[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) (char *)rv1126_dts_ca_timing[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) dmcdbg_data.skew_group[0].note =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) "(ca_skew: ddr4(pad_name)_ddr3_lpddr3_lpddr4_de-skew)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) /* cs0_a_skew parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) dmcdbg_data.skew_group[1].p_skew_info = (unsigned int *)p_skew->cs0_a_skew;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) dmcdbg_data.skew_group[1].skew_num = ARRAY_SIZE(rv1126_dts_cs0_a_timing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) for (i = 0; i < dmcdbg_data.skew_group[1].skew_num; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) dmcdbg_data.skew_group[1].p_skew_timing[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) (char *)rv1126_dts_cs0_a_timing[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) dmcdbg_data.skew_group[1].note = "(cs0_a_skew)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) /* cs0_b_skew parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) dmcdbg_data.skew_group[2].p_skew_info = (unsigned int *)p_skew->cs0_b_skew;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) dmcdbg_data.skew_group[2].skew_num = ARRAY_SIZE(rv1126_dts_cs0_b_timing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) for (i = 0; i < dmcdbg_data.skew_group[2].skew_num; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) dmcdbg_data.skew_group[2].p_skew_timing[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) (char *)rv1126_dts_cs0_b_timing[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) dmcdbg_data.skew_group[2].note = "(cs0_b_skew)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) /* cs1_a_skew parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) dmcdbg_data.skew_group[3].p_skew_info = (unsigned int *)p_skew->cs1_a_skew;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) dmcdbg_data.skew_group[3].skew_num = ARRAY_SIZE(rv1126_dts_cs1_a_timing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) for (i = 0; i < dmcdbg_data.skew_group[3].skew_num; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) dmcdbg_data.skew_group[3].p_skew_timing[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) (char *)rv1126_dts_cs1_a_timing[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) dmcdbg_data.skew_group[3].note = "(cs1_a_skew)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) /* cs1_b_skew parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) dmcdbg_data.skew_group[4].p_skew_info = (unsigned int *)p_skew->cs1_b_skew;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) dmcdbg_data.skew_group[4].skew_num = ARRAY_SIZE(rv1126_dts_cs1_b_timing);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) for (i = 0; i < dmcdbg_data.skew_group[3].skew_num; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) dmcdbg_data.skew_group[4].p_skew_timing[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) (char *)rv1126_dts_cs1_b_timing[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) dmcdbg_data.skew_group[4].note = "(cs1_b_skew)";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) static __maybe_unused int rv1126_dmcdbg_init(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) struct rockchip_dmcdbg *dmcdbg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) struct arm_smccc_res res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) /* check ddr_debug_func version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) res = sip_smc_dram(0, DDRDBG_FUNC_GET_VERSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) ROCKCHIP_SIP_CONFIG_DRAM_DEBUG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) dev_notice(&pdev->dev, "current ATF ddr_debug_func version 0x%lx.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) res.a1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) * [15:8] major version, [7:0] minor version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) * major version must match both kernel dmcdbg and ATF ddr_debug_func.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (res.a0 || res.a1 < 0x101 || ((res.a1 & 0xff00) != 0x100)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) "version invalid,need update,the major version unmatch!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /* request share memory for pass parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) res = sip_smc_request_share_mem(DMCDBG_PAGE_NUMS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) SHARE_PAGE_TYPE_DDRDBG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (res.a0 != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) dev_err(&pdev->dev, "request share mem error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) dmcdbg_data.share_memory = (void __iomem *)res.a1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) dmcdbg_data.inited_flag = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) rv1126_get_skew_parameter();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) /* create parent dir in /proc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) proc_dmcdbg_dir = proc_mkdir(PROC_DMCDBG_DIR_NAME, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (!proc_dmcdbg_dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) dev_err(&pdev->dev, "create proc dir error!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) proc_dmcinfo_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) proc_powersave_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) proc_drvodt_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) proc_skew_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) proc_regsinfo_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) static const struct of_device_id rockchip_dmcdbg_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) { .compatible = "rockchip,rv1126-dmcdbg", .data = rv1126_dmcdbg_init},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) MODULE_DEVICE_TABLE(of, rockchip_dmcdbg_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) static int rockchip_dmcdbg_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) struct rockchip_dmcdbg *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) int (*init)(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) struct rockchip_dmcdbg *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) data = devm_kzalloc(dev, sizeof(struct rockchip_dmcdbg), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) data->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) /* match soc chip init */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) match = of_match_node(rockchip_dmcdbg_of_match, pdev->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (match) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) init = match->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (init) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) if (init(pdev, data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) static struct platform_driver rockchip_dmcdbg_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) .probe = rockchip_dmcdbg_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) .name = "rockchip,dmcdbg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) .of_match_table = rockchip_dmcdbg_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) module_platform_driver(rockchip_dmcdbg_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) MODULE_AUTHOR("YouMin Chen <cym@rock-chips.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) MODULE_DESCRIPTION("rockchip dmc debug driver with devfreq framework");