| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * google_bcl_sysfs.c Google bcl sysfs driver |
| * |
| * Copyright (c) 2022, Google LLC. All rights reserved. |
| * |
| */ |
| |
| #define pr_fmt(fmt) "%s:%s " fmt, KBUILD_MODNAME, __func__ |
| |
| #include <linux/module.h> |
| #include <linux/workqueue.h> |
| #include <linux/gpio.h> |
| #include <linux/kernel.h> |
| #include <linux/io.h> |
| #include <linux/err.h> |
| #include <linux/mutex.h> |
| #include <linux/power_supply.h> |
| #include <linux/platform_device.h> |
| #include <linux/regmap.h> |
| #include "bcl.h" |
| #include <linux/regulator/pmic_class.h> |
| #if IS_ENABLED(CONFIG_REGULATOR_S2MPG14) |
| #include <dt-bindings/interrupt-controller/zuma.h> |
| #include <linux/mfd/samsung/s2mpg14-register.h> |
| #include <linux/mfd/samsung/s2mpg15-register.h> |
| #include <max77779_regs.h> |
| #elif IS_ENABLED(CONFIG_REGULATOR_S2MPG12) |
| #include <dt-bindings/interrupt-controller/gs201.h> |
| #include <linux/mfd/samsung/s2mpg12-register.h> |
| #include <linux/mfd/samsung/s2mpg13-register.h> |
| #elif IS_ENABLED(CONFIG_REGULATOR_S2MPG10) |
| #include <dt-bindings/interrupt-controller/gs101.h> |
| #include <linux/mfd/samsung/s2mpg10-register.h> |
| #include <linux/mfd/samsung/s2mpg11-register.h> |
| #endif |
| #include <max77759_regs.h> |
| #include <max77779.h> |
| #include <max777x9_bcl.h> |
| |
| const unsigned int clk_stats_offset[] = { |
| CPUCL0_CLKDIVSTEP_STAT, |
| CLKDIVSTEP_STAT, |
| CLKDIVSTEP_STAT, |
| TPU_CLKDIVSTEP_STAT, |
| G3D_CLKDIVSTEP_STAT, |
| AUR_CLKDIVSTEP_STAT, |
| }; |
| |
| static const char * const batt_irq_names[] = { |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| "uvlo1", "uvlo2", "batoilo", "batoilo2" |
| #else |
| "uvlo1", "uvlo2", "batoilo" |
| #endif |
| }; |
| |
| static const char * const concurrent_pwrwarn_irq_names[] = { |
| "none", "mmwave", "rffe" |
| }; |
| |
| static ssize_t safe_emit_bcl_cnt(char* buf, struct bcl_zone * zone) { |
| if (!zone) |
| return sysfs_emit(buf, "0\n"); |
| else |
| return sysfs_emit(buf, "%d\n", atomic_read(&zone->bcl_cnt)); |
| } |
| |
| static ssize_t safe_emit_bcl_capacity(char* buf, struct bcl_zone * zone) { |
| if (!zone) |
| return sysfs_emit(buf, "0\n"); |
| else |
| return sysfs_emit(buf, "%d\n", zone->bcl_stats.capacity); |
| } |
| |
| static ssize_t safe_emit_bcl_voltage(char* buf, struct bcl_zone * zone) { |
| if (!zone) |
| return sysfs_emit(buf, "0\n"); |
| else |
| return sysfs_emit(buf, "%d\n", zone->bcl_stats.voltage); |
| } |
| |
| static ssize_t safe_emit_bcl_time(char* buf, struct bcl_zone * zone) { |
| if (!zone) |
| return sysfs_emit(buf, "0\n"); |
| else |
| return sysfs_emit(buf, "%lld\n", zone->bcl_stats._time); |
| } |
| |
| static ssize_t batoilo_count_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_cnt(buf, bcl_dev->zone[BATOILO1]); |
| } |
| |
| static DEVICE_ATTR_RO(batoilo_count); |
| |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| static ssize_t batoilo2_count_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_cnt(buf, bcl_dev->zone[BATOILO2]); |
| } |
| |
| static DEVICE_ATTR_RO(batoilo2_count); |
| #endif |
| |
| static ssize_t vdroop2_count_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_cnt(buf, bcl_dev->zone[UVLO2]); |
| } |
| |
| static DEVICE_ATTR_RO(vdroop2_count); |
| |
| static ssize_t vdroop1_count_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_cnt(buf, bcl_dev->zone[UVLO1]); |
| } |
| |
| static DEVICE_ATTR_RO(vdroop1_count); |
| |
| static ssize_t smpl_warn_count_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_cnt(buf, bcl_dev->zone[SMPL_WARN]); |
| } |
| |
| static DEVICE_ATTR_RO(smpl_warn_count); |
| |
| static ssize_t ocp_cpu1_count_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_cnt(buf, bcl_dev->zone[OCP_WARN_CPUCL1]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_cpu1_count); |
| |
| static ssize_t ocp_cpu2_count_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_cnt(buf, bcl_dev->zone[OCP_WARN_CPUCL2]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_cpu2_count); |
| |
| static ssize_t ocp_tpu_count_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_cnt(buf, bcl_dev->zone[OCP_WARN_TPU]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_tpu_count); |
| |
| static ssize_t ocp_gpu_count_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_cnt(buf, bcl_dev->zone[OCP_WARN_GPU]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_gpu_count); |
| |
| static ssize_t soft_ocp_cpu1_count_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_cnt(buf, bcl_dev->zone[SOFT_OCP_WARN_CPUCL1]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_cpu1_count); |
| |
| static ssize_t soft_ocp_cpu2_count_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_cnt(buf, bcl_dev->zone[SOFT_OCP_WARN_CPUCL2]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_cpu2_count); |
| |
| static ssize_t soft_ocp_tpu_count_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_cnt(buf, bcl_dev->zone[SOFT_OCP_WARN_TPU]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_tpu_count); |
| |
| static ssize_t soft_ocp_gpu_count_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_cnt(buf, bcl_dev->zone[SOFT_OCP_WARN_GPU]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_gpu_count); |
| |
| static ssize_t batoilo_cap_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_capacity(buf, bcl_dev->zone[BATOILO1]); |
| } |
| |
| static DEVICE_ATTR_RO(batoilo_cap); |
| |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| static ssize_t batoilo2_cap_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_capacity(buf, bcl_dev->zone[BATOILO2]); |
| } |
| |
| static DEVICE_ATTR_RO(batoilo2_cap); |
| #endif |
| |
| static ssize_t vdroop2_cap_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_capacity(buf, bcl_dev->zone[UVLO2]); |
| } |
| |
| static DEVICE_ATTR_RO(vdroop2_cap); |
| |
| static ssize_t vdroop1_cap_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_capacity(buf, bcl_dev->zone[UVLO1]); |
| } |
| |
| static DEVICE_ATTR_RO(vdroop1_cap); |
| |
| static ssize_t smpl_warn_cap_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_capacity(buf, bcl_dev->zone[SMPL_WARN]); |
| } |
| |
| static DEVICE_ATTR_RO(smpl_warn_cap); |
| |
| static ssize_t ocp_cpu1_cap_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_capacity(buf, bcl_dev->zone[OCP_WARN_CPUCL1]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_cpu1_cap); |
| |
| static ssize_t ocp_cpu2_cap_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_capacity(buf, bcl_dev->zone[OCP_WARN_CPUCL2]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_cpu2_cap); |
| |
| static ssize_t ocp_tpu_cap_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_capacity(buf, bcl_dev->zone[OCP_WARN_TPU]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_tpu_cap); |
| |
| static ssize_t ocp_gpu_cap_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_capacity(buf, bcl_dev->zone[OCP_WARN_GPU]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_gpu_cap); |
| |
| static ssize_t soft_ocp_cpu1_cap_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_capacity(buf, bcl_dev->zone[OCP_WARN_CPUCL1]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_cpu1_cap); |
| |
| static ssize_t soft_ocp_cpu2_cap_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_capacity(buf, bcl_dev->zone[SOFT_OCP_WARN_CPUCL2]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_cpu2_cap); |
| |
| static ssize_t soft_ocp_tpu_cap_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_capacity(buf, bcl_dev->zone[SOFT_OCP_WARN_TPU]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_tpu_cap); |
| |
| static ssize_t soft_ocp_gpu_cap_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_capacity(buf, bcl_dev->zone[SOFT_OCP_WARN_GPU]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_gpu_cap); |
| |
| static ssize_t batoilo_volt_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_voltage(buf, bcl_dev->zone[BATOILO1]); |
| } |
| |
| static DEVICE_ATTR_RO(batoilo_volt); |
| |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| static ssize_t batoilo2_volt_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_voltage(buf, bcl_dev->zone[BATOILO2]); |
| } |
| |
| static DEVICE_ATTR_RO(batoilo2_volt); |
| #endif |
| |
| static ssize_t vdroop2_volt_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_voltage(buf, bcl_dev->zone[UVLO2]); |
| } |
| |
| static DEVICE_ATTR_RO(vdroop2_volt); |
| |
| static ssize_t vdroop1_volt_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_voltage(buf, bcl_dev->zone[UVLO1]); |
| } |
| |
| static DEVICE_ATTR_RO(vdroop1_volt); |
| |
| static ssize_t smpl_warn_volt_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_voltage(buf, bcl_dev->zone[SMPL_WARN]); |
| } |
| |
| static DEVICE_ATTR_RO(smpl_warn_volt); |
| |
| static ssize_t ocp_cpu1_volt_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_voltage(buf, bcl_dev->zone[OCP_WARN_CPUCL1]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_cpu1_volt); |
| |
| static ssize_t ocp_cpu2_volt_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_voltage(buf, bcl_dev->zone[OCP_WARN_CPUCL2]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_cpu2_volt); |
| |
| static ssize_t ocp_tpu_volt_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_voltage(buf, bcl_dev->zone[OCP_WARN_TPU]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_tpu_volt); |
| |
| static ssize_t ocp_gpu_volt_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_voltage(buf, bcl_dev->zone[OCP_WARN_GPU]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_gpu_volt); |
| |
| static ssize_t soft_ocp_cpu1_volt_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_voltage(buf, bcl_dev->zone[SOFT_OCP_WARN_CPUCL1]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_cpu1_volt); |
| |
| static ssize_t soft_ocp_cpu2_volt_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_voltage(buf, bcl_dev->zone[SOFT_OCP_WARN_CPUCL2]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_cpu2_volt); |
| |
| static ssize_t soft_ocp_tpu_volt_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_voltage(buf, bcl_dev->zone[SOFT_OCP_WARN_TPU]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_tpu_volt); |
| |
| static ssize_t soft_ocp_gpu_volt_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_voltage(buf, bcl_dev->zone[SOFT_OCP_WARN_GPU]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_gpu_volt); |
| |
| static ssize_t batoilo_time_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_time(buf, bcl_dev->zone[BATOILO1]); |
| } |
| |
| static DEVICE_ATTR_RO(batoilo_time); |
| |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| static ssize_t batoilo2_time_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_time(buf, bcl_dev->zone[BATOILO2]); |
| } |
| |
| static DEVICE_ATTR_RO(batoilo2_time); |
| #endif |
| |
| static ssize_t vdroop2_time_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_time(buf, bcl_dev->zone[UVLO2]); |
| } |
| |
| static DEVICE_ATTR_RO(vdroop2_time); |
| |
| static ssize_t vdroop1_time_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_time(buf, bcl_dev->zone[UVLO1]); |
| } |
| |
| static DEVICE_ATTR_RO(vdroop1_time); |
| |
| static ssize_t smpl_warn_time_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_time(buf, bcl_dev->zone[SMPL_WARN]); |
| } |
| |
| static DEVICE_ATTR_RO(smpl_warn_time); |
| |
| static ssize_t ocp_cpu1_time_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_time(buf, bcl_dev->zone[OCP_WARN_CPUCL1]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_cpu1_time); |
| |
| static ssize_t ocp_cpu2_time_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_time(buf, bcl_dev->zone[OCP_WARN_CPUCL2]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_cpu2_time); |
| |
| static ssize_t ocp_tpu_time_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_time(buf, bcl_dev->zone[OCP_WARN_TPU]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_tpu_time); |
| |
| static ssize_t ocp_gpu_time_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_time(buf, bcl_dev->zone[OCP_WARN_GPU]); |
| } |
| |
| static DEVICE_ATTR_RO(ocp_gpu_time); |
| |
| static ssize_t soft_ocp_cpu1_time_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_time(buf, bcl_dev->zone[SOFT_OCP_WARN_CPUCL1]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_cpu1_time); |
| |
| static ssize_t soft_ocp_cpu2_time_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_time(buf, bcl_dev->zone[SOFT_OCP_WARN_CPUCL2]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_cpu2_time); |
| |
| static ssize_t soft_ocp_tpu_time_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_time(buf, bcl_dev->zone[SOFT_OCP_WARN_TPU]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_tpu_time); |
| |
| static ssize_t soft_ocp_gpu_time_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| return safe_emit_bcl_time(buf, bcl_dev->zone[SOFT_OCP_WARN_GPU]); |
| } |
| |
| static DEVICE_ATTR_RO(soft_ocp_gpu_time); |
| |
| static ssize_t db_settings_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size, enum MPMM_SOURCE src) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| int value; |
| |
| if (kstrtouint(buf, 16, &value) < 0) |
| return -EINVAL; |
| |
| if (src != BIG && src != MID) |
| return -EINVAL; |
| |
| google_set_db(bcl_dev, value, src); |
| |
| return size; |
| } |
| |
| static ssize_t db_settings_show(struct device *dev, struct device_attribute *attr, |
| char *buf, enum MPMM_SOURCE src) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if ((!bcl_dev->sysreg_cpucl0) || (src == LITTLE) || (src == MPMMEN)) |
| return -EIO; |
| |
| return sysfs_emit(buf, "%#x\n", google_get_db(bcl_dev, src)); |
| } |
| |
| static ssize_t mid_db_settings_store(struct device *dev, |
| struct device_attribute *attr, const char *buf, size_t size) |
| { |
| return db_settings_store(dev, attr, buf, size, MID); |
| } |
| |
| static ssize_t mid_db_settings_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| return db_settings_show(dev, attr, buf, MID); |
| } |
| |
| static DEVICE_ATTR_RW(mid_db_settings); |
| |
| static ssize_t big_db_settings_store(struct device *dev, |
| struct device_attribute *attr, const char *buf, size_t size) |
| { |
| return db_settings_store(dev, attr, buf, size, BIG); |
| } |
| |
| static ssize_t big_db_settings_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| return db_settings_show(dev, attr, buf, BIG); |
| } |
| |
| static DEVICE_ATTR_RW(big_db_settings); |
| |
| static ssize_t enable_mitigation_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%d\n", READ_ONCE(bcl_dev->enabled)); |
| } |
| |
| static ssize_t enable_mitigation_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret, i; |
| unsigned int reg; |
| |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| |
| if (smp_load_acquire(&bcl_dev->enabled) == value) |
| return size; |
| |
| /* Kernel filesystem serializes sysfs store callbacks */ |
| smp_store_release(&bcl_dev->enabled, value); |
| if (value) { |
| bcl_dev->core_conf[SUBSYSTEM_TPU].clkdivstep |= 0x1; |
| bcl_dev->core_conf[SUBSYSTEM_GPU].clkdivstep |= 0x1; |
| bcl_dev->core_conf[SUBSYSTEM_AUR].clkdivstep |= 0x1; |
| |
| for (i = SUBSYSTEM_CPU0; i <= SUBSYSTEM_CPU2; i++) { |
| ret = cpu_buff_read(bcl_dev, i, CPU_BUFF_CLKDIVSTEP, ®); |
| if (ret < 0) |
| return ret; |
| |
| ret = cpu_buff_write(bcl_dev, i, CPU_BUFF_CLKDIVSTEP, reg | 0x1); |
| if (ret < 0) |
| return ret; |
| } |
| for (i = 0; i < TRIGGERED_SOURCE_MAX; i++) |
| if (bcl_dev->zone[i] && i != BATOILO) |
| enable_irq(bcl_dev->zone[i]->bcl_irq); |
| } else { |
| bcl_dev->core_conf[SUBSYSTEM_TPU].clkdivstep &= ~(1 << 0); |
| bcl_dev->core_conf[SUBSYSTEM_GPU].clkdivstep &= ~(1 << 0); |
| bcl_dev->core_conf[SUBSYSTEM_AUR].clkdivstep &= ~(1 << 0); |
| |
| for (i = SUBSYSTEM_CPU0; i <= SUBSYSTEM_CPU2; i++) { |
| ret = cpu_buff_read(bcl_dev, i, CPU_BUFF_CLKDIVSTEP, ®); |
| if (ret < 0) |
| return ret; |
| |
| ret = cpu_buff_write(bcl_dev, i, CPU_BUFF_CLKDIVSTEP, reg & ~(1 << 0)); |
| if (ret < 0) |
| return ret; |
| } |
| for (i = 0; i < TRIGGERED_SOURCE_MAX; i++) |
| if (bcl_dev->zone[i] && i != BATOILO) |
| disable_irq(bcl_dev->zone[i]->bcl_irq); |
| } |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(enable_mitigation); |
| |
| static ssize_t enable_rffe_mitigation_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%d\n", bcl_dev->rffe_mitigation_enable); |
| } |
| |
| static ssize_t enable_rffe_mitigation_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| |
| if (bcl_dev->rffe_mitigation_enable == value) |
| return size; |
| |
| bcl_dev->rffe_mitigation_enable = value; |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(enable_rffe_mitigation); |
| |
| static ssize_t main_offsrc1_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%#x\n", bcl_dev->main_offsrc1); |
| } |
| |
| static DEVICE_ATTR_RO(main_offsrc1); |
| |
| static ssize_t main_offsrc2_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%#x\n", bcl_dev->main_offsrc2); |
| } |
| |
| static DEVICE_ATTR_RO(main_offsrc2); |
| |
| static ssize_t sub_offsrc1_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%#x\n", bcl_dev->sub_offsrc1); |
| } |
| |
| static DEVICE_ATTR_RO(sub_offsrc1); |
| |
| static ssize_t sub_offsrc2_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%#x\n", bcl_dev->sub_offsrc2); |
| } |
| |
| static DEVICE_ATTR_RO(sub_offsrc2); |
| |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| static ssize_t evt_cnt_uvlo1_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%i\n", bcl_dev->evt_cnt.uvlo1); |
| } |
| |
| static DEVICE_ATTR_RO(evt_cnt_uvlo1); |
| |
| static ssize_t evt_cnt_uvlo2_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%i\n", bcl_dev->evt_cnt.uvlo2); |
| } |
| |
| static DEVICE_ATTR_RO(evt_cnt_uvlo2); |
| |
| static ssize_t evt_cnt_batoilo1_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%i\n", bcl_dev->evt_cnt.batoilo1); |
| } |
| |
| static DEVICE_ATTR_RO(evt_cnt_batoilo1); |
| |
| static ssize_t evt_cnt_batoilo2_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%i\n", bcl_dev->evt_cnt.batoilo2); |
| } |
| |
| static DEVICE_ATTR_RO(evt_cnt_batoilo2); |
| |
| static ssize_t evt_cnt_latest_uvlo1_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%i\n", bcl_dev->evt_cnt_latest.uvlo1); |
| } |
| |
| static DEVICE_ATTR_RO(evt_cnt_latest_uvlo1); |
| |
| static ssize_t evt_cnt_latest_uvlo2_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%i\n", bcl_dev->evt_cnt_latest.uvlo2); |
| } |
| |
| static DEVICE_ATTR_RO(evt_cnt_latest_uvlo2); |
| |
| static ssize_t evt_cnt_latest_batoilo1_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%i\n", bcl_dev->evt_cnt_latest.batoilo1); |
| } |
| |
| static DEVICE_ATTR_RO(evt_cnt_latest_batoilo1); |
| |
| static ssize_t evt_cnt_latest_batoilo2_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%i\n", bcl_dev->evt_cnt_latest.batoilo2); |
| } |
| |
| static DEVICE_ATTR_RO(evt_cnt_latest_batoilo2); |
| #endif |
| |
| static ssize_t pwronsrc_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%#x\n", bcl_dev->pwronsrc); |
| } |
| |
| static DEVICE_ATTR_RO(pwronsrc); |
| |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| static ssize_t last_current_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (bcl_dev->ifpmic != MAX77779) |
| return -ENODEV; |
| |
| return sysfs_emit(buf, "%#x\n", bcl_dev->last_current); |
| } |
| static DEVICE_ATTR_RO(last_current); |
| |
| static ssize_t vimon_buff_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| int idx, ret; |
| uint16_t rdback; |
| ssize_t count = 0; |
| |
| if (bcl_dev->ifpmic != MAX77779) |
| return -ENODEV; |
| |
| ret = bcl_vimon_read(bcl_dev); |
| if (ret < 0) |
| return -ENODEV; |
| |
| for (idx = 0; idx < ret / VIMON_BYTES_PER_ENTRY; idx++) { |
| rdback = bcl_dev->vimon_intf.data[idx]; |
| count += sysfs_emit_at(buf, count, "%#x\n", rdback); |
| } |
| |
| return count; |
| } |
| static DEVICE_ATTR_RO(vimon_buff); |
| #endif |
| |
| static ssize_t ready_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%d\n", READ_ONCE(bcl_dev->enabled)); |
| } |
| static DEVICE_ATTR_RO(ready); |
| |
| static ssize_t ifpmic_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%s\n", bcl_dev->ifpmic == MAX77779 ? "max77779" : "max77759"); |
| } |
| static DEVICE_ATTR_RO(ifpmic); |
| |
| static struct attribute *instr_attrs[] = { |
| &dev_attr_mid_db_settings.attr, |
| &dev_attr_big_db_settings.attr, |
| &dev_attr_enable_mitigation.attr, |
| &dev_attr_enable_rffe_mitigation.attr, |
| &dev_attr_main_offsrc1.attr, |
| &dev_attr_main_offsrc2.attr, |
| &dev_attr_sub_offsrc1.attr, |
| &dev_attr_sub_offsrc2.attr, |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| &dev_attr_evt_cnt_uvlo1.attr, |
| &dev_attr_evt_cnt_uvlo2.attr, |
| &dev_attr_evt_cnt_batoilo1.attr, |
| &dev_attr_evt_cnt_batoilo2.attr, |
| &dev_attr_evt_cnt_latest_uvlo1.attr, |
| &dev_attr_evt_cnt_latest_uvlo2.attr, |
| &dev_attr_evt_cnt_latest_batoilo1.attr, |
| &dev_attr_evt_cnt_latest_batoilo2.attr, |
| #endif |
| &dev_attr_pwronsrc.attr, |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| &dev_attr_last_current.attr, |
| &dev_attr_vimon_buff.attr, |
| #endif |
| &dev_attr_ready.attr, |
| &dev_attr_ifpmic.attr, |
| NULL, |
| }; |
| |
| static const struct attribute_group instr_group = { |
| .attrs = instr_attrs, |
| .name = "instruction", |
| }; |
| |
| int uvlo_reg_read(struct device *dev, enum IFPMIC ifpmic, int triggered, unsigned int *val) |
| { |
| int ret; |
| uint8_t reg, regval; |
| |
| if (!dev) |
| return -ENODEV; |
| |
| if (ifpmic == MAX77779) { |
| reg = (triggered == UVLO1) ? MAX77779_SYS_UVLO1_CNFG_0 : MAX77779_SYS_UVLO2_CNFG_0; |
| ret = max77779_external_chg_reg_read(dev, reg, ®val); |
| if (ret < 0) |
| return -EINVAL; |
| if (triggered == UVLO1) |
| *val = _max77779_sys_uvlo1_cnfg_0_sys_uvlo1_get(regval); |
| else |
| *val = _max77779_sys_uvlo2_cnfg_0_sys_uvlo2_get(regval); |
| } else { |
| reg = (triggered == UVLO1) ? MAX77759_CHG_CNFG_15 : MAX77759_CHG_CNFG_16; |
| ret = max77759_external_reg_read(dev, reg, ®val); |
| if (ret < 0) |
| return -EINVAL; |
| if (triggered == UVLO1) |
| *val = _chg_cnfg_15_sys_uvlo1_get(regval); |
| else |
| *val = _chg_cnfg_16_sys_uvlo2_get(regval); |
| } |
| return ret; |
| } |
| |
| static int uvlo_reg_write(struct device *dev, uint8_t val, |
| enum IFPMIC ifpmic, int triggered) |
| { |
| int ret; |
| uint8_t reg, regval; |
| |
| if (!dev) |
| return -ENODEV; |
| |
| if (ifpmic == MAX77779) { |
| reg = (triggered == UVLO1) ? MAX77779_SYS_UVLO1_CNFG_0 : MAX77779_SYS_UVLO2_CNFG_0; |
| ret = max77779_external_chg_reg_read(dev, reg, ®val); |
| if (ret < 0) |
| return -EINVAL; |
| if (triggered == UVLO1) |
| regval = _max77779_sys_uvlo1_cnfg_0_sys_uvlo1_set(regval, val); |
| else |
| regval = _max77779_sys_uvlo2_cnfg_0_sys_uvlo2_set(regval, val); |
| ret = max77779_external_chg_reg_write(dev, reg, regval); |
| if (ret < 0) |
| return -EINVAL; |
| } else { |
| reg = (triggered == UVLO1) ? MAX77759_CHG_CNFG_15 : MAX77759_CHG_CNFG_16; |
| ret = max77759_external_reg_read(dev, reg, ®val); |
| if (ret < 0) |
| return -EINVAL; |
| if (triggered == UVLO1) |
| regval = _chg_cnfg_15_sys_uvlo1_set(regval, val); |
| else |
| regval = _chg_cnfg_16_sys_uvlo2_set(regval, val); |
| ret = max77759_external_reg_write(dev, reg, regval); |
| if (ret < 0) |
| return -EINVAL; |
| } |
| return ret; |
| } |
| |
| static ssize_t uvlo1_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int uvlo1_lvl; |
| |
| if (!bcl_dev) |
| return -EIO; |
| if (!bcl_dev->zone[UVLO1]) |
| return -EIO; |
| if (!bcl_dev->intf_pmic_dev) |
| return -EBUSY; |
| uvlo_reg_read(bcl_dev->intf_pmic_dev, bcl_dev->ifpmic, UVLO1, &uvlo1_lvl); |
| bcl_dev->zone[UVLO1]->bcl_lvl = VD_BATTERY_VOLTAGE - VD_STEP * uvlo1_lvl + |
| VD_LOWER_LIMIT - THERMAL_HYST_LEVEL; |
| return sysfs_emit(buf, "%dmV\n", VD_STEP * uvlo1_lvl + VD_LOWER_LIMIT); |
| } |
| |
| static ssize_t uvlo1_lvl_store(struct device *dev, |
| struct device_attribute *attr, const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int value; |
| uint8_t lvl; |
| int ret; |
| |
| ret = kstrtou32(buf, 10, &value); |
| if (ret) |
| return ret; |
| |
| if (!bcl_dev) |
| return -EIO; |
| if (!bcl_dev->zone[UVLO1]) |
| return -EIO; |
| if (value < VD_LOWER_LIMIT || value > VD_UPPER_LIMIT) { |
| dev_err(bcl_dev->device, "UVLO1 %d outside of range %d - %d mV.", value, |
| VD_LOWER_LIMIT, VD_UPPER_LIMIT); |
| return -EINVAL; |
| } |
| if (!bcl_dev->intf_pmic_dev) |
| return -EIO; |
| lvl = (value - VD_LOWER_LIMIT) / VD_STEP; |
| disable_irq(bcl_dev->zone[UVLO1]->bcl_irq); |
| ret = uvlo_reg_write(bcl_dev->intf_pmic_dev, lvl, bcl_dev->ifpmic, UVLO1); |
| enable_irq(bcl_dev->zone[UVLO1]->bcl_irq); |
| if (ret) |
| return ret; |
| bcl_dev->zone[UVLO1]->bcl_lvl = VD_BATTERY_VOLTAGE - value - THERMAL_HYST_LEVEL; |
| if (bcl_dev->zone[UVLO1]->tz) { |
| bcl_dev->zone[UVLO1]->tz->trips[0].temperature = VD_BATTERY_VOLTAGE - value; |
| thermal_zone_device_update(bcl_dev->zone[UVLO1]->tz, THERMAL_EVENT_UNSPECIFIED); |
| } |
| return size; |
| |
| } |
| |
| static DEVICE_ATTR_RW(uvlo1_lvl); |
| |
| static ssize_t uvlo2_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int uvlo2_lvl; |
| |
| if (!bcl_dev) |
| return -EIO; |
| if (!bcl_dev->zone[UVLO2]) |
| return sysfs_emit(buf, "disabled\n"); |
| if (!bcl_dev->intf_pmic_dev) |
| return -EBUSY; |
| uvlo_reg_read(bcl_dev->intf_pmic_dev, bcl_dev->ifpmic, UVLO2, &uvlo2_lvl); |
| bcl_dev->zone[UVLO1]->bcl_lvl = VD_BATTERY_VOLTAGE - VD_STEP * uvlo2_lvl + |
| VD_LOWER_LIMIT - THERMAL_HYST_LEVEL; |
| return sysfs_emit(buf, "%dmV\n", VD_STEP * uvlo2_lvl + VD_LOWER_LIMIT); |
| } |
| |
| static ssize_t uvlo2_lvl_store(struct device *dev, |
| struct device_attribute *attr, const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int value; |
| uint8_t lvl; |
| int ret; |
| |
| ret = kstrtou32(buf, 10, &value); |
| if (ret) |
| return ret; |
| |
| if (!bcl_dev) |
| return -EIO; |
| if (!bcl_dev->zone[UVLO2]) { |
| dev_err(bcl_dev->device, "UVLO2 is disabled\n"); |
| return -EIO; |
| } |
| if (value < VD_LOWER_LIMIT || value > VD_UPPER_LIMIT) { |
| dev_err(bcl_dev->device, "UVLO2 %d outside of range %d - %d mV.", value, |
| VD_LOWER_LIMIT, VD_UPPER_LIMIT); |
| return -EINVAL; |
| } |
| if (!bcl_dev->intf_pmic_dev) |
| return -EIO; |
| lvl = (value - VD_LOWER_LIMIT) / VD_STEP; |
| disable_irq(bcl_dev->zone[UVLO2]->bcl_irq); |
| ret = uvlo_reg_write(bcl_dev->intf_pmic_dev, lvl, bcl_dev->ifpmic, UVLO2); |
| enable_irq(bcl_dev->zone[UVLO2]->bcl_irq); |
| if (ret) |
| return ret; |
| bcl_dev->zone[UVLO2]->bcl_lvl = VD_BATTERY_VOLTAGE - value - THERMAL_HYST_LEVEL; |
| if (bcl_dev->zone[UVLO2]->tz) { |
| bcl_dev->zone[UVLO2]->tz->trips[0].temperature = VD_BATTERY_VOLTAGE - value; |
| thermal_zone_device_update(bcl_dev->zone[UVLO2]->tz, THERMAL_EVENT_UNSPECIFIED); |
| } |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(uvlo2_lvl); |
| |
| int batoilo_reg_read(struct device *dev, enum IFPMIC ifpmic, int oilo, unsigned int *val) |
| { |
| int ret; |
| uint8_t reg, regval; |
| |
| if (!dev) |
| return -ENODEV; |
| |
| if (ifpmic == MAX77779) { |
| reg = (oilo == BATOILO1) ? MAX77779_BAT_OILO1_CNFG_0 : MAX77779_BAT_OILO2_CNFG_0; |
| ret = max77779_external_chg_reg_read(dev, reg, ®val); |
| if (ret < 0) |
| return -EINVAL; |
| if (oilo == BATOILO1) |
| *val = _max77779_bat_oilo1_cnfg_0_bat_oilo1_get(regval); |
| else |
| *val = _max77779_bat_oilo2_cnfg_0_bat_oilo2_get(regval); |
| } else { |
| reg = MAX77759_CHG_CNFG_14; |
| ret = max77759_external_reg_read(dev, reg, ®val); |
| if (ret < 0) |
| return -EINVAL; |
| *val = _chg_cnfg_14_bat_oilo_get(regval); |
| } |
| return ret; |
| } |
| |
| static int batoilo_reg_write(struct device *dev, uint8_t val, |
| enum IFPMIC ifpmic, int oilo) |
| { |
| int ret; |
| uint8_t reg, regval; |
| |
| if (!dev) |
| return -ENODEV; |
| |
| if (ifpmic == MAX77779) { |
| reg = (oilo == BATOILO1) ? MAX77779_BAT_OILO1_CNFG_0 : MAX77779_BAT_OILO2_CNFG_0; |
| ret = max77779_external_chg_reg_read(dev, reg, ®val); |
| if (ret < 0) |
| return -EINVAL; |
| if (oilo == BATOILO1) |
| regval = _max77779_bat_oilo1_cnfg_0_bat_oilo1_set(regval, val); |
| else |
| regval = _max77779_bat_oilo2_cnfg_0_bat_oilo2_set(regval, val); |
| ret = max77779_external_chg_reg_write(dev, reg, regval); |
| if (ret < 0) |
| return -EINVAL; |
| } else { |
| reg = MAX77759_CHG_CNFG_14; |
| ret = max77759_external_reg_read(dev, reg, ®val); |
| if (ret < 0) |
| return -EINVAL; |
| regval = _chg_cnfg_14_bat_oilo_set(regval, val); |
| ret = max77759_external_reg_write(dev, reg, regval); |
| if (ret < 0) |
| return -EINVAL; |
| } |
| return ret; |
| } |
| |
| static ssize_t batoilo_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int batoilo1_lvl, lvl; |
| |
| if (!bcl_dev) |
| return -EIO; |
| if (!bcl_dev->zone[BATOILO1]) |
| return -EIO; |
| if (!bcl_dev->intf_pmic_dev) |
| return -EBUSY; |
| batoilo_reg_read(bcl_dev->intf_pmic_dev, bcl_dev->ifpmic, BATOILO1, &lvl); |
| batoilo1_lvl = BO_STEP * lvl + bcl_dev->batt_irq_conf1.batoilo_lower_limit; |
| bcl_dev->zone[BATOILO1]->bcl_lvl = batoilo1_lvl; |
| return sysfs_emit(buf, "%umA\n", batoilo1_lvl); |
| } |
| |
| static ssize_t batoilo_lvl_store(struct device *dev, |
| struct device_attribute *attr, const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int value, lvl; |
| int ret; |
| |
| ret = kstrtou32(buf, 10, &value); |
| if (ret) |
| return ret; |
| |
| if (!bcl_dev) |
| return -EIO; |
| if (!bcl_dev->zone[BATOILO1]) |
| return -EIO; |
| if (value < bcl_dev->batt_irq_conf1.batoilo_lower_limit || |
| value > bcl_dev->batt_irq_conf1.batoilo_upper_limit) { |
| dev_err(bcl_dev->device, "BATOILO1 %d outside of range %d - %d mA.", value, |
| bcl_dev->batt_irq_conf1.batoilo_lower_limit, |
| bcl_dev->batt_irq_conf1.batoilo_upper_limit); |
| return -EINVAL; |
| } |
| lvl = (value - bcl_dev->batt_irq_conf1.batoilo_lower_limit) / BO_STEP; |
| ret = batoilo_reg_write(bcl_dev->intf_pmic_dev, lvl, bcl_dev->ifpmic, BATOILO1); |
| if (ret) |
| return ret; |
| bcl_dev->zone[BATOILO1]->bcl_lvl = value - THERMAL_HYST_LEVEL; |
| if (bcl_dev->zone[BATOILO1]->tz) { |
| bcl_dev->zone[BATOILO1]->tz->trips[0].temperature = value; |
| thermal_zone_device_update(bcl_dev->zone[BATOILO1]->tz, THERMAL_EVENT_UNSPECIFIED); |
| } |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(batoilo_lvl); |
| |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| static ssize_t batoilo2_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int batoilo2_lvl, lvl; |
| |
| if (!bcl_dev) |
| return -EIO; |
| if (!bcl_dev->zone[BATOILO2]) |
| return -EIO; |
| if (!bcl_dev->intf_pmic_dev) |
| return -EBUSY; |
| batoilo_reg_read(bcl_dev->intf_pmic_dev, bcl_dev->ifpmic, BATOILO2, &lvl); |
| batoilo2_lvl = BO_STEP * lvl + bcl_dev->batt_irq_conf2.batoilo_lower_limit; |
| bcl_dev->zone[BATOILO2]->bcl_lvl = batoilo2_lvl; |
| return sysfs_emit(buf, "%umA\n", batoilo2_lvl); |
| } |
| |
| static ssize_t batoilo2_lvl_store(struct device *dev, |
| struct device_attribute *attr, const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int value, lvl; |
| int ret; |
| |
| ret = kstrtou32(buf, 10, &value); |
| if (ret) |
| return ret; |
| |
| if (!bcl_dev) |
| return -EIO; |
| if (!bcl_dev->zone[BATOILO2]) |
| return -EIO; |
| if (value < bcl_dev->batt_irq_conf2.batoilo_lower_limit || |
| value > bcl_dev->batt_irq_conf2.batoilo_upper_limit) { |
| dev_err(bcl_dev->device, "BATOILO2 %d outside of range %d - %d mA.", value, |
| bcl_dev->batt_irq_conf2.batoilo_lower_limit, |
| bcl_dev->batt_irq_conf2.batoilo_upper_limit); |
| return -EINVAL; |
| } |
| lvl = (value - bcl_dev->batt_irq_conf2.batoilo_lower_limit) / BO_STEP; |
| ret = batoilo_reg_write(bcl_dev->intf_pmic_dev, lvl, bcl_dev->ifpmic, BATOILO2); |
| if (ret) |
| return ret; |
| bcl_dev->zone[BATOILO2]->bcl_lvl = value - THERMAL_HYST_LEVEL; |
| if (bcl_dev->zone[BATOILO2]->tz) { |
| bcl_dev->zone[BATOILO2]->tz->trips[0].temperature = value; |
| thermal_zone_device_update(bcl_dev->zone[BATOILO2]->tz, THERMAL_EVENT_UNSPECIFIED); |
| } |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(batoilo2_lvl); |
| #endif |
| |
| static ssize_t smpl_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| u8 value = 0; |
| unsigned int smpl_warn_lvl; |
| |
| if (!bcl_dev) |
| return -EIO; |
| if (!bcl_dev->main_pmic_i2c) { |
| return -EBUSY; |
| } |
| pmic_read(CORE_PMIC_MAIN, bcl_dev, SMPL_WARN_CTRL, &value); |
| value >>= SMPL_WARN_SHIFT; |
| |
| smpl_warn_lvl = value * 100 + SMPL_LOWER_LIMIT; |
| return sysfs_emit(buf, "%umV\n", smpl_warn_lvl); |
| } |
| |
| static ssize_t smpl_lvl_store(struct device *dev, |
| struct device_attribute *attr, const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int val; |
| u8 value; |
| int ret; |
| |
| ret = kstrtou32(buf, 10, &val); |
| if (ret) |
| return ret; |
| |
| if (!bcl_dev) |
| return -EIO; |
| if (val < SMPL_LOWER_LIMIT || val > SMPL_UPPER_LIMIT) { |
| dev_err(bcl_dev->device, "SMPL_WARN LEVEL %d outside of range %d - %d mV.", val, |
| SMPL_LOWER_LIMIT, SMPL_UPPER_LIMIT); |
| return -EINVAL; |
| } |
| if (!bcl_dev->main_pmic_i2c) { |
| dev_err(bcl_dev->device, "MAIN I2C not found\n"); |
| return -EIO; |
| } |
| if (pmic_read(CORE_PMIC_MAIN, bcl_dev, SMPL_WARN_CTRL, &value)) { |
| dev_err(bcl_dev->device, "S2MPG1415 read 0x%x failed.", SMPL_WARN_CTRL); |
| return -EBUSY; |
| } |
| disable_irq(bcl_dev->zone[SMPL_WARN]->bcl_irq); |
| value &= ~SMPL_WARN_MASK; |
| value |= ((val - SMPL_LOWER_LIMIT) / 100) << SMPL_WARN_SHIFT; |
| if (pmic_write(CORE_PMIC_MAIN, bcl_dev, SMPL_WARN_CTRL, value)) { |
| dev_err(bcl_dev->device, "i2c write error setting smpl_warn\n"); |
| enable_irq(bcl_dev->zone[SMPL_WARN]->bcl_irq); |
| return ret; |
| } |
| bcl_dev->zone[SMPL_WARN]->bcl_lvl = SMPL_BATTERY_VOLTAGE - val - THERMAL_HYST_LEVEL; |
| |
| if (bcl_dev->zone[SMPL_WARN]->tz) { |
| bcl_dev->zone[SMPL_WARN]->tz->trips[0].temperature = SMPL_BATTERY_VOLTAGE - val; |
| thermal_zone_device_update(bcl_dev->zone[SMPL_WARN]->tz, THERMAL_EVENT_UNSPECIFIED); |
| } |
| enable_irq(bcl_dev->zone[SMPL_WARN]->bcl_irq); |
| |
| return size; |
| |
| } |
| |
| static DEVICE_ATTR_RW(smpl_lvl); |
| |
| static int get_ocp_lvl(struct bcl_device *bcl_dev, u64 *val, u8 addr, u8 pmic, u8 mask, u16 limit, |
| u16 step) |
| { |
| u8 value = 0; |
| unsigned int ocp_warn_lvl; |
| |
| if (!bcl_dev) |
| return -EIO; |
| if (pmic_read(pmic, bcl_dev, addr, &value)) { |
| dev_err(bcl_dev->device, "S2MPG1415 read 0x%x failed.", addr); |
| return -EBUSY; |
| } |
| value &= mask; |
| ocp_warn_lvl = limit - value * step; |
| *val = ocp_warn_lvl; |
| return 0; |
| } |
| |
| static int set_ocp_lvl(struct bcl_device *bcl_dev, u64 val, u8 addr, u8 pmic, u8 mask, |
| u16 llimit, u16 ulimit, u16 step, u8 id) |
| { |
| u8 value; |
| int ret; |
| |
| if (!bcl_dev) |
| return -EIO; |
| if (!bcl_dev->zone[id]) |
| return 0; |
| if (val < llimit || val > ulimit) { |
| dev_err(bcl_dev->device, "OCP_WARN LEVEL %llu outside of range %d - %d mA.", val, |
| llimit, ulimit); |
| return -EBUSY; |
| } |
| if (pmic_read(pmic, bcl_dev, addr, &value)) { |
| dev_err(bcl_dev->device, "S2MPG1415 read 0x%x failed.", addr); |
| return -EBUSY; |
| } |
| disable_irq(bcl_dev->zone[id]->bcl_irq); |
| value &= ~(OCP_WARN_MASK) << OCP_WARN_LVL_SHIFT; |
| value |= ((ulimit - val) / step) << OCP_WARN_LVL_SHIFT; |
| ret = pmic_write(pmic, bcl_dev, addr, value); |
| if (!ret) |
| bcl_dev->zone[id]->bcl_lvl = val - THERMAL_HYST_LEVEL; |
| if (bcl_dev->zone[id]->tz) { |
| bcl_dev->zone[id]->tz->trips[0].temperature = val; |
| thermal_zone_device_update(bcl_dev->zone[id]->tz, THERMAL_EVENT_UNSPECIFIED); |
| } |
| enable_irq(bcl_dev->zone[id]->bcl_irq); |
| |
| return ret; |
| } |
| |
| static ssize_t ocp_cpu1_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| u64 val; |
| |
| if (get_ocp_lvl(bcl_dev, &val, CPU1_OCP_WARN, CORE_PMIC_MAIN, OCP_WARN_MASK, |
| CPU1_UPPER_LIMIT, CPU1_STEP) < 0) |
| return -EINVAL; |
| return sysfs_emit(buf, "%llumA\n", val); |
| |
| } |
| |
| static ssize_t ocp_cpu1_lvl_store(struct device *dev, |
| struct device_attribute *attr, const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int value; |
| int ret; |
| |
| ret = kstrtou32(buf, 10, &value); |
| if (ret) |
| return ret; |
| |
| if (set_ocp_lvl(bcl_dev, value, CPU1_OCP_WARN, CORE_PMIC_MAIN, OCP_WARN_MASK, |
| CPU1_LOWER_LIMIT, CPU1_UPPER_LIMIT, CPU1_STEP, OCP_WARN_CPUCL1) < 0) |
| return -EINVAL; |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(ocp_cpu1_lvl); |
| |
| static ssize_t ocp_cpu2_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| u64 val; |
| |
| if (get_ocp_lvl(bcl_dev, &val, CPU2_OCP_WARN, CORE_PMIC_MAIN, OCP_WARN_MASK, |
| CPU2_UPPER_LIMIT, CPU2_STEP) < 0) |
| return -EINVAL; |
| return sysfs_emit(buf, "%llumA\n", val); |
| |
| } |
| |
| static ssize_t ocp_cpu2_lvl_store(struct device *dev, |
| struct device_attribute *attr, const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int value; |
| int ret; |
| |
| ret = kstrtou32(buf, 10, &value); |
| if (ret) |
| return ret; |
| |
| if (set_ocp_lvl(bcl_dev, value, CPU2_OCP_WARN, CORE_PMIC_MAIN, OCP_WARN_MASK, |
| CPU2_LOWER_LIMIT, CPU2_UPPER_LIMIT, CPU2_STEP, OCP_WARN_CPUCL2) < 0) |
| return -EINVAL; |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(ocp_cpu2_lvl); |
| |
| static ssize_t ocp_tpu_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| u64 val; |
| |
| if (get_ocp_lvl(bcl_dev, &val, TPU_OCP_WARN, CORE_PMIC_MAIN, OCP_WARN_MASK, |
| TPU_UPPER_LIMIT, TPU_STEP) < 0) |
| return -EINVAL; |
| return sysfs_emit(buf, "%llumA\n", val); |
| |
| } |
| |
| static ssize_t ocp_tpu_lvl_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int value; |
| int ret; |
| |
| ret = kstrtou32(buf, 10, &value); |
| if (ret) |
| return ret; |
| |
| if (set_ocp_lvl(bcl_dev, value, TPU_OCP_WARN, CORE_PMIC_MAIN, OCP_WARN_MASK, |
| TPU_LOWER_LIMIT, TPU_UPPER_LIMIT, TPU_STEP, OCP_WARN_TPU) < 0) |
| return -EINVAL; |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(ocp_tpu_lvl); |
| |
| static ssize_t ocp_gpu_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| u64 val; |
| |
| if (get_ocp_lvl(bcl_dev, &val, GPU_OCP_WARN, CORE_PMIC_SUB, OCP_WARN_MASK, GPU_UPPER_LIMIT, |
| GPU_STEP) < 0) |
| return -EINVAL; |
| return sysfs_emit(buf, "%llumA\n", val); |
| |
| } |
| |
| static ssize_t ocp_gpu_lvl_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int value; |
| int ret; |
| |
| ret = kstrtou32(buf, 10, &value); |
| if (ret) |
| return ret; |
| |
| if (set_ocp_lvl(bcl_dev, value, GPU_OCP_WARN, CORE_PMIC_SUB, OCP_WARN_MASK, |
| GPU_LOWER_LIMIT, GPU_UPPER_LIMIT, GPU_STEP, OCP_WARN_GPU) < 0) |
| return -EINVAL; |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(ocp_gpu_lvl); |
| |
| static ssize_t soft_ocp_cpu1_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| u64 val; |
| |
| if (get_ocp_lvl(bcl_dev, &val, SOFT_CPU1_OCP_WARN, CORE_PMIC_MAIN, OCP_WARN_MASK, |
| CPU1_UPPER_LIMIT, CPU1_STEP) < 0) |
| return -EINVAL; |
| return sysfs_emit(buf, "%llumA\n", val); |
| } |
| |
| static ssize_t soft_ocp_cpu1_lvl_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int value; |
| int ret; |
| |
| ret = kstrtou32(buf, 10, &value); |
| if (ret) |
| return ret; |
| |
| if (set_ocp_lvl(bcl_dev, value, SOFT_CPU1_OCP_WARN, CORE_PMIC_MAIN, OCP_WARN_MASK, |
| CPU1_LOWER_LIMIT, CPU1_UPPER_LIMIT, CPU1_STEP, SOFT_OCP_WARN_CPUCL1) < 0) |
| return -EINVAL; |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(soft_ocp_cpu1_lvl); |
| |
| static ssize_t soft_ocp_cpu2_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| u64 val; |
| |
| if (get_ocp_lvl(bcl_dev, &val, SOFT_CPU2_OCP_WARN, CORE_PMIC_MAIN, OCP_WARN_MASK, |
| CPU2_UPPER_LIMIT, CPU2_STEP) < 0) |
| return -EINVAL; |
| return sysfs_emit(buf, "%llumA\n", val); |
| } |
| |
| static ssize_t soft_ocp_cpu2_lvl_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int value; |
| int ret; |
| |
| ret = kstrtou32(buf, 10, &value); |
| if (ret) |
| return ret; |
| |
| if (set_ocp_lvl(bcl_dev, value, SOFT_CPU2_OCP_WARN, CORE_PMIC_MAIN, OCP_WARN_MASK, |
| CPU2_LOWER_LIMIT, CPU2_UPPER_LIMIT, CPU2_STEP, SOFT_OCP_WARN_CPUCL2) < 0) |
| return -EINVAL; |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(soft_ocp_cpu2_lvl); |
| |
| static ssize_t soft_ocp_tpu_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| u64 val; |
| |
| if (get_ocp_lvl(bcl_dev, &val, SOFT_TPU_OCP_WARN, CORE_PMIC_MAIN, OCP_WARN_MASK, |
| TPU_UPPER_LIMIT, TPU_STEP) < 0) |
| return -EINVAL; |
| return sysfs_emit(buf, "%llumA\n", val); |
| } |
| |
| static ssize_t soft_ocp_tpu_lvl_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int value; |
| int ret; |
| |
| ret = kstrtou32(buf, 10, &value); |
| if (ret) |
| return ret; |
| |
| if (set_ocp_lvl(bcl_dev, value, SOFT_TPU_OCP_WARN, CORE_PMIC_MAIN, OCP_WARN_MASK, |
| TPU_LOWER_LIMIT, TPU_UPPER_LIMIT, TPU_STEP, SOFT_OCP_WARN_TPU) < 0) |
| return -EINVAL; |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(soft_ocp_tpu_lvl); |
| |
| static ssize_t soft_ocp_gpu_lvl_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| u64 val; |
| |
| if (get_ocp_lvl(bcl_dev, &val, SOFT_GPU_OCP_WARN, CORE_PMIC_SUB, OCP_WARN_MASK, |
| GPU_UPPER_LIMIT, GPU_STEP) < 0) |
| return -EINVAL; |
| return sysfs_emit(buf, "%llumA\n", val); |
| } |
| |
| static ssize_t soft_ocp_gpu_lvl_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int value; |
| int ret; |
| |
| ret = kstrtou32(buf, 10, &value); |
| if (ret) |
| return ret; |
| |
| if (set_ocp_lvl(bcl_dev, value, SOFT_GPU_OCP_WARN, CORE_PMIC_SUB, OCP_WARN_MASK, |
| GPU_LOWER_LIMIT, GPU_UPPER_LIMIT, GPU_STEP, SOFT_OCP_WARN_GPU) < 0) |
| return -EINVAL; |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(soft_ocp_gpu_lvl); |
| |
| static struct attribute *triggered_lvl_attrs[] = { |
| &dev_attr_uvlo1_lvl.attr, |
| &dev_attr_uvlo2_lvl.attr, |
| &dev_attr_batoilo_lvl.attr, |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| &dev_attr_batoilo2_lvl.attr, |
| #endif |
| &dev_attr_smpl_lvl.attr, |
| &dev_attr_ocp_cpu1_lvl.attr, |
| &dev_attr_ocp_cpu2_lvl.attr, |
| &dev_attr_ocp_tpu_lvl.attr, |
| &dev_attr_ocp_gpu_lvl.attr, |
| &dev_attr_soft_ocp_cpu1_lvl.attr, |
| &dev_attr_soft_ocp_cpu2_lvl.attr, |
| &dev_attr_soft_ocp_tpu_lvl.attr, |
| &dev_attr_soft_ocp_gpu_lvl.attr, |
| NULL, |
| }; |
| |
| static const struct attribute_group triggered_lvl_group = { |
| .attrs = triggered_lvl_attrs, |
| .name = "triggered_lvl", |
| }; |
| |
| static ssize_t clk_div_show(struct bcl_device *bcl_dev, int idx, char *buf) |
| { |
| unsigned int reg = 0; |
| int ret; |
| |
| if (!bcl_dev) |
| return -EIO; |
| switch (idx) { |
| case SUBSYSTEM_TPU: |
| case SUBSYSTEM_GPU: |
| case SUBSYSTEM_AUR: |
| return sysfs_emit(buf, "0x%x\n", bcl_dev->core_conf[idx].clkdivstep); |
| case SUBSYSTEM_CPU1: |
| case SUBSYSTEM_CPU2: |
| ret = cpu_buff_read(bcl_dev, idx, CPU_BUFF_CLKDIVSTEP, ®); |
| if (ret < 0) |
| return ret; |
| break; |
| } |
| return sysfs_emit(buf, "0x%x\n", reg); |
| } |
| |
| static ssize_t clk_stats_show(struct bcl_device *bcl_dev, int idx, char *buf) |
| { |
| unsigned int reg = 0; |
| int ret; |
| |
| if (!bcl_dev) |
| return -EIO; |
| switch (idx) { |
| case SUBSYSTEM_TPU: |
| case SUBSYSTEM_GPU: |
| case SUBSYSTEM_AUR: |
| return sysfs_emit(buf, "0x%x\n", bcl_dev->core_conf[idx].clk_stats); |
| case SUBSYSTEM_CPU0: |
| case SUBSYSTEM_CPU1: |
| case SUBSYSTEM_CPU2: |
| ret = cpu_buff_read(bcl_dev, idx, CPU_BUFF_CLK_STATS, ®); |
| if (ret < 0) |
| return ret; |
| break; |
| } |
| return sysfs_emit(buf, "0x%x\n", reg); |
| } |
| static ssize_t cpu0_clk_div_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_div_show(bcl_dev, SUBSYSTEM_CPU0, buf); |
| } |
| |
| static ssize_t clk_div_store(struct bcl_device *bcl_dev, int idx, |
| const char *buf, size_t size) |
| { |
| unsigned int value; |
| int ret; |
| |
| ret = sscanf(buf, "0x%x", &value); |
| if (ret != 1) |
| return -EINVAL; |
| |
| if (!bcl_dev) |
| return -EIO; |
| switch (idx) { |
| case SUBSYSTEM_TPU: |
| case SUBSYSTEM_GPU: |
| case SUBSYSTEM_AUR: |
| return size; |
| case SUBSYSTEM_CPU0: |
| case SUBSYSTEM_CPU1: |
| case SUBSYSTEM_CPU2: |
| ret = cpu_buff_write(bcl_dev, idx, CPU_BUFF_CLKDIVSTEP, value); |
| if (ret < 0) |
| return ret; |
| break; |
| } |
| return size; |
| } |
| |
| static ssize_t cpu0_clk_div_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_div_store(bcl_dev, SUBSYSTEM_CPU0, buf, size); |
| } |
| |
| static DEVICE_ATTR_RW(cpu0_clk_div); |
| |
| static ssize_t cpu1_clk_div_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_div_show(bcl_dev, SUBSYSTEM_CPU1, buf); |
| } |
| |
| static ssize_t cpu1_clk_div_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_div_store(bcl_dev, SUBSYSTEM_CPU1, buf, size); |
| } |
| |
| static DEVICE_ATTR_RW(cpu1_clk_div); |
| |
| static ssize_t cpu2_clk_div_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_div_show(bcl_dev, SUBSYSTEM_CPU2, buf); |
| } |
| |
| static ssize_t cpu2_clk_div_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_div_store(bcl_dev, SUBSYSTEM_CPU2, buf, size); |
| } |
| |
| static DEVICE_ATTR_RW(cpu2_clk_div); |
| |
| static ssize_t tpu_clk_div_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_div_show(bcl_dev, SUBSYSTEM_TPU, buf); |
| } |
| |
| static ssize_t tpu_clk_div_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_div_store(bcl_dev, SUBSYSTEM_TPU, buf, size); |
| } |
| |
| static DEVICE_ATTR_RW(tpu_clk_div); |
| |
| static ssize_t aur_clk_div_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_div_show(bcl_dev, SUBSYSTEM_AUR, buf); |
| } |
| |
| static ssize_t aur_clk_div_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_div_store(bcl_dev, SUBSYSTEM_AUR, buf, size); |
| } |
| |
| static DEVICE_ATTR_RW(aur_clk_div); |
| |
| static ssize_t gpu_clk_div_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_div_show(bcl_dev, SUBSYSTEM_GPU, buf); |
| } |
| |
| static ssize_t gpu_clk_div_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_div_store(bcl_dev, SUBSYSTEM_GPU, buf, size); |
| } |
| |
| static DEVICE_ATTR_RW(gpu_clk_div); |
| |
| static struct attribute *clock_div_attrs[] = { |
| &dev_attr_cpu0_clk_div.attr, |
| &dev_attr_cpu1_clk_div.attr, |
| &dev_attr_cpu2_clk_div.attr, |
| &dev_attr_tpu_clk_div.attr, |
| &dev_attr_gpu_clk_div.attr, |
| &dev_attr_aur_clk_div.attr, |
| NULL, |
| }; |
| |
| static const struct attribute_group clock_div_group = { |
| .attrs = clock_div_attrs, |
| .name = "clock_div", |
| }; |
| |
| static ssize_t clk_ratio_show(struct bcl_device *bcl_dev, enum RATIO_SOURCE idx, char *buf, |
| int sub_idx) |
| { |
| unsigned int reg = 0; |
| int ret; |
| |
| if (!bcl_dev) |
| return -EIO; |
| |
| switch (idx) { |
| case TPU_HEAVY: |
| case GPU_HEAVY: |
| return sysfs_emit(buf, "0x%x\n", bcl_dev->core_conf[sub_idx].con_heavy); |
| case TPU_LIGHT: |
| case GPU_LIGHT: |
| return sysfs_emit(buf, "0x%x\n", bcl_dev->core_conf[sub_idx].con_light); |
| case CPU0_CON: |
| case CPU1_LIGHT: |
| case CPU2_LIGHT: |
| ret = cpu_buff_read(bcl_dev, sub_idx, CPU_BUFF_CON_LIGHT, ®); |
| if (ret < 0) |
| return ret; |
| break; |
| case CPU1_HEAVY: |
| case CPU2_HEAVY: |
| ret = cpu_buff_read(bcl_dev, sub_idx, CPU_BUFF_CON_HEAVY, ®); |
| if (ret < 0) |
| return ret; |
| break; |
| } |
| return sysfs_emit(buf, "0x%x\n", reg); |
| } |
| |
| static ssize_t clk_ratio_store(struct bcl_device *bcl_dev, enum RATIO_SOURCE idx, |
| const char *buf, size_t size, int sub_idx) |
| { |
| unsigned int value; |
| int ret; |
| |
| ret = sscanf(buf, "0x%x", &value); |
| if (ret != 1) |
| return -EINVAL; |
| |
| if (!bcl_dev) |
| return -EIO; |
| |
| switch (idx) { |
| case TPU_HEAVY: |
| case GPU_HEAVY: |
| bcl_dev->core_conf[sub_idx].con_heavy = value; |
| return size; |
| case TPU_LIGHT: |
| case GPU_LIGHT: |
| bcl_dev->core_conf[sub_idx].con_light = value; |
| return size; |
| case CPU0_CON: |
| case CPU1_LIGHT: |
| case CPU2_LIGHT: |
| ret = cpu_buff_write(bcl_dev, sub_idx, CPU_BUFF_CON_LIGHT, value); |
| if (ret < 0) |
| return ret; |
| break; |
| case CPU1_HEAVY: |
| case CPU2_HEAVY: |
| ret = cpu_buff_write(bcl_dev, sub_idx, CPU_BUFF_CON_HEAVY, value); |
| if (ret < 0) |
| return ret; |
| break; |
| } |
| return size; |
| } |
| |
| static ssize_t cpu0_clk_ratio_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_show(bcl_dev, CPU0_CON, buf, SUBSYSTEM_CPU0); |
| } |
| |
| static ssize_t cpu0_clk_ratio_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_store(bcl_dev, CPU0_CON, buf, size, SUBSYSTEM_CPU0); |
| } |
| |
| static DEVICE_ATTR_RW(cpu0_clk_ratio); |
| |
| static ssize_t cpu1_heavy_clk_ratio_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_show(bcl_dev, CPU1_HEAVY, buf, SUBSYSTEM_CPU1); |
| } |
| |
| static ssize_t cpu1_heavy_clk_ratio_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_store(bcl_dev, CPU1_HEAVY, buf, size, SUBSYSTEM_CPU1); |
| } |
| |
| static DEVICE_ATTR_RW(cpu1_heavy_clk_ratio); |
| |
| static ssize_t cpu2_heavy_clk_ratio_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_show(bcl_dev, CPU2_HEAVY, buf, SUBSYSTEM_CPU2); |
| } |
| |
| static ssize_t cpu2_heavy_clk_ratio_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_store(bcl_dev, CPU2_HEAVY, buf, size, SUBSYSTEM_CPU2); |
| } |
| |
| static DEVICE_ATTR_RW(cpu2_heavy_clk_ratio); |
| |
| static ssize_t tpu_heavy_clk_ratio_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_show(bcl_dev, TPU_HEAVY, buf, SUBSYSTEM_TPU); |
| } |
| |
| static ssize_t tpu_heavy_clk_ratio_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_store(bcl_dev, TPU_HEAVY, buf, size, SUBSYSTEM_TPU); |
| } |
| |
| static DEVICE_ATTR_RW(tpu_heavy_clk_ratio); |
| |
| static ssize_t gpu_heavy_clk_ratio_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_show(bcl_dev, GPU_HEAVY, buf, SUBSYSTEM_GPU); |
| } |
| |
| static ssize_t gpu_heavy_clk_ratio_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_store(bcl_dev, GPU_HEAVY, buf, size, SUBSYSTEM_GPU); |
| } |
| |
| static DEVICE_ATTR_RW(gpu_heavy_clk_ratio); |
| |
| static ssize_t cpu1_light_clk_ratio_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_show(bcl_dev, CPU1_LIGHT, buf, SUBSYSTEM_CPU1); |
| } |
| |
| static ssize_t cpu1_light_clk_ratio_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_store(bcl_dev, CPU1_LIGHT, buf, size, SUBSYSTEM_CPU1); |
| } |
| |
| static DEVICE_ATTR_RW(cpu1_light_clk_ratio); |
| |
| static ssize_t cpu2_light_clk_ratio_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_show(bcl_dev, CPU2_LIGHT, buf, SUBSYSTEM_CPU2); |
| } |
| |
| static ssize_t cpu2_light_clk_ratio_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_store(bcl_dev, CPU2_LIGHT, buf, size, SUBSYSTEM_CPU2); |
| } |
| |
| static DEVICE_ATTR_RW(cpu2_light_clk_ratio); |
| |
| static ssize_t tpu_light_clk_ratio_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_show(bcl_dev, TPU_LIGHT, buf, SUBSYSTEM_TPU); |
| } |
| |
| static ssize_t tpu_light_clk_ratio_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_store(bcl_dev, TPU_LIGHT, buf, size, SUBSYSTEM_TPU); |
| } |
| |
| static DEVICE_ATTR_RW(tpu_light_clk_ratio); |
| |
| static ssize_t gpu_light_clk_ratio_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_show(bcl_dev, GPU_LIGHT, buf, SUBSYSTEM_GPU); |
| } |
| |
| static ssize_t gpu_light_clk_ratio_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_ratio_store(bcl_dev, GPU_LIGHT, buf, size, SUBSYSTEM_GPU); |
| } |
| |
| static DEVICE_ATTR_RW(gpu_light_clk_ratio); |
| |
| static struct attribute *clock_ratio_attrs[] = { |
| &dev_attr_cpu0_clk_ratio.attr, |
| &dev_attr_cpu1_heavy_clk_ratio.attr, |
| &dev_attr_cpu2_heavy_clk_ratio.attr, |
| &dev_attr_tpu_heavy_clk_ratio.attr, |
| &dev_attr_gpu_heavy_clk_ratio.attr, |
| &dev_attr_cpu1_light_clk_ratio.attr, |
| &dev_attr_cpu2_light_clk_ratio.attr, |
| &dev_attr_tpu_light_clk_ratio.attr, |
| &dev_attr_gpu_light_clk_ratio.attr, |
| NULL, |
| }; |
| |
| static const struct attribute_group clock_ratio_group = { |
| .attrs = clock_ratio_attrs, |
| .name = "clock_ratio", |
| }; |
| |
| static ssize_t cpu0_clk_stats_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_stats_show(bcl_dev, SUBSYSTEM_CPU0, buf); |
| } |
| |
| static DEVICE_ATTR_RO(cpu0_clk_stats); |
| |
| static ssize_t cpu1_clk_stats_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_stats_show(bcl_dev, SUBSYSTEM_CPU1, buf); |
| } |
| |
| static DEVICE_ATTR_RO(cpu1_clk_stats); |
| |
| static ssize_t cpu2_clk_stats_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_stats_show(bcl_dev, SUBSYSTEM_CPU2, buf); |
| } |
| |
| static DEVICE_ATTR_RO(cpu2_clk_stats); |
| |
| static ssize_t tpu_clk_stats_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_stats_show(bcl_dev, SUBSYSTEM_TPU, buf); |
| } |
| |
| static DEVICE_ATTR_RO(tpu_clk_stats); |
| |
| static ssize_t aur_clk_stats_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_stats_show(bcl_dev, SUBSYSTEM_AUR, buf); |
| } |
| |
| static DEVICE_ATTR_RO(aur_clk_stats); |
| |
| static ssize_t gpu_clk_stats_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return clk_stats_show(bcl_dev, SUBSYSTEM_GPU, buf); |
| } |
| |
| static DEVICE_ATTR_RO(gpu_clk_stats); |
| |
| static ssize_t last_triggered_cnt(struct bcl_zone *zone, char *buf, int mode) |
| { |
| if (!zone) |
| return -ENODEV; |
| if (mode >= 0 && mode < MAX_MITIGATION_MODE) |
| return sysfs_emit(buf, "%d\n", |
| atomic_read(&zone->last_triggered.triggered_cnt[mode])); |
| return sysfs_emit(buf, "0\n"); |
| } |
| |
| static ssize_t last_triggered_time(struct bcl_zone *zone, char *buf, int mode) |
| { |
| if (!zone) |
| return -ENODEV; |
| if (mode >= 0 && mode < MAX_MITIGATION_MODE) |
| return sysfs_emit(buf, "%lld\n", zone->last_triggered.triggered_time[mode]); |
| return sysfs_emit(buf, "0\n"); |
| } |
| |
| static ssize_t last_triggered_uvlo1_heavy_cnt_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[UVLO1], buf, HEAVY); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo1_heavy_cnt); |
| |
| static ssize_t last_triggered_uvlo1_medium_cnt_show(struct device *dev, |
| struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[UVLO1], buf, MEDIUM); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo1_medium_cnt); |
| |
| static ssize_t last_triggered_uvlo1_light_cnt_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[UVLO1], buf, LIGHT); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo1_light_cnt); |
| |
| static ssize_t last_triggered_uvlo1_start_cnt_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[UVLO1], buf, START); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo1_start_cnt); |
| |
| static ssize_t last_triggered_uvlo1_heavy_time_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[UVLO1], buf, HEAVY); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo1_heavy_time); |
| |
| static ssize_t last_triggered_uvlo1_medium_time_show(struct device *dev, |
| struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[UVLO1], buf, MEDIUM); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo1_medium_time); |
| |
| static ssize_t last_triggered_uvlo1_light_time_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[UVLO1], buf, LIGHT); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo1_light_time); |
| |
| static ssize_t last_triggered_uvlo1_start_time_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[UVLO1], buf, START); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo1_start_time); |
| |
| static ssize_t last_triggered_uvlo2_heavy_cnt_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[UVLO2], buf, HEAVY); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo2_heavy_cnt); |
| |
| static ssize_t last_triggered_uvlo2_medium_cnt_show(struct device *dev, |
| struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[UVLO2], buf, MEDIUM); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo2_medium_cnt); |
| |
| static ssize_t last_triggered_uvlo2_light_cnt_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[UVLO2], buf, LIGHT); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo2_light_cnt); |
| |
| static ssize_t last_triggered_uvlo2_start_cnt_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[UVLO2], buf, START); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo2_start_cnt); |
| |
| static ssize_t last_triggered_uvlo2_heavy_time_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[UVLO2], buf, HEAVY); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo2_heavy_time); |
| |
| static ssize_t last_triggered_uvlo2_medium_time_show(struct device *dev, |
| struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[UVLO2], buf, MEDIUM); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo2_medium_time); |
| |
| static ssize_t last_triggered_uvlo2_light_time_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[UVLO2], buf, LIGHT); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo2_light_time); |
| |
| static ssize_t last_triggered_uvlo2_start_time_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[UVLO2], buf, START); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_uvlo2_start_time); |
| |
| static ssize_t last_triggered_batoilo2_heavy_cnt_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[BATOILO2], buf, HEAVY); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo2_heavy_cnt); |
| |
| static ssize_t last_triggered_batoilo2_medium_cnt_show(struct device *dev, |
| struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[BATOILO2], buf, MEDIUM); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo2_medium_cnt); |
| |
| static ssize_t last_triggered_batoilo2_light_cnt_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[BATOILO2], buf, LIGHT); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo2_light_cnt); |
| |
| static ssize_t last_triggered_batoilo2_start_cnt_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[BATOILO2], buf, START); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo2_start_cnt); |
| |
| static ssize_t last_triggered_batoilo2_heavy_time_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[BATOILO2], buf, HEAVY); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo2_heavy_time); |
| |
| static ssize_t last_triggered_batoilo2_medium_time_show(struct device *dev, |
| struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[BATOILO2], buf, MEDIUM); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo2_medium_time); |
| |
| static ssize_t last_triggered_batoilo2_light_time_show(struct device *dev, |
| struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[BATOILO2], buf, LIGHT); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo2_light_time); |
| |
| static ssize_t last_triggered_batoilo2_start_time_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[BATOILO2], buf, START); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo2_start_time); |
| |
| static ssize_t last_triggered_batoilo_heavy_cnt_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[BATOILO], buf, HEAVY); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo_heavy_cnt); |
| |
| static ssize_t last_triggered_batoilo_medium_cnt_show(struct device *dev, |
| struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[BATOILO], buf, MEDIUM); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo_medium_cnt); |
| |
| static ssize_t last_triggered_batoilo_light_cnt_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[BATOILO], buf, LIGHT); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo_light_cnt); |
| |
| static ssize_t last_triggered_batoilo_start_cnt_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_cnt(bcl_dev->zone[BATOILO], buf, START); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo_start_cnt); |
| |
| static ssize_t last_triggered_batoilo_heavy_time_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[BATOILO], buf, HEAVY); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo_heavy_time); |
| |
| static ssize_t last_triggered_batoilo_medium_time_show(struct device *dev, |
| struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[BATOILO], buf, MEDIUM); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo_medium_time); |
| |
| static ssize_t last_triggered_batoilo_light_time_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[BATOILO], buf, LIGHT); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo_light_time); |
| |
| static ssize_t last_triggered_batoilo_start_time_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return last_triggered_time(bcl_dev->zone[BATOILO], buf, START); |
| } |
| |
| static DEVICE_ATTR_RO(last_triggered_batoilo_start_time); |
| |
| static struct attribute *clock_stats_attrs[] = { |
| &dev_attr_cpu0_clk_stats.attr, |
| &dev_attr_cpu1_clk_stats.attr, |
| &dev_attr_cpu2_clk_stats.attr, |
| &dev_attr_tpu_clk_stats.attr, |
| &dev_attr_gpu_clk_stats.attr, |
| &dev_attr_aur_clk_stats.attr, |
| NULL, |
| }; |
| |
| static const struct attribute_group clock_stats_group = { |
| .attrs = clock_stats_attrs, |
| .name = "clock_stats", |
| }; |
| |
| static struct attribute *triggered_count_attrs[] = { |
| &dev_attr_smpl_warn_count.attr, |
| &dev_attr_ocp_cpu1_count.attr, |
| &dev_attr_ocp_cpu2_count.attr, |
| &dev_attr_ocp_tpu_count.attr, |
| &dev_attr_ocp_gpu_count.attr, |
| &dev_attr_soft_ocp_cpu1_count.attr, |
| &dev_attr_soft_ocp_cpu2_count.attr, |
| &dev_attr_soft_ocp_tpu_count.attr, |
| &dev_attr_soft_ocp_gpu_count.attr, |
| &dev_attr_vdroop1_count.attr, |
| &dev_attr_vdroop2_count.attr, |
| &dev_attr_batoilo_count.attr, |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| &dev_attr_batoilo2_count.attr, |
| #endif |
| NULL, |
| }; |
| |
| static const struct attribute_group triggered_count_group = { |
| .attrs = triggered_count_attrs, |
| .name = "last_triggered_count", |
| }; |
| |
| static struct attribute *triggered_time_attrs[] = { |
| &dev_attr_smpl_warn_time.attr, |
| &dev_attr_ocp_cpu1_time.attr, |
| &dev_attr_ocp_cpu2_time.attr, |
| &dev_attr_ocp_tpu_time.attr, |
| &dev_attr_ocp_gpu_time.attr, |
| &dev_attr_soft_ocp_cpu1_time.attr, |
| &dev_attr_soft_ocp_cpu2_time.attr, |
| &dev_attr_soft_ocp_tpu_time.attr, |
| &dev_attr_soft_ocp_gpu_time.attr, |
| &dev_attr_vdroop1_time.attr, |
| &dev_attr_vdroop2_time.attr, |
| &dev_attr_batoilo_time.attr, |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| &dev_attr_batoilo2_time.attr, |
| #endif |
| NULL, |
| }; |
| |
| static const struct attribute_group triggered_timestamp_group = { |
| .attrs = triggered_time_attrs, |
| .name = "last_triggered_timestamp", |
| }; |
| |
| static struct attribute *triggered_cap_attrs[] = { |
| &dev_attr_smpl_warn_cap.attr, |
| &dev_attr_ocp_cpu1_cap.attr, |
| &dev_attr_ocp_cpu2_cap.attr, |
| &dev_attr_ocp_tpu_cap.attr, |
| &dev_attr_ocp_gpu_cap.attr, |
| &dev_attr_soft_ocp_cpu1_cap.attr, |
| &dev_attr_soft_ocp_cpu2_cap.attr, |
| &dev_attr_soft_ocp_tpu_cap.attr, |
| &dev_attr_soft_ocp_gpu_cap.attr, |
| &dev_attr_vdroop1_cap.attr, |
| &dev_attr_vdroop2_cap.attr, |
| &dev_attr_batoilo_cap.attr, |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| &dev_attr_batoilo2_cap.attr, |
| #endif |
| NULL, |
| }; |
| |
| static const struct attribute_group triggered_capacity_group = { |
| .attrs = triggered_cap_attrs, |
| .name = "last_triggered_capacity", |
| }; |
| |
| static struct attribute *triggered_volt_attrs[] = { |
| &dev_attr_smpl_warn_volt.attr, |
| &dev_attr_ocp_cpu1_volt.attr, |
| &dev_attr_ocp_cpu2_volt.attr, |
| &dev_attr_ocp_tpu_volt.attr, |
| &dev_attr_ocp_gpu_volt.attr, |
| &dev_attr_soft_ocp_cpu1_volt.attr, |
| &dev_attr_soft_ocp_cpu2_volt.attr, |
| &dev_attr_soft_ocp_tpu_volt.attr, |
| &dev_attr_soft_ocp_gpu_volt.attr, |
| &dev_attr_vdroop1_volt.attr, |
| &dev_attr_vdroop2_volt.attr, |
| &dev_attr_batoilo_volt.attr, |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| &dev_attr_batoilo2_volt.attr, |
| #endif |
| NULL, |
| }; |
| |
| static const struct attribute_group triggered_voltage_group = { |
| .attrs = triggered_volt_attrs, |
| .name = "last_triggered_voltage", |
| }; |
| |
| static struct attribute *last_triggered_mode_attrs[] = { |
| &dev_attr_last_triggered_uvlo1_start_cnt.attr, |
| &dev_attr_last_triggered_uvlo1_start_time.attr, |
| &dev_attr_last_triggered_uvlo1_light_cnt.attr, |
| &dev_attr_last_triggered_uvlo1_light_time.attr, |
| &dev_attr_last_triggered_uvlo1_medium_cnt.attr, |
| &dev_attr_last_triggered_uvlo1_medium_time.attr, |
| &dev_attr_last_triggered_uvlo1_heavy_cnt.attr, |
| &dev_attr_last_triggered_uvlo1_heavy_time.attr, |
| &dev_attr_last_triggered_uvlo2_start_cnt.attr, |
| &dev_attr_last_triggered_uvlo2_start_time.attr, |
| &dev_attr_last_triggered_uvlo2_light_cnt.attr, |
| &dev_attr_last_triggered_uvlo2_light_time.attr, |
| &dev_attr_last_triggered_uvlo2_medium_cnt.attr, |
| &dev_attr_last_triggered_uvlo2_medium_time.attr, |
| &dev_attr_last_triggered_uvlo2_heavy_cnt.attr, |
| &dev_attr_last_triggered_uvlo2_heavy_time.attr, |
| &dev_attr_last_triggered_batoilo_start_cnt.attr, |
| &dev_attr_last_triggered_batoilo_start_time.attr, |
| &dev_attr_last_triggered_batoilo_light_cnt.attr, |
| &dev_attr_last_triggered_batoilo_light_time.attr, |
| &dev_attr_last_triggered_batoilo_medium_cnt.attr, |
| &dev_attr_last_triggered_batoilo_medium_time.attr, |
| &dev_attr_last_triggered_batoilo_heavy_cnt.attr, |
| &dev_attr_last_triggered_batoilo_heavy_time.attr, |
| &dev_attr_last_triggered_batoilo2_start_cnt.attr, |
| &dev_attr_last_triggered_batoilo2_start_time.attr, |
| &dev_attr_last_triggered_batoilo2_light_cnt.attr, |
| &dev_attr_last_triggered_batoilo2_light_time.attr, |
| &dev_attr_last_triggered_batoilo2_medium_cnt.attr, |
| &dev_attr_last_triggered_batoilo2_medium_time.attr, |
| &dev_attr_last_triggered_batoilo2_heavy_cnt.attr, |
| &dev_attr_last_triggered_batoilo2_heavy_time.attr, |
| NULL, |
| }; |
| |
| static const struct attribute_group last_triggered_mode_group = { |
| .attrs = last_triggered_mode_attrs, |
| .name = "last_triggered_mode", |
| }; |
| |
| static ssize_t vdroop_flt_show(struct bcl_device *bcl_dev, int idx, char *buf) |
| { |
| unsigned int reg = 0; |
| int ret; |
| |
| if (!bcl_dev) |
| return -EIO; |
| switch (idx) { |
| case SUBSYSTEM_TPU: |
| case SUBSYSTEM_GPU: |
| return sysfs_emit(buf, "0x%x\n", bcl_dev->core_conf[idx].vdroop_flt); |
| case SUBSYSTEM_CPU1: |
| case SUBSYSTEM_CPU2: |
| ret = cpu_buff_read(bcl_dev, idx, CPU_BUFF_VDROOP_FLT, ®); |
| if (ret < 0) |
| return ret; |
| break; |
| } |
| return sysfs_emit(buf, "0x%x\n", reg); |
| } |
| |
| static ssize_t vdroop_flt_store(struct bcl_device *bcl_dev, int idx, |
| const char *buf, size_t size) |
| { |
| unsigned int value; |
| int ret; |
| |
| if (sscanf(buf, "0x%x", &value) != 1) |
| return -EINVAL; |
| |
| if (!bcl_dev) |
| return -EIO; |
| switch (idx) { |
| case SUBSYSTEM_TPU: |
| case SUBSYSTEM_GPU: |
| bcl_dev->core_conf[idx].vdroop_flt = value; |
| return size; |
| case SUBSYSTEM_CPU1: |
| case SUBSYSTEM_CPU2: |
| ret = cpu_buff_write(bcl_dev, idx, CPU_BUFF_VDROOP_FLT, value); |
| if (ret < 0) |
| return ret; |
| } |
| return size; |
| } |
| |
| static ssize_t cpu1_vdroop_flt_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return vdroop_flt_show(bcl_dev, SUBSYSTEM_CPU1, buf); |
| } |
| |
| static ssize_t cpu1_vdroop_flt_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return vdroop_flt_store(bcl_dev, SUBSYSTEM_CPU1, buf, size); |
| } |
| |
| static DEVICE_ATTR_RW(cpu1_vdroop_flt); |
| |
| static ssize_t cpu2_vdroop_flt_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return vdroop_flt_show(bcl_dev, SUBSYSTEM_CPU2, buf); |
| } |
| |
| static ssize_t cpu2_vdroop_flt_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return vdroop_flt_store(bcl_dev, SUBSYSTEM_CPU2, buf, size); |
| } |
| |
| static DEVICE_ATTR_RW(cpu2_vdroop_flt); |
| |
| static ssize_t tpu_vdroop_flt_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return vdroop_flt_show(bcl_dev, SUBSYSTEM_TPU, buf); |
| } |
| |
| static ssize_t tpu_vdroop_flt_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return vdroop_flt_store(bcl_dev, SUBSYSTEM_TPU, buf, size); |
| } |
| |
| static DEVICE_ATTR_RW(tpu_vdroop_flt); |
| |
| static ssize_t gpu_vdroop_flt_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return vdroop_flt_show(bcl_dev, SUBSYSTEM_GPU, buf); |
| } |
| |
| static ssize_t gpu_vdroop_flt_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return vdroop_flt_store(bcl_dev, SUBSYSTEM_GPU, buf, size); |
| } |
| |
| static DEVICE_ATTR_RW(gpu_vdroop_flt); |
| |
| static struct attribute *vdroop_flt_attrs[] = { |
| &dev_attr_cpu1_vdroop_flt.attr, |
| &dev_attr_cpu2_vdroop_flt.attr, |
| &dev_attr_tpu_vdroop_flt.attr, |
| &dev_attr_gpu_vdroop_flt.attr, |
| NULL, |
| }; |
| |
| static const struct attribute_group vdroop_flt_group = { |
| .attrs = vdroop_flt_attrs, |
| .name = "vdroop_flt", |
| }; |
| |
| static ssize_t main_pwrwarn_threshold_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| int ret, idx; |
| |
| #if IS_ENABLED(CONFIG_REGULATOR_S2MPG12) || IS_ENABLED(CONFIG_REGULATOR_S2MPG10) |
| return -ENODEV; |
| #endif |
| |
| ret = sscanf(attr->attr.name, "main_pwrwarn_threshold%d", &idx); |
| if (ret != 1) |
| return -EINVAL; |
| if (idx >= METER_CHANNEL_MAX || idx < 0) |
| return -EINVAL; |
| |
| return sysfs_emit(buf, "%d=%lld\n", bcl_dev->main_setting[idx], bcl_dev->main_limit[idx]); |
| } |
| |
| static ssize_t main_pwrwarn_threshold_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| int ret, idx, value; |
| |
| #if IS_ENABLED(CONFIG_REGULATOR_S2MPG12) || IS_ENABLED(CONFIG_REGULATOR_S2MPG10) |
| return -ENODEV; |
| #endif |
| |
| ret = kstrtou32(buf, 10, &value); |
| if (ret) |
| return ret; |
| ret = sscanf(attr->attr.name, "main_pwrwarn_threshold%d", &idx); |
| if (ret != 1) |
| return -EINVAL; |
| if (idx >= METER_CHANNEL_MAX || idx < 0) |
| return -EINVAL; |
| |
| bcl_dev->main_setting[idx] = value; |
| bcl_dev->main_limit[idx] = settings_to_current(bcl_dev, CORE_PMIC_MAIN, idx, |
| value << LPF_CURRENT_SHIFT); |
| meter_write(CORE_PMIC_MAIN, bcl_dev, MAIN_METER_PWR_WARN0 + idx, value); |
| |
| return size; |
| } |
| |
| static ssize_t sub_pwrwarn_threshold_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| int ret, idx; |
| |
| #if IS_ENABLED(CONFIG_REGULATOR_S2MPG12) || IS_ENABLED(CONFIG_REGULATOR_S2MPG10) |
| return -ENODEV; |
| #endif |
| |
| ret = sscanf(attr->attr.name, "sub_pwrwarn_threshold%d", &idx); |
| if (ret != 1) |
| return -EINVAL; |
| if (idx >= METER_CHANNEL_MAX || idx < 0) |
| return -EINVAL; |
| |
| return sysfs_emit(buf, "%d=%lld\n", bcl_dev->sub_setting[idx], bcl_dev->sub_limit[idx]); |
| } |
| |
| static ssize_t sub_pwrwarn_threshold_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| int ret, idx, value; |
| |
| #if IS_ENABLED(CONFIG_REGULATOR_S2MPG12) || IS_ENABLED(CONFIG_REGULATOR_S2MPG10) |
| return -ENODEV; |
| #endif |
| |
| ret = kstrtou32(buf, 10, &value); |
| if (ret) |
| return ret; |
| ret = sscanf(attr->attr.name, "sub_pwrwarn_threshold%d", &idx); |
| if (ret != 1) |
| return -EINVAL; |
| if (idx >= METER_CHANNEL_MAX || idx < 0) |
| return -EINVAL; |
| |
| bcl_dev->sub_setting[idx] = value; |
| bcl_dev->sub_limit[idx] = settings_to_current(bcl_dev, CORE_PMIC_SUB, idx, |
| value << LPF_CURRENT_SHIFT); |
| meter_write(CORE_PMIC_SUB, bcl_dev, SUB_METER_PWR_WARN0 + idx, value); |
| |
| return size; |
| } |
| |
| #define DEVICE_PWRWARN_ATTR(_name, _num) \ |
| struct device_attribute attr_##_name##_num = \ |
| __ATTR(_name##_num, 0644, _name##_show, _name##_store) |
| |
| static DEVICE_PWRWARN_ATTR(main_pwrwarn_threshold, 0); |
| static DEVICE_PWRWARN_ATTR(main_pwrwarn_threshold, 1); |
| static DEVICE_PWRWARN_ATTR(main_pwrwarn_threshold, 2); |
| static DEVICE_PWRWARN_ATTR(main_pwrwarn_threshold, 3); |
| static DEVICE_PWRWARN_ATTR(main_pwrwarn_threshold, 4); |
| static DEVICE_PWRWARN_ATTR(main_pwrwarn_threshold, 5); |
| static DEVICE_PWRWARN_ATTR(main_pwrwarn_threshold, 6); |
| static DEVICE_PWRWARN_ATTR(main_pwrwarn_threshold, 7); |
| static DEVICE_PWRWARN_ATTR(main_pwrwarn_threshold, 8); |
| static DEVICE_PWRWARN_ATTR(main_pwrwarn_threshold, 9); |
| static DEVICE_PWRWARN_ATTR(main_pwrwarn_threshold, 10); |
| static DEVICE_PWRWARN_ATTR(main_pwrwarn_threshold, 11); |
| |
| static struct attribute *main_pwrwarn_attrs[] = { |
| &attr_main_pwrwarn_threshold0.attr, |
| &attr_main_pwrwarn_threshold1.attr, |
| &attr_main_pwrwarn_threshold2.attr, |
| &attr_main_pwrwarn_threshold3.attr, |
| &attr_main_pwrwarn_threshold4.attr, |
| &attr_main_pwrwarn_threshold5.attr, |
| &attr_main_pwrwarn_threshold6.attr, |
| &attr_main_pwrwarn_threshold7.attr, |
| &attr_main_pwrwarn_threshold8.attr, |
| &attr_main_pwrwarn_threshold9.attr, |
| &attr_main_pwrwarn_threshold10.attr, |
| &attr_main_pwrwarn_threshold11.attr, |
| NULL, |
| }; |
| |
| static DEVICE_PWRWARN_ATTR(sub_pwrwarn_threshold, 0); |
| static DEVICE_PWRWARN_ATTR(sub_pwrwarn_threshold, 1); |
| static DEVICE_PWRWARN_ATTR(sub_pwrwarn_threshold, 2); |
| static DEVICE_PWRWARN_ATTR(sub_pwrwarn_threshold, 3); |
| static DEVICE_PWRWARN_ATTR(sub_pwrwarn_threshold, 4); |
| static DEVICE_PWRWARN_ATTR(sub_pwrwarn_threshold, 5); |
| static DEVICE_PWRWARN_ATTR(sub_pwrwarn_threshold, 6); |
| static DEVICE_PWRWARN_ATTR(sub_pwrwarn_threshold, 7); |
| static DEVICE_PWRWARN_ATTR(sub_pwrwarn_threshold, 8); |
| static DEVICE_PWRWARN_ATTR(sub_pwrwarn_threshold, 9); |
| static DEVICE_PWRWARN_ATTR(sub_pwrwarn_threshold, 10); |
| static DEVICE_PWRWARN_ATTR(sub_pwrwarn_threshold, 11); |
| |
| static struct attribute *sub_pwrwarn_attrs[] = { |
| &attr_sub_pwrwarn_threshold0.attr, |
| &attr_sub_pwrwarn_threshold1.attr, |
| &attr_sub_pwrwarn_threshold2.attr, |
| &attr_sub_pwrwarn_threshold3.attr, |
| &attr_sub_pwrwarn_threshold4.attr, |
| &attr_sub_pwrwarn_threshold5.attr, |
| &attr_sub_pwrwarn_threshold6.attr, |
| &attr_sub_pwrwarn_threshold7.attr, |
| &attr_sub_pwrwarn_threshold8.attr, |
| &attr_sub_pwrwarn_threshold9.attr, |
| &attr_sub_pwrwarn_threshold10.attr, |
| &attr_sub_pwrwarn_threshold11.attr, |
| NULL, |
| }; |
| |
| static ssize_t qos_show(struct bcl_device *bcl_dev, int idx, char *buf) |
| { |
| struct bcl_zone *zone; |
| |
| if (!bcl_dev) |
| return -EIO; |
| zone = bcl_dev->zone[idx]; |
| if ((!zone) || (!zone->bcl_qos)) |
| return -EIO; |
| |
| return sysfs_emit(buf, "CPU0,CPU1,CPU2,GPU,TPU\n%d,%d,%d,%d,%d\n", |
| zone->bcl_qos->cpu0_limit, |
| zone->bcl_qos->cpu1_limit, |
| zone->bcl_qos->cpu2_limit, |
| zone->bcl_qos->gpu_limit, |
| zone->bcl_qos->tpu_limit); |
| } |
| |
| static ssize_t qos_store(struct bcl_device *bcl_dev, int idx, const char *buf, size_t size) |
| { |
| unsigned int cpu0, cpu1, cpu2, gpu, tpu; |
| struct bcl_zone *zone; |
| |
| if (sscanf(buf, "%d,%d,%d,%d,%d", &cpu0, &cpu1, &cpu2, &gpu, &tpu) != 5) |
| return -EINVAL; |
| if (!bcl_dev) |
| return -EIO; |
| zone = bcl_dev->zone[idx]; |
| if ((!zone) || (!zone->bcl_qos)) |
| return -EIO; |
| zone->bcl_qos->cpu0_limit = cpu0; |
| zone->bcl_qos->cpu1_limit = cpu1; |
| zone->bcl_qos->cpu2_limit = cpu2; |
| zone->bcl_qos->gpu_limit = gpu; |
| zone->bcl_qos->tpu_limit = tpu; |
| |
| return size; |
| } |
| |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| static ssize_t qos_batoilo2_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_show(bcl_dev, BATOILO2, buf); |
| } |
| |
| static ssize_t qos_batoilo2_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_store(bcl_dev, BATOILO2, buf, size); |
| } |
| #endif |
| |
| static ssize_t qos_batoilo_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_show(bcl_dev, BATOILO, buf); |
| } |
| |
| static ssize_t qos_batoilo_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_store(bcl_dev, BATOILO, buf, size); |
| } |
| |
| static ssize_t qos_vdroop1_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_show(bcl_dev, UVLO1, buf); |
| } |
| |
| static ssize_t qos_vdroop1_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_store(bcl_dev, UVLO1, buf, size); |
| } |
| |
| static ssize_t qos_vdroop2_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_show(bcl_dev, UVLO2, buf); |
| } |
| |
| static ssize_t qos_vdroop2_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_store(bcl_dev, UVLO2, buf, size); |
| } |
| |
| static ssize_t qos_smpl_warn_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_show(bcl_dev, SMPL_WARN, buf); |
| } |
| |
| static ssize_t qos_smpl_warn_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_store(bcl_dev, SMPL_WARN, buf, size); |
| } |
| |
| static ssize_t qos_ocp_cpu2_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_show(bcl_dev, OCP_WARN_CPUCL2, buf); |
| } |
| |
| static ssize_t qos_ocp_cpu2_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_store(bcl_dev, OCP_WARN_CPUCL2, buf, size); |
| } |
| |
| static ssize_t qos_ocp_cpu1_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_show(bcl_dev, OCP_WARN_CPUCL1, buf); |
| } |
| |
| static ssize_t qos_ocp_cpu1_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_store(bcl_dev, OCP_WARN_CPUCL1, buf, size); |
| } |
| |
| static ssize_t qos_ocp_tpu_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_show(bcl_dev, OCP_WARN_TPU, buf); |
| } |
| |
| static ssize_t qos_ocp_tpu_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_store(bcl_dev, OCP_WARN_TPU, buf, size); |
| } |
| |
| static ssize_t qos_ocp_gpu_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_show(bcl_dev, OCP_WARN_GPU, buf); |
| } |
| |
| static ssize_t qos_ocp_gpu_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return qos_store(bcl_dev, OCP_WARN_GPU, buf, size); |
| } |
| |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| static DEVICE_ATTR_RW(qos_batoilo2); |
| #endif |
| static DEVICE_ATTR_RW(qos_batoilo); |
| static DEVICE_ATTR_RW(qos_vdroop1); |
| static DEVICE_ATTR_RW(qos_vdroop2); |
| static DEVICE_ATTR_RW(qos_smpl_warn); |
| static DEVICE_ATTR_RW(qos_ocp_cpu2); |
| static DEVICE_ATTR_RW(qos_ocp_cpu1); |
| static DEVICE_ATTR_RW(qos_ocp_gpu); |
| static DEVICE_ATTR_RW(qos_ocp_tpu); |
| |
| static struct attribute *qos_attrs[] = { |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| &dev_attr_qos_batoilo2.attr, |
| #endif |
| &dev_attr_qos_batoilo.attr, |
| &dev_attr_qos_vdroop1.attr, |
| &dev_attr_qos_vdroop2.attr, |
| &dev_attr_qos_smpl_warn.attr, |
| &dev_attr_qos_ocp_cpu2.attr, |
| &dev_attr_qos_ocp_cpu1.attr, |
| &dev_attr_qos_ocp_gpu.attr, |
| &dev_attr_qos_ocp_tpu.attr, |
| NULL, |
| }; |
| |
| static const struct attribute_group main_pwrwarn_group = { |
| .attrs = main_pwrwarn_attrs, |
| .name = "main_pwrwarn", |
| }; |
| |
| static const struct attribute_group sub_pwrwarn_group = { |
| .attrs = sub_pwrwarn_attrs, |
| .name = "sub_pwrwarn", |
| }; |
| |
| static ssize_t less_than_5ms_count_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| int irq_count, batt_idx, pwrwarn_idx; |
| ssize_t count = 0; |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| #if IS_ENABLED(CONFIG_REGULATOR_S2MPG12) || IS_ENABLED(CONFIG_REGULATOR_S2MPG10) |
| return -ENODEV; |
| #endif |
| |
| for (batt_idx = 0; batt_idx < MAX_BCL_BATT_IRQ; batt_idx++) { |
| for (pwrwarn_idx = 0; pwrwarn_idx < MAX_CONCURRENT_PWRWARN_IRQ; pwrwarn_idx++) { |
| irq_count = atomic_read(&bcl_dev->ifpmic_irq_bins[batt_idx][pwrwarn_idx] |
| .lt_5ms_count); |
| count += scnprintf(buf + count, PAGE_SIZE - count, |
| "%s + %s: %i\n", |
| batt_irq_names[batt_idx], |
| concurrent_pwrwarn_irq_names[pwrwarn_idx], |
| irq_count); |
| } |
| } |
| for (pwrwarn_idx = 0; pwrwarn_idx < METER_CHANNEL_MAX; pwrwarn_idx++) { |
| irq_count = atomic_read(&bcl_dev->pwrwarn_main_irq_bins[pwrwarn_idx].lt_5ms_count); |
| count += scnprintf(buf + count, PAGE_SIZE - count, |
| "main CH%d[%s]: %i\n", |
| pwrwarn_idx, |
| bcl_dev->main_rail_names[pwrwarn_idx], |
| irq_count); |
| } |
| for (pwrwarn_idx = 0; pwrwarn_idx < METER_CHANNEL_MAX; pwrwarn_idx++) { |
| irq_count = atomic_read(&bcl_dev->pwrwarn_sub_irq_bins[pwrwarn_idx].lt_5ms_count); |
| count += scnprintf(buf + count, PAGE_SIZE - count, |
| "sub CH%d[%s]: %i\n", |
| pwrwarn_idx, |
| bcl_dev->sub_rail_names[pwrwarn_idx], |
| irq_count); |
| } |
| return count; |
| } |
| |
| static DEVICE_ATTR_RO(less_than_5ms_count); |
| |
| static ssize_t between_5ms_to_10ms_count_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| int irq_count, batt_idx, pwrwarn_idx; |
| ssize_t count = 0; |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| #if IS_ENABLED(CONFIG_REGULATOR_S2MPG12) || IS_ENABLED(CONFIG_REGULATOR_S2MPG10) |
| return -ENODEV; |
| #endif |
| |
| for (batt_idx = 0; batt_idx < MAX_BCL_BATT_IRQ; batt_idx++) { |
| for (pwrwarn_idx = 0; pwrwarn_idx < MAX_CONCURRENT_PWRWARN_IRQ; pwrwarn_idx++) { |
| irq_count = atomic_read(&bcl_dev->ifpmic_irq_bins[batt_idx][pwrwarn_idx] |
| .bt_5ms_10ms_count); |
| count += scnprintf(buf + count, PAGE_SIZE - count, |
| "%s + %s: %i\n", |
| batt_irq_names[batt_idx], |
| concurrent_pwrwarn_irq_names[pwrwarn_idx], |
| irq_count); |
| } |
| } |
| for (pwrwarn_idx = 0; pwrwarn_idx < METER_CHANNEL_MAX; pwrwarn_idx++) { |
| irq_count = atomic_read(&bcl_dev->pwrwarn_main_irq_bins[pwrwarn_idx] |
| .bt_5ms_10ms_count); |
| count += scnprintf(buf + count, PAGE_SIZE - count, |
| "main CH%d[%s]: %i\n", |
| pwrwarn_idx, |
| bcl_dev->main_rail_names[pwrwarn_idx], |
| irq_count); |
| } |
| for (pwrwarn_idx = 0; pwrwarn_idx < METER_CHANNEL_MAX; pwrwarn_idx++) { |
| irq_count = atomic_read(&bcl_dev->pwrwarn_sub_irq_bins[pwrwarn_idx] |
| .bt_5ms_10ms_count); |
| count += scnprintf(buf + count, PAGE_SIZE - count, |
| "sub CH%d[%s]: %i\n", |
| pwrwarn_idx, |
| bcl_dev->sub_rail_names[pwrwarn_idx], |
| irq_count); |
| } |
| return count; |
| } |
| |
| static DEVICE_ATTR_RO(between_5ms_to_10ms_count); |
| |
| static ssize_t greater_than_10ms_count_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| int irq_count, batt_idx, pwrwarn_idx; |
| ssize_t count = 0; |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| #if IS_ENABLED(CONFIG_REGULATOR_S2MPG12) || IS_ENABLED(CONFIG_REGULATOR_S2MPG10) |
| return -ENODEV; |
| #endif |
| |
| for (batt_idx = 0; batt_idx < MAX_BCL_BATT_IRQ; batt_idx++) { |
| for (pwrwarn_idx = 0; pwrwarn_idx < MAX_CONCURRENT_PWRWARN_IRQ; pwrwarn_idx++) { |
| irq_count = atomic_read(&bcl_dev->ifpmic_irq_bins[batt_idx][pwrwarn_idx] |
| .gt_10ms_count); |
| count += scnprintf(buf + count, PAGE_SIZE - count, |
| "%s + %s: %i\n", |
| batt_irq_names[batt_idx], |
| concurrent_pwrwarn_irq_names[pwrwarn_idx], |
| irq_count); |
| } |
| } |
| for (pwrwarn_idx = 0; pwrwarn_idx < METER_CHANNEL_MAX; pwrwarn_idx++) { |
| irq_count = atomic_read(&bcl_dev->pwrwarn_main_irq_bins[pwrwarn_idx].gt_10ms_count); |
| count += scnprintf(buf + count, PAGE_SIZE - count, |
| "main CH%d[%s]: %i\n", |
| pwrwarn_idx, |
| bcl_dev->main_rail_names[pwrwarn_idx], |
| irq_count); |
| } |
| for (pwrwarn_idx = 0; pwrwarn_idx < METER_CHANNEL_MAX; pwrwarn_idx++) { |
| irq_count = atomic_read(&bcl_dev->pwrwarn_sub_irq_bins[pwrwarn_idx].gt_10ms_count); |
| count += scnprintf(buf + count, PAGE_SIZE - count, |
| "sub CH%d[%s]: %i\n", |
| pwrwarn_idx, |
| bcl_dev->sub_rail_names[pwrwarn_idx], |
| irq_count); |
| } |
| return count; |
| } |
| |
| static DEVICE_ATTR_RO(greater_than_10ms_count); |
| |
| static struct attribute *irq_dur_cnt_attrs[] = { |
| &dev_attr_less_than_5ms_count.attr, |
| &dev_attr_between_5ms_to_10ms_count.attr, |
| &dev_attr_greater_than_10ms_count.attr, |
| NULL, |
| }; |
| |
| static ssize_t disabled_store(struct bcl_zone *zone, bool disabled, size_t size) |
| { |
| if (disabled && !zone->disabled) { |
| zone->disabled = true; |
| disable_irq(zone->bcl_irq); |
| } else if (!disabled && zone->disabled) { |
| zone->disabled = false; |
| enable_irq(zone->bcl_irq); |
| } |
| return size; |
| } |
| |
| static ssize_t uvlo1_disabled_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[UVLO1]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d\n", bcl_dev->zone[UVLO1]->disabled); |
| } |
| |
| static ssize_t uvlo1_disabled_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| if (!bcl_dev->zone[UVLO1]) |
| return -ENODEV; |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| return disabled_store(bcl_dev->zone[UVLO1], value, size); |
| } |
| |
| static ssize_t uvlo2_disabled_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[UVLO2]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d\n", bcl_dev->zone[UVLO2]->disabled); |
| } |
| |
| static ssize_t uvlo2_disabled_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| if (!bcl_dev->zone[UVLO2]) |
| return -ENODEV; |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| return disabled_store(bcl_dev->zone[UVLO2], value, size); |
| } |
| |
| static ssize_t batoilo_disabled_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[BATOILO]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d\n", bcl_dev->zone[BATOILO]->disabled); |
| } |
| |
| static ssize_t batoilo_disabled_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| if (!bcl_dev->zone[BATOILO]) |
| return -ENODEV; |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| return disabled_store(bcl_dev->zone[BATOILO], value, size); |
| } |
| |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| static ssize_t batoilo2_disabled_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[BATOILO2]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d\n", bcl_dev->zone[BATOILO2]->disabled); |
| } |
| |
| static ssize_t batoilo2_disabled_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| if (!bcl_dev->zone[BATOILO2]) |
| return -ENODEV; |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| return disabled_store(bcl_dev->zone[BATOILO2], value, size); |
| } |
| #endif |
| |
| static ssize_t smpl_disabled_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[SMPL_WARN]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d\n", bcl_dev->zone[SMPL_WARN]->disabled); |
| } |
| |
| static ssize_t smpl_disabled_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| if (!bcl_dev->zone[SMPL_WARN]) |
| return -ENODEV; |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| return disabled_store(bcl_dev->zone[SMPL_WARN], value, size); |
| } |
| |
| static ssize_t ocp_cpu1_disabled_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[OCP_WARN_CPUCL1]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d\n", bcl_dev->zone[OCP_WARN_CPUCL1]->disabled); |
| } |
| |
| static ssize_t ocp_cpu1_disabled_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| if (!bcl_dev->zone[OCP_WARN_CPUCL1]) |
| return -ENODEV; |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| return disabled_store(bcl_dev->zone[OCP_WARN_CPUCL1], value, size); |
| } |
| |
| static ssize_t ocp_cpu2_disabled_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[OCP_WARN_CPUCL2]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d\n", bcl_dev->zone[OCP_WARN_CPUCL2]->disabled); |
| } |
| |
| static ssize_t ocp_cpu2_disabled_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| if (!bcl_dev->zone[OCP_WARN_CPUCL2]) |
| return -ENODEV; |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| return disabled_store(bcl_dev->zone[OCP_WARN_CPUCL2], value, size); |
| } |
| |
| static ssize_t ocp_tpu_disabled_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[OCP_WARN_TPU]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d\n", bcl_dev->zone[OCP_WARN_TPU]->disabled); |
| } |
| |
| static ssize_t ocp_tpu_disabled_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| if (!bcl_dev->zone[OCP_WARN_TPU]) |
| return -ENODEV; |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| return disabled_store(bcl_dev->zone[OCP_WARN_TPU], value, size); |
| } |
| |
| static ssize_t ocp_gpu_disabled_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[OCP_WARN_GPU]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d\n", bcl_dev->zone[OCP_WARN_GPU]->disabled); |
| } |
| |
| static ssize_t ocp_gpu_disabled_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| if (!bcl_dev->zone[OCP_WARN_GPU]) |
| return -ENODEV; |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| return disabled_store(bcl_dev->zone[OCP_WARN_GPU], value, size); |
| } |
| |
| static ssize_t soft_ocp_cpu1_disabled_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[SOFT_OCP_WARN_CPUCL1]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d\n", bcl_dev->zone[SOFT_OCP_WARN_CPUCL1]->disabled); |
| } |
| |
| static ssize_t soft_ocp_cpu1_disabled_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| if (!bcl_dev->zone[SOFT_OCP_WARN_CPUCL1]) |
| return -ENODEV; |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| return disabled_store(bcl_dev->zone[SOFT_OCP_WARN_CPUCL1], value, size); |
| } |
| |
| static ssize_t soft_ocp_cpu2_disabled_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[SOFT_OCP_WARN_CPUCL2]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d\n", bcl_dev->zone[SOFT_OCP_WARN_CPUCL2]->disabled); |
| } |
| |
| static ssize_t soft_ocp_cpu2_disabled_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| if (!bcl_dev->zone[SOFT_OCP_WARN_CPUCL2]) |
| return -ENODEV; |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| return disabled_store(bcl_dev->zone[SOFT_OCP_WARN_CPUCL2], value, size); |
| } |
| |
| static ssize_t soft_ocp_tpu_disabled_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[SOFT_OCP_WARN_TPU]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d\n", bcl_dev->zone[SOFT_OCP_WARN_TPU]->disabled); |
| } |
| |
| static ssize_t soft_ocp_tpu_disabled_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| if (!bcl_dev->zone[SOFT_OCP_WARN_TPU]) |
| return -ENODEV; |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| return disabled_store(bcl_dev->zone[SOFT_OCP_WARN_TPU], value, size); |
| } |
| |
| static ssize_t soft_ocp_gpu_disabled_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[SOFT_OCP_WARN_GPU]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d\n", bcl_dev->zone[SOFT_OCP_WARN_GPU]->disabled); |
| } |
| |
| static ssize_t soft_ocp_gpu_disabled_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| if (!bcl_dev->zone[SOFT_OCP_WARN_GPU]) |
| return -ENODEV; |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| return disabled_store(bcl_dev->zone[SOFT_OCP_WARN_GPU], value, size); |
| } |
| |
| static DEVICE_ATTR_RW(uvlo1_disabled); |
| static DEVICE_ATTR_RW(uvlo2_disabled); |
| static DEVICE_ATTR_RW(batoilo_disabled); |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| static DEVICE_ATTR_RW(batoilo2_disabled); |
| #endif |
| static DEVICE_ATTR_RW(smpl_disabled); |
| static DEVICE_ATTR_RW(ocp_cpu1_disabled); |
| static DEVICE_ATTR_RW(ocp_cpu2_disabled); |
| static DEVICE_ATTR_RW(ocp_tpu_disabled); |
| static DEVICE_ATTR_RW(ocp_gpu_disabled); |
| static DEVICE_ATTR_RW(soft_ocp_cpu1_disabled); |
| static DEVICE_ATTR_RW(soft_ocp_cpu2_disabled); |
| static DEVICE_ATTR_RW(soft_ocp_tpu_disabled); |
| static DEVICE_ATTR_RW(soft_ocp_gpu_disabled); |
| |
| static struct attribute *irq_config_attrs[] = { |
| &dev_attr_uvlo1_disabled.attr, |
| &dev_attr_uvlo2_disabled.attr, |
| &dev_attr_batoilo_disabled.attr, |
| #if IS_ENABLED(CONFIG_SOC_ZUMAPRO) |
| &dev_attr_batoilo2_disabled.attr, |
| #endif |
| &dev_attr_smpl_disabled.attr, |
| &dev_attr_ocp_cpu1_disabled.attr, |
| &dev_attr_ocp_cpu2_disabled.attr, |
| &dev_attr_ocp_tpu_disabled.attr, |
| &dev_attr_ocp_gpu_disabled.attr, |
| &dev_attr_soft_ocp_cpu1_disabled.attr, |
| &dev_attr_soft_ocp_cpu2_disabled.attr, |
| &dev_attr_soft_ocp_tpu_disabled.attr, |
| &dev_attr_soft_ocp_gpu_disabled.attr, |
| NULL, |
| }; |
| |
| int get_final_mitigation_module_ids(struct bcl_device *bcl_dev) { |
| int mitigation_module_ids = atomic_read(&bcl_dev->mitigation_module_ids); |
| int w = hweight32(mitigation_module_ids); |
| |
| if (w >= HEAVY_MITIGATION_MODULES_NUM || w == 0) |
| mitigation_module_ids |= bcl_dev->non_monitored_mitigation_module_ids; |
| |
| return mitigation_module_ids; |
| } |
| |
| static ssize_t uvlo1_triggered_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[UVLO1]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d_%d\n", bcl_dev->zone[UVLO1]->current_state, |
| get_final_mitigation_module_ids(bcl_dev)); |
| } |
| |
| static ssize_t uvlo2_triggered_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[UVLO2]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d_%d\n", bcl_dev->zone[UVLO2]->current_state, |
| get_final_mitigation_module_ids(bcl_dev)); |
| } |
| |
| static ssize_t oilo1_triggered_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[BATOILO]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d_%d\n", bcl_dev->zone[BATOILO]->current_state, |
| get_final_mitigation_module_ids(bcl_dev)); |
| } |
| |
| static ssize_t oilo2_triggered_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[BATOILO2]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d_%d\n", bcl_dev->zone[BATOILO2]->current_state, |
| get_final_mitigation_module_ids(bcl_dev)); |
| } |
| |
| static ssize_t smpl_triggered_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (!bcl_dev->zone[SMPL_WARN]) |
| return -ENODEV; |
| return sysfs_emit(buf, "%d_%d\n", bcl_dev->zone[SMPL_WARN]->current_state, |
| get_final_mitigation_module_ids(bcl_dev)); |
| } |
| |
| static DEVICE_ATTR(oilo1_triggered, 0444, oilo1_triggered_show, NULL); |
| static DEVICE_ATTR(oilo2_triggered, 0444, oilo2_triggered_show, NULL); |
| static DEVICE_ATTR(uvlo1_triggered, 0444, uvlo1_triggered_show, NULL); |
| static DEVICE_ATTR(uvlo2_triggered, 0444, uvlo2_triggered_show, NULL); |
| static DEVICE_ATTR(smpl_triggered, 0444, smpl_triggered_show, NULL); |
| |
| void bunch_mitigation_threshold_addr(struct bcl_mitigation_conf *mitigation_conf, |
| unsigned int *addr[METER_CHANNEL_MAX]) { |
| int i; |
| |
| #if IS_ENABLED(CONFIG_REGULATOR_S2MPG12) || IS_ENABLED(CONFIG_REGULATOR_S2MPG10) |
| return; |
| #endif |
| |
| for (i = 0; i < METER_CHANNEL_MAX; i++) |
| addr[i] = &mitigation_conf[i].threshold; |
| } |
| |
| void bunch_mitigation_module_id_addr(struct bcl_mitigation_conf *mitigation_conf, |
| unsigned int *addr[METER_CHANNEL_MAX]) { |
| int i; |
| |
| #if IS_ENABLED(CONFIG_REGULATOR_S2MPG12) || IS_ENABLED(CONFIG_REGULATOR_S2MPG10) |
| return; |
| #endif |
| |
| for (i = 0; i < METER_CHANNEL_MAX; i++) |
| addr[i] = &mitigation_conf[i].module_id; |
| } |
| |
| static ssize_t mitigation_show(unsigned int *addr[METER_CHANNEL_MAX], char *buf) |
| { |
| int i, at = 0; |
| |
| #if IS_ENABLED(CONFIG_REGULATOR_S2MPG12) || IS_ENABLED(CONFIG_REGULATOR_S2MPG10) |
| return -ENODEV; |
| #endif |
| |
| for (i = 0; i < METER_CHANNEL_MAX; i++) |
| at += sysfs_emit_at(buf, at, "%d,", *addr[i]); |
| |
| return at; |
| } |
| |
| static ssize_t mitigation_store(unsigned int *addr[METER_CHANNEL_MAX], |
| const char *buf, size_t size) { |
| int i; |
| unsigned int ch[METER_CHANNEL_MAX] = {0}; |
| char * const str = kstrndup(buf, size, GFP_KERNEL); |
| char *sep_str = str; |
| char *token = NULL; |
| |
| #if IS_ENABLED(CONFIG_REGULATOR_S2MPG12) || IS_ENABLED(CONFIG_REGULATOR_S2MPG10) |
| goto mitigation_store_exit; |
| #endif |
| |
| if (!sep_str) |
| goto mitigation_store_exit; |
| |
| for (i = 0; i < METER_CHANNEL_MAX; i++) { |
| token = strsep(&sep_str, MITIGATION_INPUT_DELIM); |
| if (!token || sscanf(token, "%d", &ch[i]) != 1) |
| break; |
| else |
| *addr[i] = ch[i]; |
| } |
| |
| mitigation_store_exit: |
| kfree(str); |
| |
| #if IS_ENABLED(CONFIG_REGULATOR_S2MPG12) || IS_ENABLED(CONFIG_REGULATOR_S2MPG10) |
| return -ENODEV; |
| #endif |
| return size; |
| } |
| |
| static ssize_t main_mitigation_threshold_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int *addr[METER_CHANNEL_MAX]; |
| |
| bunch_mitigation_threshold_addr(bcl_dev->main_mitigation_conf, addr); |
| |
| return mitigation_show(addr, buf); |
| } |
| |
| static ssize_t main_mitigation_threshold_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int *addr[METER_CHANNEL_MAX]; |
| |
| bunch_mitigation_threshold_addr(bcl_dev->main_mitigation_conf, addr); |
| |
| return mitigation_store(addr, buf, size); |
| } |
| |
| static ssize_t sub_mitigation_threshold_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int *addr[METER_CHANNEL_MAX]; |
| |
| bunch_mitigation_threshold_addr(bcl_dev->sub_mitigation_conf, addr); |
| |
| return mitigation_show(addr, buf); |
| } |
| |
| static ssize_t sub_mitigation_threshold_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int *addr[METER_CHANNEL_MAX]; |
| |
| bunch_mitigation_threshold_addr(bcl_dev->sub_mitigation_conf, addr); |
| |
| return mitigation_store(addr, buf, size); |
| } |
| |
| static ssize_t main_mitigation_module_id_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int *addr[METER_CHANNEL_MAX]; |
| |
| bunch_mitigation_module_id_addr(bcl_dev->main_mitigation_conf, addr); |
| |
| return mitigation_show(addr, buf); |
| } |
| |
| static ssize_t main_mitigation_module_id_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int *addr[METER_CHANNEL_MAX]; |
| |
| bunch_mitigation_module_id_addr(bcl_dev->main_mitigation_conf, addr); |
| |
| return mitigation_store(addr, buf, size); |
| } |
| |
| static ssize_t sub_mitigation_module_id_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int *addr[METER_CHANNEL_MAX]; |
| |
| bunch_mitigation_module_id_addr(bcl_dev->sub_mitigation_conf, addr); |
| |
| return mitigation_show(addr, buf); |
| } |
| |
| static ssize_t sub_mitigation_module_id_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| unsigned int *addr[METER_CHANNEL_MAX]; |
| |
| bunch_mitigation_module_id_addr(bcl_dev->sub_mitigation_conf, addr); |
| |
| return mitigation_store(addr, buf, size); |
| } |
| |
| static DEVICE_ATTR_RW(main_mitigation_threshold); |
| static DEVICE_ATTR_RW(sub_mitigation_threshold); |
| static DEVICE_ATTR_RW(main_mitigation_module_id); |
| static DEVICE_ATTR_RW(sub_mitigation_module_id); |
| |
| static struct attribute *mitigation_attrs[] = { |
| &dev_attr_main_mitigation_threshold.attr, |
| &dev_attr_sub_mitigation_threshold.attr, |
| &dev_attr_main_mitigation_module_id.attr, |
| &dev_attr_sub_mitigation_module_id.attr, |
| NULL, |
| }; |
| |
| static struct attribute *triggered_state_sq_attrs[] = { |
| &dev_attr_oilo1_triggered.attr, |
| &dev_attr_uvlo1_triggered.attr, |
| &dev_attr_uvlo2_triggered.attr, |
| &dev_attr_smpl_triggered.attr, |
| &dev_attr_oilo2_triggered.attr, |
| NULL, |
| }; |
| |
| static struct attribute *triggered_state_mw_attrs[] = { |
| &dev_attr_oilo1_triggered.attr, |
| &dev_attr_uvlo1_triggered.attr, |
| &dev_attr_uvlo2_triggered.attr, |
| &dev_attr_smpl_triggered.attr, |
| NULL, |
| }; |
| |
| static ssize_t triggered_idx_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%d\n", bcl_dev->triggered_idx); |
| } |
| |
| static DEVICE_ATTR(triggered_idx, 0444, triggered_idx_show, NULL); |
| |
| static ssize_t enable_br_stats_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| return sysfs_emit(buf, "%d\n", bcl_dev->enabled_br_stats); |
| } |
| |
| static ssize_t enable_br_stats_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| bool value; |
| int ret; |
| |
| if (!bcl_dev->data_logging_initialized) |
| return -EINVAL; |
| |
| ret = kstrtobool(buf, &value); |
| if (ret) |
| return ret; |
| |
| bcl_dev->enabled_br_stats = value; |
| |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(enable_br_stats); |
| |
| static ssize_t trigger_br_stats_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| return sysfs_emit(buf, ""); |
| } |
| |
| static ssize_t trigger_br_stats_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t size) |
| { |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| int value; |
| |
| if (!bcl_dev->data_logging_initialized) |
| return -EINVAL; |
| |
| if (kstrtouint(buf, 16, &value) < 0) |
| return -EINVAL; |
| |
| if (value > -1 && value < TRIGGERED_SOURCE_MAX) { |
| dev_info(bcl_dev->device, "Triggered: %d\n", value); |
| google_bcl_start_data_logging(bcl_dev, value); |
| } |
| |
| return size; |
| } |
| |
| static DEVICE_ATTR_RW(trigger_br_stats); |
| |
| static ssize_t meter_channels_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| return sysfs_emit(buf, "%d\n", METER_CHANNEL_MAX); |
| } |
| static DEVICE_ATTR_RO(meter_channels); |
| |
| static struct attribute *br_stats_attrs[] = { |
| &dev_attr_triggered_idx.attr, |
| &dev_attr_enable_br_stats.attr, |
| &dev_attr_trigger_br_stats.attr, |
| &dev_attr_meter_channels.attr, |
| NULL, |
| }; |
| |
| static ssize_t br_stats_dump_read(struct file *filp, |
| struct kobject *kobj, struct bin_attribute *attr, |
| char *buf, loff_t off, size_t count) |
| { |
| struct device *dev = container_of(kobj, struct device, kobj); |
| struct platform_device *pdev = container_of(dev, struct platform_device, dev); |
| struct bcl_device *bcl_dev = platform_get_drvdata(pdev); |
| |
| if (off > bcl_dev->br_stats_size) |
| return 0; |
| if (off + count > bcl_dev->br_stats_size) |
| count = bcl_dev->br_stats_size - off; |
| |
| memcpy(buf, (const void *)bcl_dev->br_stats + off, count); |
| |
| return count; |
| } |
| |
| static struct bin_attribute br_stats_dump_attr = { |
| .attr = { .name = "stats", .mode = 0444 }, |
| .read = br_stats_dump_read, |
| .size = sizeof(struct brownout_stats), |
| }; |
| |
| static struct bin_attribute *br_stats_bin_attrs[] = { |
| &br_stats_dump_attr, |
| NULL, |
| }; |
| |
| static const struct attribute_group irq_dur_cnt_group = { |
| .attrs = irq_dur_cnt_attrs, |
| .name = "irq_dur_cnt", |
| }; |
| |
| static const struct attribute_group qos_group = { |
| .attrs = qos_attrs, |
| .name = "qos", |
| }; |
| |
| static const struct attribute_group br_stats_group = { |
| .attrs = br_stats_attrs, |
| .bin_attrs = br_stats_bin_attrs, |
| .name = "br_stats", |
| }; |
| |
| static const struct attribute_group irq_config_group = { |
| .attrs = irq_config_attrs, |
| .name = "irq_config", |
| }; |
| |
| const struct attribute_group triggered_state_sq_group = { |
| .attrs = triggered_state_sq_attrs, |
| .name = "triggered_state", |
| }; |
| |
| const struct attribute_group triggered_state_mw_group = { |
| .attrs = triggered_state_mw_attrs, |
| .name = "triggered_state", |
| }; |
| |
| const struct attribute_group mitigation_group = { |
| .attrs = mitigation_attrs, |
| .name = "mitigation", |
| }; |
| |
| |
| const struct attribute_group *mitigation_mw_groups[] = { |
| &instr_group, |
| &triggered_lvl_group, |
| &clock_div_group, |
| &clock_ratio_group, |
| &clock_stats_group, |
| &triggered_count_group, |
| &triggered_timestamp_group, |
| &triggered_capacity_group, |
| &triggered_voltage_group, |
| &vdroop_flt_group, |
| &main_pwrwarn_group, |
| &sub_pwrwarn_group, |
| &irq_dur_cnt_group, |
| &qos_group, |
| &br_stats_group, |
| &last_triggered_mode_group, |
| &triggered_state_mw_group, |
| &irq_config_group, |
| NULL, |
| }; |
| |
| const struct attribute_group *mitigation_sq_groups[] = { |
| &instr_group, |
| &triggered_lvl_group, |
| &clock_div_group, |
| &clock_ratio_group, |
| &clock_stats_group, |
| &triggered_count_group, |
| &triggered_timestamp_group, |
| &triggered_capacity_group, |
| &triggered_voltage_group, |
| &vdroop_flt_group, |
| &main_pwrwarn_group, |
| &sub_pwrwarn_group, |
| &irq_dur_cnt_group, |
| &qos_group, |
| &br_stats_group, |
| &last_triggered_mode_group, |
| &triggered_state_sq_group, |
| &mitigation_group, |
| &irq_config_group, |
| NULL, |
| }; |