On 22/05/2020 11:40, Roger Lu wrote: > > Hi Enric, > > On Tue, 2020-05-19 at 17:30 +0200, Enric Balletbo Serra wrote: >> Hi Roger, >> >> Thank you for your patch. I have the feeling that this driver is >> complex and difficult to follow and I am wondering if it wouldn't be >> better if you can send a version that simply adds basic functionality >> for now. Some comments below. > > Thanks for the advices. I'll submit SVS v9 with basic functionality > patch + step by step functionalities' patches. > >> >> Missatge de Roger Lu <roger.lu@xxxxxxxxxxxx> del dia dl., 18 de maig >> 2020 a les 11:25: >>> >>> The SVS (Smart Voltage Scaling) engine is a piece >>> of hardware which is used to calculate optimized >>> voltage values of several power domains, >>> e.g. CPU/GPU/CCI, according to chip process corner, >>> temperatures, and other factors. Then DVFS driver >>> could apply those optimized voltage values to reduce >>> power consumption. >>> >>> Signed-off-by: Roger Lu <roger.lu@xxxxxxxxxxxx> >>> --- >>> drivers/power/avs/Kconfig | 10 + >>> drivers/power/avs/Makefile | 1 + >>> drivers/power/avs/mtk_svs.c | 2119 +++++++++++++++++++++++++++++++++ >>> include/linux/power/mtk_svs.h | 23 + >>> 4 files changed, 2153 insertions(+) >>> create mode 100644 drivers/power/avs/mtk_svs.c >>> create mode 100644 include/linux/power/mtk_svs.h >>> >>> diff --git a/drivers/power/avs/Kconfig b/drivers/power/avs/Kconfig >>> index cdb4237bfd02..67089ac6040e 100644 >>> --- a/drivers/power/avs/Kconfig >>> +++ b/drivers/power/avs/Kconfig >>> @@ -35,3 +35,13 @@ config ROCKCHIP_IODOMAIN >>> Say y here to enable support io domains on Rockchip SoCs. It is >>> necessary for the io domain setting of the SoC to match the >>> voltage supplied by the regulators. >>> + >>> +config MTK_SVS >>> + bool "MediaTek Smart Voltage Scaling(SVS)" >> >> Can't be this a module? Why? In such case, you should use tristate option > > Generally, MTK_SVS is needed in MTK SoC(mt81xx) products. So, we don't provide > module option in config. If, somehow, SVS isn't needed, we suggest > CONFIG_MTK_SVS=n to be set. > The question here is if it needs to be probed before we probe the modules. If not, we should add a Kconfig option for MT81xx SoCs to select MTK_SVS. >> >>> + depends on POWER_AVS && MTK_EFUSE && NVMEM >>> + help >>> + The SVS engine is a piece of hardware which is used to calculate >>> + optimized voltage values of several power domains, e.g. >>> + CPU clusters/GPU/CCI, according to chip process corner, temperatures, >>> + and other factors. Then DVFS driver could apply those optimized voltage >>> + values to reduce power consumption. >>> diff --git a/drivers/power/avs/Makefile b/drivers/power/avs/Makefile >>> index 9007d05853e2..231adf078582 100644 >>> --- a/drivers/power/avs/Makefile >>> +++ b/drivers/power/avs/Makefile >>> @@ -2,3 +2,4 @@ >>> obj-$(CONFIG_POWER_AVS_OMAP) += smartreflex.o >>> obj-$(CONFIG_QCOM_CPR) += qcom-cpr.o >>> obj-$(CONFIG_ROCKCHIP_IODOMAIN) += rockchip-io-domain.o >>> +obj-$(CONFIG_MTK_SVS) += mtk_svs.o >> >> Will this driver be SoC specific or the idea is to support different >> SoCs? If the answer to the first question is yes, please name the file >> with the SoC prefix (i.e mt8183_svs). However, If the answer to the >> second question is yes, make sure you prefix common >> functions/structs/defines with a generic prefix mtk_svs but use the >> SoC prefix for the ones you expect will be different between SoC, i.e >> mt8183_svs_. This helps the readability of the driver. Also, try to >> avoid too generic names. > > MTK_SVS is designed for supporting different MTK SoCs.Therefore, the answer is second > question and thanks for the heads-up. > >> >>> diff --git a/drivers/power/avs/mtk_svs.c b/drivers/power/avs/mtk_svs.c >>> new file mode 100644 >>> index 000000000000..a4083b3ef175 >>> --- /dev/null >>> +++ b/drivers/power/avs/mtk_svs.c >>> @@ -0,0 +1,2119 @@ >>> +// SPDX-License-Identifier: GPL-2.0 >> >> I suspect you want this only GPLv2 compliant. Use GPL-2.0-only > > OK. I'll use GPL-2.0-only.Thanks. > >> >>> +/* >>> + * Copyright (C) 2020 MediaTek Inc. >>> + */ >>> + >>> +#define pr_fmt(fmt) "[mtk_svs] " fmt >> >> I don't see any reason to use pr_fmt in this driver. Use dev_* >> functions instead and remove the above. > > Ok. I will remove it. Thanks. > >> >>> + >>> +#include <linux/bits.h> >>> +#include <linux/clk.h> >>> +#include <linux/completion.h> >>> +#include <linux/init.h> >>> +#include <linux/interrupt.h> >>> +#include <linux/kernel.h> >>> +#include <linux/kthread.h> >>> +#include <linux/module.h> >>> +#include <linux/mutex.h> >>> +#include <linux/nvmem-consumer.h> >>> +#include <linux/of_address.h> >>> +#include <linux/of_irq.h> >>> +#include <linux/of_platform.h> >>> +#include <linux/platform_device.h> >>> +#include <linux/pm_domain.h> >>> +#include <linux/pm_opp.h> >>> +#include <linux/pm_qos.h> >>> +#include <linux/pm_runtime.h> >>> +#include <linux/power/mtk_svs.h> >>> +#include <linux/proc_fs.h> >>> +#include <linux/regulator/consumer.h> >>> +#include <linux/reset.h> >>> +#include <linux/seq_file.h> >>> +#include <linux/slab.h> >>> +#include <linux/spinlock.h> >>> +#include <linux/thermal.h> >>> +#include <linux/uaccess.h> >>> + >>> +/* svs 1-line sw id */ >>> +#define SVS_CPU_LITTLE BIT(0) >>> +#define SVS_CPU_BIG BIT(1) >>> +#define SVS_CCI BIT(2) >>> +#define SVS_GPU BIT(3) >>> + >>> +/* svs bank mode support */ >>> +#define SVSB_MODE_ALL_DISABLE (0) >> >> nit: SVS_BMODE_? > > Oh. If we add bank wording like SVS_Bxxx, it might cause some confusion when B combines > with other words. So, I'll keep SVSB for SVS Bank representation. > E.g: SVS_BDC_SIGNED_BIT might lead to be explained differently ("SVS bank + DC_SIGNED_BIT" or "SVS + BDC_SIGNED_BIT") > - "SVS bank + DC_SIGNED_BIT" is what we want for naming SVS_BDC_SIGNED_BIT but it might be misunderstood. > >> >>> +#define SVSB_MODE_INIT01 BIT(1) >>> +#define SVSB_MODE_INIT02 BIT(2) >>> +#define SVSB_MODE_MON BIT(3) >>> + >>> +/* svs bank init01 condition */ >>> +#define SVSB_INIT01_VOLT_IGNORE BIT(1) >>> +#define SVSB_INIT01_VOLT_INC_ONLY BIT(2) >>> + >>> +/* svs bank common setting */ >>> +#define HIGH_TEMP_MAX (U32_MAX) >> >> nit: SVS_* > > ok. I will add SVS or SVSB when it refers to SVS BANK. > >> >>> +#define RUNCONFIG_DEFAULT (0x80000000) >> >> Btw, there is any public datasheet where I can see those addresses and >> registers and bit fields? > > Excuse us, there is no public datasheet. We can reply it on patchwork. Thanks. > >> >>> +#define DC_SIGNED_BIT (0x8000) >>> +#define INTEN_INIT0x (0x00005f01) >>> +#define INTEN_MONVOPEN (0x00ff0000) >>> +#define SVSEN_OFF (0x0) >>> +#define SVSEN_MASK (0x7) >>> +#define SVSEN_INIT01 (0x1) >>> +#define SVSEN_INIT02 (0x5) >>> +#define SVSEN_MON (0x2) >>> +#define INTSTS_MONVOP (0x00ff0000) >>> +#define INTSTS_COMPLETE (0x1) >>> +#define INTSTS_CLEAN (0x00ffffff) >>> + >>> +#define proc_fops_rw(name) \ >>> + static int name ## _proc_open(struct inode *inode, \ >>> + struct file *file) \ >>> + { \ >>> + return single_open(file, name ## _proc_show, \ >>> + PDE_DATA(inode)); \ >>> + } \ >>> + static const struct proc_ops name ## _proc_fops = { \ >>> + .proc_open = name ## _proc_open, \ >>> + .proc_read = seq_read, \ >>> + .proc_lseek = seq_lseek, \ >>> + .proc_release = single_release, \ >>> + .proc_write = name ## _proc_write, \ >>> + } >>> + >>> +#define proc_fops_ro(name) \ >>> + static int name ## _proc_open(struct inode *inode, \ >>> + struct file *file) \ >>> + { \ >>> + return single_open(file, name ## _proc_show, \ >>> + PDE_DATA(inode)); \ >>> + } \ >>> + static const struct proc_ops name ## _proc_fops = { \ >>> + .proc_open = name ## _proc_open, \ >>> + .proc_read = seq_read, \ >>> + .proc_lseek = seq_lseek, \ >>> + .proc_release = single_release, \ >>> + } >>> + >>> +#define proc_entry(name) {__stringify(name), &name ## _proc_fops} >>> + >> >> /proc is usually the old way of exporting files to userspace, so >> unless you have a really good reason use sysfs instead, or even >> better, if it is only for debug purposes use debugfs. Also, you should >> document the entries in Documentation. > > Ok. I'll change it to debugfs and could you give us an example about entries in documentation? > We can follow them. Thanks. > >> >>> +static DEFINE_SPINLOCK(mtk_svs_lock); >>> +struct mtk_svs; >>> + >>> +enum svsb_phase { >> >> nit: mtk_svs_bphase? > > ditto > >> >>> + SVSB_PHASE_INIT01 = 0, >> >> nit: SVS_BPHASE_? > > ditto > >> >>> + SVSB_PHASE_INIT02, >>> + SVSB_PHASE_MON, >>> + SVSB_PHASE_ERROR, >>> +}; >>> + >>> +enum reg_index { >> >> nit: svs_reg_index? > > OK. Thanks. > >> >>> + TEMPMONCTL0 = 0, >>> + TEMPMONCTL1, >>> + TEMPMONCTL2, >>> + TEMPMONINT, >>> + TEMPMONINTSTS, >>> + TEMPMONIDET0, >>> + TEMPMONIDET1, >>> + TEMPMONIDET2, >>> + TEMPH2NTHRE, >>> + TEMPHTHRE, >>> + TEMPCTHRE, >>> + TEMPOFFSETH, >>> + TEMPOFFSETL, >>> + TEMPMSRCTL0, >>> + TEMPMSRCTL1, >>> + TEMPAHBPOLL, >>> + TEMPAHBTO, >>> + TEMPADCPNP0, >>> + TEMPADCPNP1, >>> + TEMPADCPNP2, >>> + TEMPADCMUX, >>> + TEMPADCEXT, >>> + TEMPADCEXT1, >>> + TEMPADCEN, >>> + TEMPPNPMUXADDR, >>> + TEMPADCMUXADDR, >>> + TEMPADCEXTADDR, >>> + TEMPADCEXT1ADDR, >>> + TEMPADCENADDR, >>> + TEMPADCVALIDADDR, >>> + TEMPADCVOLTADDR, >>> + TEMPRDCTRL, >>> + TEMPADCVALIDMASK, >>> + TEMPADCVOLTAGESHIFT, >>> + TEMPADCWRITECTRL, >>> + TEMPMSR0, >>> + TEMPMSR1, >>> + TEMPMSR2, >>> + TEMPADCHADDR, >>> + TEMPIMMD0, >>> + TEMPIMMD1, >>> + TEMPIMMD2, >>> + TEMPMONIDET3, >>> + TEMPADCPNP3, >>> + TEMPMSR3, >>> + TEMPIMMD3, >>> + TEMPPROTCTL, >>> + TEMPPROTTA, >>> + TEMPPROTTB, >>> + TEMPPROTTC, >>> + TEMPSPARE0, >>> + TEMPSPARE1, >>> + TEMPSPARE2, >>> + TEMPSPARE3, >>> + TEMPMSR0_1, >>> + TEMPMSR1_1, >>> + TEMPMSR2_1, >>> + TEMPMSR3_1, >>> + DESCHAR, >>> + TEMPCHAR, >>> + DETCHAR, >>> + AGECHAR, >>> + DCCONFIG, >>> + AGECONFIG, >>> + FREQPCT30, >>> + FREQPCT74, >>> + LIMITVALS, >>> + VBOOT, >>> + DETWINDOW, >>> + CONFIG, >>> + TSCALCS, >>> + RUNCONFIG, >>> + SVSEN, >>> + INIT2VALS, >>> + DCVALUES, >>> + AGEVALUES, >>> + VOP30, >>> + VOP74, >>> + TEMP, >>> + INTSTS, >>> + INTSTSRAW, >>> + INTEN, >>> + CHKINT, >>> + CHKSHIFT, >>> + STATUS, >>> + VDESIGN30, >>> + VDESIGN74, >>> + DVT30, >>> + DVT74, >>> + AGECOUNT, >>> + SMSTATE0, >>> + SMSTATE1, >>> + CTL0, >>> + DESDETSEC, >>> + TEMPAGESEC, >>> + CTRLSPARE0, >>> + CTRLSPARE1, >>> + CTRLSPARE2, >>> + CTRLSPARE3, >>> + CORESEL, >>> + THERMINTST, >>> + INTST, >>> + THSTAGE0ST, >>> + THSTAGE1ST, >>> + THSTAGE2ST, >>> + THAHBST0, >>> + THAHBST1, >>> + SPARE0, >>> + SPARE1, >>> + SPARE2, >>> + SPARE3, >>> + THSLPEVEB, >>> + reg_num, >>> +}; >>> + >>> +static const u32 svs_regs_v2[] = { >> >> Is this SoC specific or shared between SoCs? > > Shared between SoCs. Some SVS in MTK SoCs use v2 register map. > And which silicon uses v1 then? Is v2 a MediaTek internal naming you want to keep? >> >>> + [TEMPMONCTL0] = 0x000, >>> + [TEMPMONCTL1] = 0x004, >>> + [TEMPMONCTL2] = 0x008, >>> + [TEMPMONINT] = 0x00c, >>> + [TEMPMONINTSTS] = 0x010, >>> + [TEMPMONIDET0] = 0x014, >>> + [TEMPMONIDET1] = 0x018, >>> + [TEMPMONIDET2] = 0x01c, >>> + [TEMPH2NTHRE] = 0x024, >>> + [TEMPHTHRE] = 0x028, >>> + [TEMPCTHRE] = 0x02c, >>> + [TEMPOFFSETH] = 0x030, >>> + [TEMPOFFSETL] = 0x034, >>> + [TEMPMSRCTL0] = 0x038, >>> + [TEMPMSRCTL1] = 0x03c, >>> + [TEMPAHBPOLL] = 0x040, >>> + [TEMPAHBTO] = 0x044, >>> + [TEMPADCPNP0] = 0x048, >>> + [TEMPADCPNP1] = 0x04c, >>> + [TEMPADCPNP2] = 0x050, >>> + [TEMPADCMUX] = 0x054, >>> + [TEMPADCEXT] = 0x058, >>> + [TEMPADCEXT1] = 0x05c, >>> + [TEMPADCEN] = 0x060, >>> + [TEMPPNPMUXADDR] = 0x064, >>> + [TEMPADCMUXADDR] = 0x068, >>> + [TEMPADCEXTADDR] = 0x06c, >>> + [TEMPADCEXT1ADDR] = 0x070, >>> + [TEMPADCENADDR] = 0x074, >>> + [TEMPADCVALIDADDR] = 0x078, >>> + [TEMPADCVOLTADDR] = 0x07c, >>> + [TEMPRDCTRL] = 0x080, >>> + [TEMPADCVALIDMASK] = 0x084, >>> + [TEMPADCVOLTAGESHIFT] = 0x088, >>> + [TEMPADCWRITECTRL] = 0x08c, >>> + [TEMPMSR0] = 0x090, >>> + [TEMPMSR1] = 0x094, >>> + [TEMPMSR2] = 0x098, >>> + [TEMPADCHADDR] = 0x09c, >>> + [TEMPIMMD0] = 0x0a0, >>> + [TEMPIMMD1] = 0x0a4, >>> + [TEMPIMMD2] = 0x0a8, >>> + [TEMPMONIDET3] = 0x0b0, >>> + [TEMPADCPNP3] = 0x0b4, >>> + [TEMPMSR3] = 0x0b8, >>> + [TEMPIMMD3] = 0x0bc, >>> + [TEMPPROTCTL] = 0x0c0, >>> + [TEMPPROTTA] = 0x0c4, >>> + [TEMPPROTTB] = 0x0c8, >>> + [TEMPPROTTC] = 0x0cc, >>> + [TEMPSPARE0] = 0x0f0, >>> + [TEMPSPARE1] = 0x0f4, >>> + [TEMPSPARE2] = 0x0f8, >>> + [TEMPSPARE3] = 0x0fc, >>> + [TEMPMSR0_1] = 0x190, >>> + [TEMPMSR1_1] = 0x194, >>> + [TEMPMSR2_1] = 0x198, >>> + [TEMPMSR3_1] = 0x1b8, >>> + [DESCHAR] = 0xc00, >>> + [TEMPCHAR] = 0xc04, >>> + [DETCHAR] = 0xc08, >>> + [AGECHAR] = 0xc0c, >>> + [DCCONFIG] = 0xc10, >>> + [AGECONFIG] = 0xc14, >>> + [FREQPCT30] = 0xc18, >>> + [FREQPCT74] = 0xc1c, >>> + [LIMITVALS] = 0xc20, >>> + [VBOOT] = 0xc24, >>> + [DETWINDOW] = 0xc28, >>> + [CONFIG] = 0xc2c, >>> + [TSCALCS] = 0xc30, >>> + [RUNCONFIG] = 0xc34, >>> + [SVSEN] = 0xc38, >>> + [INIT2VALS] = 0xc3c, >>> + [DCVALUES] = 0xc40, >>> + [AGEVALUES] = 0xc44, >>> + [VOP30] = 0xc48, >>> + [VOP74] = 0xc4c, >>> + [TEMP] = 0xc50, >>> + [INTSTS] = 0xc54, >>> + [INTSTSRAW] = 0xc58, >>> + [INTEN] = 0xc5c, >>> + [CHKINT] = 0xc60, >>> + [CHKSHIFT] = 0xc64, >>> + [STATUS] = 0xc68, >>> + [VDESIGN30] = 0xc6c, >>> + [VDESIGN74] = 0xc70, >>> + [DVT30] = 0xc74, >>> + [DVT74] = 0xc78, >>> + [AGECOUNT] = 0xc7c, >>> + [SMSTATE0] = 0xc80, >>> + [SMSTATE1] = 0xc84, >>> + [CTL0] = 0xc88, >>> + [DESDETSEC] = 0xce0, >>> + [TEMPAGESEC] = 0xce4, >>> + [CTRLSPARE0] = 0xcf0, >>> + [CTRLSPARE1] = 0xcf4, >>> + [CTRLSPARE2] = 0xcf8, >>> + [CTRLSPARE3] = 0xcfc, >>> + [CORESEL] = 0xf00, >>> + [THERMINTST] = 0xf04, >>> + [INTST] = 0xf08, >>> + [THSTAGE0ST] = 0xf0c, >>> + [THSTAGE1ST] = 0xf10, >>> + [THSTAGE2ST] = 0xf14, >>> + [THAHBST0] = 0xf18, >>> + [THAHBST1] = 0xf1c, >>> + [SPARE0] = 0xf20, >>> + [SPARE1] = 0xf24, >>> + [SPARE2] = 0xf28, >>> + [SPARE3] = 0xf2c, >>> + [THSLPEVEB] = 0xf30, >>> +}; >>> + >>> +struct thermal_parameter { >> >> In general, not only in this struct, would be good have some >> documentation to have a better undestanding of the fields. That makes >> the job of the reviewer a bit easier. > > Ok. Could you share a documentation example to us? We'll share the > information as much as we can. Thanks a lot. > you should find that in all drivers, eg: https://elixir.bootlin.com/linux/latest/source/drivers/soc/mediatek/mtk-scpsys.c#L111 Regards, Matthias