mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
platform: tegra: Remove actmon driver for Tegra194
The tegra-cactmon driver is only used for Tegra194 and given that the out-of-tree drivers are only supported for Tegra234 and newer devices we can remove this driver. Bug 4174107 Change-Id: I152e8119b5c179f2d75771c1af2eb5d5f865ccbc Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2927995 Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com> Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com> GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
committed by
mobile promotions
parent
7e764afb5f
commit
69b4420809
@@ -4,9 +4,6 @@
|
|||||||
tegra-bootloader-debug-objs := tegra_bootloader_debug.o
|
tegra-bootloader-debug-objs := tegra_bootloader_debug.o
|
||||||
obj-m += tegra-bootloader-debug.o
|
obj-m += tegra-bootloader-debug.o
|
||||||
|
|
||||||
tegra-cactmon-objs := cactmon.o
|
|
||||||
tegra-cactmon-objs += actmon_common.o
|
|
||||||
obj-m += tegra-cactmon.o
|
|
||||||
obj-m += tegra-cactmon-mc-all.o
|
obj-m += tegra-cactmon-mc-all.o
|
||||||
obj-m += tegra-fsicom.o
|
obj-m += tegra-fsicom.o
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,580 +0,0 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
|
||||||
// Copyright (c) 2022, NVIDIA CORPORATION, All rights reserved.
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/of_device.h>
|
|
||||||
#include <linux/reset.h>
|
|
||||||
#if IS_ENABLED(CONFIG_INTERCONNECT)
|
|
||||||
#include <linux/interconnect.h>
|
|
||||||
#include <dt-bindings/interconnect/tegra_icc_id.h>
|
|
||||||
#endif
|
|
||||||
#include <linux/platform/tegra/emc_bwmgr.h>
|
|
||||||
#include <linux/platform/tegra/actmon_common.h>
|
|
||||||
|
|
||||||
#include <linux/platform/tegra/mc_utils.h>
|
|
||||||
|
|
||||||
/************ START OF REG DEFINITION **************/
|
|
||||||
/* Actmon common registers */
|
|
||||||
#define ACTMON_GLB_CTRL 0x00
|
|
||||||
#define ACTMON_GLB_INT_EN 0x04
|
|
||||||
#define ACTMON_GLB_INT_STATUS 0x08
|
|
||||||
|
|
||||||
/* Actmon device registers */
|
|
||||||
/* ACTMON_*_CTRL_0 offset */
|
|
||||||
#define ACTMON_DEV_CTRL 0x00
|
|
||||||
/* ACTMON_*_CTRL_0 bit definitions */
|
|
||||||
#define ACTMON_DEV_CTRL_UP_WMARK_NUM_SHIFT 26
|
|
||||||
#define ACTMON_DEV_CTRL_UP_WMARK_NUM_MASK (0x7 << 26)
|
|
||||||
#define ACTMON_DEV_CTRL_DOWN_WMARK_NUM_SHIFT 21
|
|
||||||
#define ACTMON_DEV_CTRL_DOWN_WMARK_NUM_MASK (0x7 << 21)
|
|
||||||
#define ACTMON_DEV_CTRL_PERIODIC_ENB (0x1 << 13)
|
|
||||||
#define ACTMON_DEV_CTRL_K_VAL_SHIFT 10
|
|
||||||
#define ACTMON_DEV_CTRL_K_VAL_MASK (0x7 << 10)
|
|
||||||
|
|
||||||
/* ACTMON_*_INTR_ENABLE_0 */
|
|
||||||
#define ACTMON_DEV_INTR_ENB 0x04
|
|
||||||
/* ACTMON_*_INTR_ENABLE_0 bit definitions */
|
|
||||||
#define ACTMON_DEV_INTR_UP_WMARK_ENB (0x1 << 31)
|
|
||||||
#define ACTMON_DEV_INTR_DOWN_WMARK_ENB (0x1 << 30)
|
|
||||||
#define ACTMON_DEV_INTR_AVG_UP_WMARK_ENB (0x1 << 29)
|
|
||||||
#define ACTMON_DEV_INTR_AVG_DOWN_WMARK_ENB (0x1 << 28)
|
|
||||||
|
|
||||||
/* ACTMON_*_INTR_STAUS_0 */
|
|
||||||
#define ACTMON_DEV_INTR_STATUS 0x08
|
|
||||||
/* ACTMON_*_UPPER_WMARK_0 */
|
|
||||||
#define ACTMON_DEV_UP_WMARK 0x0c
|
|
||||||
/* ACTMON_*_LOWER_WMARK_0 */
|
|
||||||
#define ACTMON_DEV_DOWN_WMARK 0x10
|
|
||||||
/* ACTMON_*_AVG_UPPER_WMARK_0 */
|
|
||||||
#define ACTMON_DEV_AVG_UP_WMARK 0x14
|
|
||||||
/* ACTMON_*_AVG_LOWER_WMARK_0 */
|
|
||||||
#define ACTMON_DEV_AVG_DOWN_WMARK 0x18
|
|
||||||
/* ACTMON_*_AVG_INIT_AVG_0 */
|
|
||||||
#define ACTMON_DEV_INIT_AVG 0x1c
|
|
||||||
/* ACTMON_*_COUNT_0 */
|
|
||||||
#define ACTMON_DEV_COUNT 0x20
|
|
||||||
/* ACTMON_*_AVG_COUNT_0 */
|
|
||||||
#define ACTMON_DEV_AVG_COUNT 0x24
|
|
||||||
/* ACTMON_*_AVG_COUNT_WEIGHT_0 */
|
|
||||||
#define ACTMON_DEV_COUNT_WEGHT 0x28
|
|
||||||
/* ACTMON_*_CUMULATIVE_COUNT_0 */
|
|
||||||
#define ACTMON_DEV_CUMULATIVE_COUNT 0x2c
|
|
||||||
/************ END OF REG DEFINITION **************/
|
|
||||||
|
|
||||||
/******** start of actmon register operations **********/
|
|
||||||
static void set_prd(u32 val, void __iomem *base)
|
|
||||||
{
|
|
||||||
__raw_writel(val, base + ACTMON_GLB_CTRL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_glb_intr(u32 val, void __iomem *base)
|
|
||||||
{
|
|
||||||
__raw_writel(val, base + ACTMON_GLB_INT_EN);
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 get_glb_intr_st(void __iomem *base)
|
|
||||||
{
|
|
||||||
return __raw_readl(base + ACTMON_GLB_INT_STATUS);
|
|
||||||
}
|
|
||||||
/******** end of actmon register operations **********/
|
|
||||||
|
|
||||||
/*********start of actmon device register operations***********/
|
|
||||||
static void set_init_avg(u32 val, void __iomem *base)
|
|
||||||
{
|
|
||||||
__raw_writel(val, base + ACTMON_DEV_INIT_AVG);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_avg_up_wm(u32 val, void __iomem *base)
|
|
||||||
{
|
|
||||||
__raw_writel(val, base + ACTMON_DEV_AVG_UP_WMARK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_avg_dn_wm(u32 val, void __iomem *base)
|
|
||||||
{
|
|
||||||
__raw_writel(val, base + ACTMON_DEV_AVG_DOWN_WMARK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_dev_up_wm(u32 val, void __iomem *base)
|
|
||||||
{
|
|
||||||
__raw_writel(val, base + ACTMON_DEV_UP_WMARK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_dev_dn_wm(u32 val, void __iomem *base)
|
|
||||||
{
|
|
||||||
__raw_writel(val, base + ACTMON_DEV_DOWN_WMARK);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_cnt_wt(u32 val, void __iomem *base)
|
|
||||||
{
|
|
||||||
__raw_writel(val, base + ACTMON_DEV_COUNT_WEGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_intr_st(u32 val, void __iomem *base)
|
|
||||||
{
|
|
||||||
__raw_writel(val, base + ACTMON_DEV_INTR_STATUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 get_intr_st(void __iomem *base)
|
|
||||||
{
|
|
||||||
return __raw_readl(base + ACTMON_DEV_INTR_STATUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void init_dev_cntrl(struct actmon_dev *dev, void __iomem *base)
|
|
||||||
{
|
|
||||||
u32 val = 0;
|
|
||||||
|
|
||||||
val |= ACTMON_DEV_CTRL_PERIODIC_ENB;
|
|
||||||
val |= (((dev->avg_window_log2 - 1) << ACTMON_DEV_CTRL_K_VAL_SHIFT)
|
|
||||||
& ACTMON_DEV_CTRL_K_VAL_MASK);
|
|
||||||
val |= (((dev->down_wmark_window - 1) <<
|
|
||||||
ACTMON_DEV_CTRL_DOWN_WMARK_NUM_SHIFT) &
|
|
||||||
ACTMON_DEV_CTRL_DOWN_WMARK_NUM_MASK);
|
|
||||||
val |= (((dev->up_wmark_window - 1) <<
|
|
||||||
ACTMON_DEV_CTRL_UP_WMARK_NUM_SHIFT) &
|
|
||||||
ACTMON_DEV_CTRL_UP_WMARK_NUM_MASK);
|
|
||||||
|
|
||||||
__raw_writel(val, base + ACTMON_DEV_CTRL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void enb_dev_intr_all(void __iomem *base)
|
|
||||||
{
|
|
||||||
u32 val = 0;
|
|
||||||
|
|
||||||
val |= (ACTMON_DEV_INTR_UP_WMARK_ENB |
|
|
||||||
ACTMON_DEV_INTR_DOWN_WMARK_ENB |
|
|
||||||
ACTMON_DEV_INTR_AVG_UP_WMARK_ENB |
|
|
||||||
ACTMON_DEV_INTR_AVG_DOWN_WMARK_ENB);
|
|
||||||
|
|
||||||
__raw_writel(val, base + ACTMON_DEV_INTR_ENB);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void enb_dev_intr(u32 val, void __iomem *base)
|
|
||||||
{
|
|
||||||
__raw_writel(val, base + ACTMON_DEV_INTR_ENB);
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 get_dev_intr(void __iomem *base)
|
|
||||||
{
|
|
||||||
return __raw_readl(base + ACTMON_DEV_INTR_ENB);
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 get_avg_cnt(void __iomem *base)
|
|
||||||
{
|
|
||||||
return __raw_readl(base + ACTMON_DEV_AVG_COUNT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 get_raw_cnt(void __iomem *base)
|
|
||||||
{
|
|
||||||
return __raw_readl(base + ACTMON_DEV_COUNT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void enb_dev_wm(u32 *val)
|
|
||||||
{
|
|
||||||
*val |= (ACTMON_DEV_INTR_UP_WMARK_ENB |
|
|
||||||
ACTMON_DEV_INTR_DOWN_WMARK_ENB);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void disb_dev_up_wm(u32 *val)
|
|
||||||
{
|
|
||||||
*val &= ~ACTMON_DEV_INTR_UP_WMARK_ENB;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void disb_dev_dn_wm(u32 *val)
|
|
||||||
{
|
|
||||||
*val &= ~ACTMON_DEV_INTR_DOWN_WMARK_ENB;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********end of actmon device register operations***********/
|
|
||||||
|
|
||||||
static void actmon_dev_reg_ops_init(struct actmon_dev *adev)
|
|
||||||
{
|
|
||||||
adev->ops.set_init_avg = set_init_avg;
|
|
||||||
adev->ops.set_avg_up_wm = set_avg_up_wm;
|
|
||||||
adev->ops.set_avg_dn_wm = set_avg_dn_wm;
|
|
||||||
adev->ops.set_dev_up_wm = set_dev_up_wm;
|
|
||||||
adev->ops.set_dev_dn_wm = set_dev_dn_wm;
|
|
||||||
adev->ops.set_cnt_wt = set_cnt_wt;
|
|
||||||
adev->ops.set_intr_st = set_intr_st;
|
|
||||||
adev->ops.get_intr_st = get_intr_st;
|
|
||||||
adev->ops.init_dev_cntrl = init_dev_cntrl;
|
|
||||||
adev->ops.enb_dev_intr_all = enb_dev_intr_all;
|
|
||||||
adev->ops.enb_dev_intr = enb_dev_intr;
|
|
||||||
adev->ops.get_dev_intr_enb = get_dev_intr;
|
|
||||||
adev->ops.get_avg_cnt = get_avg_cnt;
|
|
||||||
adev->ops.get_raw_cnt = get_raw_cnt;
|
|
||||||
adev->ops.enb_dev_wm = enb_dev_wm;
|
|
||||||
adev->ops.disb_dev_up_wm = disb_dev_up_wm;
|
|
||||||
adev->ops.disb_dev_dn_wm = disb_dev_dn_wm;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long actmon_dev_get_max_rate(struct actmon_dev *adev)
|
|
||||||
{
|
|
||||||
unsigned long rate = 0;
|
|
||||||
|
|
||||||
if (!adev->bwmgr_disable)
|
|
||||||
return tegra_bwmgr_get_max_emc_rate();
|
|
||||||
|
|
||||||
if (adev->dram_clk_handle) {
|
|
||||||
rate = clk_round_rate(adev->dram_clk_handle, ULONG_MAX);
|
|
||||||
return rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long actmon_dev_get_rate(struct actmon_dev *adev)
|
|
||||||
{
|
|
||||||
unsigned long rate = 0;
|
|
||||||
|
|
||||||
if (!adev->bwmgr_disable)
|
|
||||||
return tegra_bwmgr_get_emc_rate();
|
|
||||||
|
|
||||||
if (adev->dram_clk_handle) {
|
|
||||||
rate = clk_get_rate(adev->dram_clk_handle);
|
|
||||||
return rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long actmon_dev_post_change_rate(
|
|
||||||
struct actmon_dev *adev, void *cclk)
|
|
||||||
{
|
|
||||||
struct clk_notifier_data *clk_data = cclk;
|
|
||||||
|
|
||||||
return clk_data->new_rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TBD: Use the implementation from mc_utils */
|
|
||||||
#if IS_ENABLED(CONFIG_INTERCONNECT)
|
|
||||||
#define BYTES_PER_CLK_PER_CH 4
|
|
||||||
#define CH_16 16
|
|
||||||
#define CH_16_BYTES_PER_CLK (BYTES_PER_CLK_PER_CH * CH_16)
|
|
||||||
|
|
||||||
unsigned long emc_freq_to_bw(unsigned long freq)
|
|
||||||
{
|
|
||||||
return freq * CH_16_BYTES_PER_CLK;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void icc_set_rate(struct actmon_dev *adev, unsigned long freq)
|
|
||||||
{
|
|
||||||
#if IS_ENABLED(CONFIG_INTERCONNECT)
|
|
||||||
struct icc_path *icc_path_handle = NULL;
|
|
||||||
u32 floor_bw_kbps = 0;
|
|
||||||
|
|
||||||
icc_path_handle = (struct icc_path *)adev->clnt;
|
|
||||||
floor_bw_kbps = emc_freq_to_bw(freq);
|
|
||||||
|
|
||||||
icc_set_bw(icc_path_handle, 0, floor_bw_kbps);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void actmon_dev_set_rate(struct actmon_dev *adev,
|
|
||||||
unsigned long freq)
|
|
||||||
{
|
|
||||||
struct tegra_bwmgr_client *bwclnt = NULL;
|
|
||||||
|
|
||||||
if (!adev->bwmgr_disable) {
|
|
||||||
bwclnt = (struct tegra_bwmgr_client *)adev->clnt;
|
|
||||||
|
|
||||||
tegra_bwmgr_set_emc(bwclnt, freq * 1000,
|
|
||||||
TEGRA_BWMGR_SET_EMC_FLOOR);
|
|
||||||
} else {
|
|
||||||
icc_set_rate(adev, freq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cactmon_bwmgr_register(
|
|
||||||
struct actmon_dev *adev, struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct tegra_bwmgr_client *bwclnt = (struct tegra_bwmgr_client *)
|
|
||||||
adev->clnt;
|
|
||||||
struct device *mon_dev = &pdev->dev;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
bwclnt = tegra_bwmgr_register(TEGRA_BWMGR_CLIENT_MON);
|
|
||||||
if (IS_ERR_OR_NULL(bwclnt)) {
|
|
||||||
ret = -ENODEV;
|
|
||||||
dev_err(mon_dev, "emc bw manager registration failed for %s\n",
|
|
||||||
adev->dn->name);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
adev->clnt = bwclnt;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void cactmon_bwmgr_unregister(
|
|
||||||
struct actmon_dev *adev, struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct tegra_bwmgr_client *bwclnt = (struct tegra_bwmgr_client *)
|
|
||||||
adev->clnt;
|
|
||||||
struct device *mon_dev = &pdev->dev;
|
|
||||||
|
|
||||||
if (bwclnt) {
|
|
||||||
dev_dbg(mon_dev, "unregistering BW manager for %s\n",
|
|
||||||
adev->dn->name);
|
|
||||||
tegra_bwmgr_unregister(bwclnt);
|
|
||||||
adev->clnt = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cactmon_icc_register(
|
|
||||||
struct actmon_dev *adev, struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_INTERCONNECT)
|
|
||||||
struct icc_path *icc_path_handle = NULL;
|
|
||||||
struct device *mon_dev = &pdev->dev;
|
|
||||||
|
|
||||||
icc_path_handle = icc_get(mon_dev, TEGRA_ICC_CACTMON, TEGRA_ICC_PRIMARY);
|
|
||||||
if (IS_ERR_OR_NULL(icc_path_handle)) {
|
|
||||||
ret = -ENODEV;
|
|
||||||
dev_err(mon_dev, "icc registration failed for %s\n",
|
|
||||||
adev->dn->name);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
adev->clnt = icc_path_handle;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cactmon_icc_unregister(
|
|
||||||
struct actmon_dev *adev, struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
#if IS_ENABLED(CONFIG_INTERCONNECT)
|
|
||||||
struct icc_path *icc_path_handle = (struct icc_path *)
|
|
||||||
adev->clnt;
|
|
||||||
struct device *mon_dev = &pdev->dev;
|
|
||||||
|
|
||||||
if (icc_path_handle) {
|
|
||||||
dev_dbg(mon_dev, "unregistering icc for %s\n",
|
|
||||||
adev->dn->name);
|
|
||||||
icc_put(icc_path_handle);
|
|
||||||
adev->clnt = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cactmon_register_bw(
|
|
||||||
struct actmon_dev *adev, struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (adev->bwmgr_disable)
|
|
||||||
ret = cactmon_icc_register(adev, pdev);
|
|
||||||
else
|
|
||||||
ret = cactmon_bwmgr_register(adev, pdev);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cactmon_unregister_bw(
|
|
||||||
struct actmon_dev *adev, struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
if (adev->bwmgr_disable)
|
|
||||||
cactmon_icc_unregister(adev, pdev);
|
|
||||||
else
|
|
||||||
cactmon_bwmgr_unregister(adev, pdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int actmon_dev_platform_init(struct actmon_dev *adev,
|
|
||||||
struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct tegra_bwmgr_client *bwclnt;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
ret = cactmon_register_bw(adev, pdev);
|
|
||||||
if (ret)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
adev->dev_name = adev->dn->name;
|
|
||||||
adev->max_freq = actmon_dev_get_max_rate(adev);
|
|
||||||
|
|
||||||
if (!adev->bwmgr_disable) {
|
|
||||||
bwclnt = (struct tegra_bwmgr_client *) adev->clnt;
|
|
||||||
tegra_bwmgr_set_emc(bwclnt, adev->max_freq,
|
|
||||||
TEGRA_BWMGR_SET_EMC_FLOOR);
|
|
||||||
} else {
|
|
||||||
icc_set_rate(adev, adev->max_freq);
|
|
||||||
}
|
|
||||||
|
|
||||||
adev->max_freq /= 1000;
|
|
||||||
actmon_dev_reg_ops_init(adev);
|
|
||||||
adev->actmon_dev_set_rate = actmon_dev_set_rate;
|
|
||||||
adev->actmon_dev_get_rate = actmon_dev_get_rate;
|
|
||||||
if (adev->rate_change_nb.notifier_call) {
|
|
||||||
if (!adev->bwmgr_disable)
|
|
||||||
ret = tegra_bwmgr_notifier_register(&adev->rate_change_nb);
|
|
||||||
else
|
|
||||||
ret = clk_notifier_register(adev->dram_clk_handle, &adev->rate_change_nb);
|
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
pr_err("Failed to register bw manager rate change notifier for %s\n",
|
|
||||||
adev->dev_name);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
adev->actmon_dev_post_change_rate = actmon_dev_post_change_rate;
|
|
||||||
end:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cactmon_free_resource(
|
|
||||||
struct actmon_dev *adev, struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (adev->rate_change_nb.notifier_call) {
|
|
||||||
if (!adev->bwmgr_disable)
|
|
||||||
ret = tegra_bwmgr_notifier_unregister(&adev->rate_change_nb);
|
|
||||||
else
|
|
||||||
ret = clk_notifier_unregister(adev->dram_clk_handle, &adev->rate_change_nb);
|
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
pr_err("Failed to register bw manager rate change notifier for %s\n",
|
|
||||||
adev->dev_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cactmon_unregister_bw(adev, pdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cactmon_reset_dinit(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct actmon_drv_data *actmon = platform_get_drvdata(pdev);
|
|
||||||
struct device *mon_dev = &pdev->dev;
|
|
||||||
int ret = -EINVAL;
|
|
||||||
|
|
||||||
if (actmon->actmon_rst) {
|
|
||||||
ret = reset_control_assert(actmon->actmon_rst);
|
|
||||||
if (ret)
|
|
||||||
dev_err(mon_dev, "failed to assert actmon\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cactmon_reset_init(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct actmon_drv_data *actmon = platform_get_drvdata(pdev);
|
|
||||||
struct device *mon_dev = &pdev->dev;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
actmon->actmon_rst = devm_reset_control_get(mon_dev, "actmon_rst");
|
|
||||||
if (IS_ERR(actmon->actmon_rst)) {
|
|
||||||
ret = PTR_ERR(actmon->actmon_rst);
|
|
||||||
dev_err(mon_dev, "can not get actmon reset%d\n", ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make actmon out of reset */
|
|
||||||
ret = reset_control_deassert(actmon->actmon_rst);
|
|
||||||
if (ret)
|
|
||||||
dev_err(mon_dev, "failed to deassert actmon\n");
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int cactmon_clk_disable(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct actmon_drv_data *actmon = platform_get_drvdata(pdev);
|
|
||||||
struct device *mon_dev = &pdev->dev;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (actmon->actmon_clk) {
|
|
||||||
clk_disable_unprepare(actmon->actmon_clk);
|
|
||||||
devm_clk_put(mon_dev, actmon->actmon_clk);
|
|
||||||
actmon->actmon_clk = NULL;
|
|
||||||
dev_dbg(mon_dev, "actmon clocks disabled\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cactmon_clk_enable(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct actmon_drv_data *actmon = platform_get_drvdata(pdev);
|
|
||||||
struct device *mon_dev = &pdev->dev;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
actmon->actmon_clk = devm_clk_get(mon_dev, "actmon");
|
|
||||||
if (IS_ERR_OR_NULL(actmon->actmon_clk)) {
|
|
||||||
dev_err(mon_dev, "unable to find actmon clock\n");
|
|
||||||
ret = PTR_ERR(actmon->actmon_clk);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = clk_prepare_enable(actmon->actmon_clk);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(mon_dev, "unable to enable actmon clock\n");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
actmon->freq = clk_get_rate(actmon->actmon_clk) / 1000;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
end:
|
|
||||||
devm_clk_put(mon_dev, actmon->actmon_clk);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct actmon_drv_data actmon_data = {
|
|
||||||
.clock_init = cactmon_clk_enable,
|
|
||||||
.clock_deinit = cactmon_clk_disable,
|
|
||||||
.reset_init = cactmon_reset_init,
|
|
||||||
.reset_deinit = cactmon_reset_dinit,
|
|
||||||
.dev_free_resource = cactmon_free_resource,
|
|
||||||
.actmon_dev_platform_init = actmon_dev_platform_init,
|
|
||||||
.ops.set_sample_prd = set_prd,
|
|
||||||
.ops.set_glb_intr = set_glb_intr,
|
|
||||||
.ops.get_glb_intr_st = get_glb_intr_st,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct of_device_id tegra_actmon_of_match[] = {
|
|
||||||
{ .compatible = "nvidia,tegra194-cactmon", .data = &actmon_data, },
|
|
||||||
{ .compatible = "nvidia,tegra186-cactmon", .data = &actmon_data, },
|
|
||||||
{ .compatible = "nvidia,tegra234-cactmon", .data = &actmon_data, },
|
|
||||||
{},
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init tegra_actmon_probe(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
const struct of_device_id *of_id;
|
|
||||||
struct actmon_drv_data *actmon;
|
|
||||||
|
|
||||||
of_id = of_match_node(tegra_actmon_of_match, pdev->dev.of_node);
|
|
||||||
if (of_id == NULL) {
|
|
||||||
pr_err("No matching of node\n");
|
|
||||||
ret = -ENODATA;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
actmon = (struct actmon_drv_data *)of_id->data;
|
|
||||||
platform_set_drvdata(pdev, actmon);
|
|
||||||
actmon->pdev = pdev;
|
|
||||||
ret = tegra_actmon_register(actmon);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct platform_driver tegra19x_actmon_driver __refdata = {
|
|
||||||
.probe = tegra_actmon_probe,
|
|
||||||
.remove = tegra_actmon_remove,
|
|
||||||
.driver = {
|
|
||||||
.name = "tegra_actmon",
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.of_match_table = of_match_ptr(tegra_actmon_of_match),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
module_platform_driver(tegra19x_actmon_driver);
|
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Central Tegra Activity Monitor");
|
|
||||||
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
|
|
||||||
MODULE_LICENSE("GPL v2");
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user