mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-23 09:42:19 +03:00
gpu: host1x: Enable general interrupts for actmon
Host1x general interrupts include actmon-related interrupts, axi timeout interrupts, and illegal access interrupts. This change enables actmon-related interrupts only. Bug 3788919 Signed-off-by: Johnny Liu <johnliu@nvidia.com> Change-Id: Iea1f1622a11afa72f70f8d10efebd857a51cc4e2 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2889825 Reviewed-by: Mikko Perttunen <mperttunen@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
8733469474
commit
03fd3f1188
@@ -249,35 +249,27 @@ static void host1x_actmon_deinit(struct host1x_actmon *actmon)
|
||||
|
||||
static void host1x_actmon_module_init(struct host1x_actmon_module *module)
|
||||
{
|
||||
struct host1x_actmon *actmon = module->actmon;
|
||||
u32 val;
|
||||
|
||||
/* Local control register */
|
||||
val = 0;
|
||||
val |= HOST1X_ACTMON_MODULE_CTRL_ACTMON_ENB(1);
|
||||
val |= HOST1X_ACTMON_MODULE_CTRL_ENB_PERIODIC(1);
|
||||
val |= HOST1X_ACTMON_MODULE_CTRL_K_VAL(module->k);
|
||||
val |= HOST1X_ACTMON_MODULE_CTRL_CONSEC_UPPER_NUM(module->consec_upper_num);
|
||||
val |= HOST1X_ACTMON_MODULE_CTRL_CONSEC_LOWER_NUM(module->consec_lower_num);
|
||||
actmon_module_writel(module, val, HOST1X_ACTMON_MODULE_CTRL_REG);
|
||||
actmon_module_writel(module,
|
||||
HOST1X_ACTMON_MODULE_CTRL_ACTMON_ENB(1) |
|
||||
HOST1X_ACTMON_MODULE_CTRL_ENB_PERIODIC(1) |
|
||||
HOST1X_ACTMON_MODULE_CTRL_K_VAL(module->k) |
|
||||
HOST1X_ACTMON_MODULE_CTRL_CONSEC_UPPER_NUM(module->consec_upper_num) |
|
||||
HOST1X_ACTMON_MODULE_CTRL_CONSEC_LOWER_NUM(module->consec_lower_num),
|
||||
HOST1X_ACTMON_MODULE_CTRL_REG);
|
||||
|
||||
/* Interrupt enable register */
|
||||
val = 0;
|
||||
val |= HOST1X_ACTMON_MODULE_INTR_AVG_BELOW_WORK_ENB(1);
|
||||
val |= HOST1X_ACTMON_MODULE_INTR_AVG_ABOVE_WORK_ENB(1);
|
||||
val |= HOST1X_ACTMON_MODULE_INTR_CONSEC_BELOW_WORK_ENB(1);
|
||||
val |= HOST1X_ACTMON_MODULE_INTR_CONSEC_ABOVE_WORK_ENB(1);
|
||||
actmon_module_writel(module, val, HOST1X_ACTMON_MODULE_INTR_ENB_REG);
|
||||
/* Interrupt enable register (disable interrupts by default) */
|
||||
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_INTR_ENB_REG);
|
||||
|
||||
/* Interrupt status register */
|
||||
actmon_module_writel(module, 0xffffffff, HOST1X_ACTMON_MODULE_INTR_STATUS_REG);
|
||||
actmon_module_writel(module, ~0, HOST1X_ACTMON_MODULE_INTR_STATUS_REG);
|
||||
|
||||
/* Consecutive watermark registers */
|
||||
actmon_module_writel(module, 0xffffffff, HOST1X_ACTMON_MODULE_UPPER_WMARK_REG);
|
||||
actmon_module_writel(module, ~0, HOST1X_ACTMON_MODULE_UPPER_WMARK_REG);
|
||||
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_LOWER_WMARK_REG);
|
||||
|
||||
/* Moving-average watermark registers */
|
||||
actmon_module_writel(module, 0xffffffff, HOST1X_ACTMON_MODULE_AVG_UPPER_WMARK_REG);
|
||||
actmon_module_writel(module, ~0, HOST1X_ACTMON_MODULE_AVG_UPPER_WMARK_REG);
|
||||
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_AVG_LOWER_WMARK_REG);
|
||||
|
||||
/* Init average value register */
|
||||
@@ -288,7 +280,7 @@ static void host1x_actmon_module_deinit(struct host1x_actmon_module *module)
|
||||
{
|
||||
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_CTRL_REG);
|
||||
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_INTR_ENB_REG);
|
||||
actmon_module_writel(module, 0xffffffff, HOST1X_ACTMON_MODULE_INTR_STATUS_REG);
|
||||
actmon_module_writel(module, ~0, HOST1X_ACTMON_MODULE_INTR_STATUS_REG);
|
||||
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_UPPER_WMARK_REG);
|
||||
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_LOWER_WMARK_REG);
|
||||
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_AVG_UPPER_WMARK_REG);
|
||||
@@ -297,6 +289,40 @@ static void host1x_actmon_module_deinit(struct host1x_actmon_module *module)
|
||||
actmon_module_writel(module, 0, HOST1X_ACTMON_MODULE_COUNT_WEIGHT_REG);
|
||||
}
|
||||
|
||||
void host1x_actmon_handle_interrupt(struct host1x *host, int classid)
|
||||
{
|
||||
unsigned long actmon_status, module_status;
|
||||
struct host1x_actmon_module *module;
|
||||
struct host1x_actmon *actmon;
|
||||
struct host1x_client *client;
|
||||
|
||||
list_for_each_entry(actmon, &host->actmons, list) {
|
||||
if (actmon->client->class == classid)
|
||||
break;
|
||||
}
|
||||
|
||||
client = actmon->client;
|
||||
module = &actmon->modules[HOST1X_ACTMON_MODULE_ACTIVE];
|
||||
|
||||
actmon_status = actmon_readl(actmon, HOST1X_ACTMON_INTR_STATUS_REG);
|
||||
module_status = actmon_module_readl(module, HOST1X_ACTMON_MODULE_INTR_STATUS_REG);
|
||||
|
||||
/* Trigger DFS if client supports it */
|
||||
if (!client->ops->actmon_event)
|
||||
;
|
||||
else if (module_status & HOST1X_ACTMON_MODULE_INTR_CONSEC_WMARK_ABOVE)
|
||||
client->ops->actmon_event(client, HOST1X_ACTMON_CONSEC_WMARK_ABOVE);
|
||||
else if (module_status & HOST1X_ACTMON_MODULE_INTR_CONSEC_WMARK_BELOW)
|
||||
client->ops->actmon_event(client, HOST1X_ACTMON_CONSEC_WMARK_BELOW);
|
||||
else if (module_status & HOST1X_ACTMON_MODULE_INTR_AVG_WMARK_ABOVE)
|
||||
client->ops->actmon_event(client, HOST1X_ACTMON_AVG_WMARK_ABOVE);
|
||||
else if (module_status & HOST1X_ACTMON_MODULE_INTR_AVG_WMARK_BELOW)
|
||||
client->ops->actmon_event(client, HOST1X_ACTMON_AVG_WMARK_BELOW);
|
||||
|
||||
actmon_module_writel(module, module_status, HOST1X_ACTMON_MODULE_INTR_STATUS_REG);
|
||||
actmon_writel(actmon, actmon_status, HOST1X_ACTMON_INTR_STATUS_REG);
|
||||
}
|
||||
|
||||
int host1x_actmon_register(struct host1x_client *client)
|
||||
{
|
||||
struct host1x *host = dev_get_drvdata(client->host->parent);
|
||||
@@ -304,6 +330,7 @@ int host1x_actmon_register(struct host1x_client *client)
|
||||
struct host1x_actmon_entry *entry = NULL;
|
||||
struct host1x_actmon_module *module;
|
||||
struct host1x_actmon *actmon;
|
||||
unsigned long flags;
|
||||
int i, err;
|
||||
|
||||
if (!host->actmon_regs || !host->actmon_clk)
|
||||
@@ -320,6 +347,12 @@ int host1x_actmon_register(struct host1x_client *client)
|
||||
if (!actmon)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&actmon->list);
|
||||
|
||||
spin_lock_irqsave(&host->actmons_lock, flags);
|
||||
list_add_tail(&actmon->list, &host->actmons);
|
||||
spin_unlock_irqrestore(&host->actmons_lock, flags);
|
||||
|
||||
actmon->client = client;
|
||||
actmon->rate = clk_get_rate(host->actmon_clk);
|
||||
actmon->regs = host->actmon_regs + entry->offset;
|
||||
@@ -361,6 +394,7 @@ int host1x_actmon_unregister(struct host1x_client *client)
|
||||
struct host1x_actmon_module *module;
|
||||
struct host1x *host = dev_get_drvdata(client->host->parent);
|
||||
struct host1x_actmon *actmon = client->actmon;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
if (!host->actmon_regs || !host->actmon_clk)
|
||||
@@ -379,6 +413,10 @@ int host1x_actmon_unregister(struct host1x_client *client)
|
||||
|
||||
host1x_actmon_deinit(actmon);
|
||||
|
||||
spin_lock_irqsave(&host->actmons_lock, flags);
|
||||
list_del(&actmon->list);
|
||||
spin_unlock_irqrestore(&host->actmons_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(host1x_actmon_unregister);
|
||||
|
||||
@@ -40,6 +40,11 @@ struct host1x_actmon {
|
||||
struct host1x_client *client;
|
||||
struct host1x_actmon_module modules[8];
|
||||
struct dentry *debugfs;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct host1x;
|
||||
|
||||
void host1x_actmon_handle_interrupt(struct host1x *host, int classid);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,11 @@ void host1x_common_writel(struct host1x *host1x, u32 v, u32 r)
|
||||
writel(v, host1x->common_regs + r);
|
||||
}
|
||||
|
||||
u32 host1x_common_readl(struct host1x *host1x, u32 r)
|
||||
{
|
||||
return readl(host1x->common_regs + r);
|
||||
}
|
||||
|
||||
void host1x_hypervisor_writel(struct host1x *host1x, u32 v, u32 r)
|
||||
{
|
||||
writel(v, host1x->hv_regs + r);
|
||||
@@ -832,8 +837,12 @@ static int host1x_probe(struct platform_device *pdev)
|
||||
if (host->syncpt_irq < 0)
|
||||
return host->syncpt_irq;
|
||||
|
||||
host->general_irq = platform_get_irq_byname_optional(pdev, "host1x");
|
||||
|
||||
mutex_init(&host->devices_lock);
|
||||
INIT_LIST_HEAD(&host->devices);
|
||||
spin_lock_init(&host->actmons_lock);
|
||||
INIT_LIST_HEAD(&host->actmons);
|
||||
INIT_LIST_HEAD(&host->list);
|
||||
host->dev = &pdev->dev;
|
||||
|
||||
@@ -849,6 +858,12 @@ static int host1x_probe(struct platform_device *pdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (host->general_irq > 0 && host->common_regs) {
|
||||
err = host1x_hw_intr_init_host_general(host);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = host1x_get_assigned_resources(host);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -979,6 +994,7 @@ static int __maybe_unused host1x_runtime_suspend(struct device *dev)
|
||||
struct host1x *host = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
host1x_hw_intr_disable_all_general_intrs(host);
|
||||
host1x_intr_stop(host);
|
||||
host1x_syncpt_save(host);
|
||||
|
||||
@@ -999,6 +1015,7 @@ static int __maybe_unused host1x_runtime_suspend(struct device *dev)
|
||||
resume_host1x:
|
||||
host1x_setup_virtualization_tables(host);
|
||||
host1x_syncpt_restore(host);
|
||||
host1x_hw_intr_enable_general_intrs(host);
|
||||
host1x_intr_start(host);
|
||||
|
||||
return err;
|
||||
@@ -1035,6 +1052,7 @@ static int __maybe_unused host1x_runtime_resume(struct device *dev)
|
||||
|
||||
host1x_setup_virtualization_tables(host);
|
||||
host1x_syncpt_restore(host);
|
||||
host1x_hw_intr_enable_general_intrs(host);
|
||||
host1x_intr_start(host);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#include "actmon.h"
|
||||
#include "cdma.h"
|
||||
#include "channel.h"
|
||||
#include "context.h"
|
||||
@@ -73,6 +74,12 @@ struct host1x_syncpt_ops {
|
||||
void (*enable_protection)(struct host1x *host);
|
||||
};
|
||||
|
||||
struct host1x_intr_general_ops {
|
||||
int (*init_host_general)(struct host1x *host);
|
||||
void (*enable_general_intrs)(struct host1x *host);
|
||||
void (*disable_all_general_intrs)(struct host1x *host);
|
||||
};
|
||||
|
||||
struct host1x_intr_ops {
|
||||
int (*init_host_sync)(struct host1x *host, u32 cpm);
|
||||
void (*set_syncpt_threshold)(
|
||||
@@ -142,6 +149,7 @@ struct host1x {
|
||||
void __iomem *common_regs;
|
||||
void __iomem *actmon_regs;
|
||||
int syncpt_irq;
|
||||
int general_irq;
|
||||
struct host1x_syncpt *syncpt;
|
||||
struct host1x_syncpt_base *bases;
|
||||
struct device *dev;
|
||||
@@ -166,6 +174,7 @@ struct host1x {
|
||||
struct mutex intr_mutex;
|
||||
|
||||
const struct host1x_syncpt_ops *syncpt_op;
|
||||
const struct host1x_intr_general_ops *intr_general_op;
|
||||
const struct host1x_intr_ops *intr_op;
|
||||
const struct host1x_channel_ops *channel_op;
|
||||
const struct host1x_cdma_ops *cdma_op;
|
||||
@@ -185,6 +194,9 @@ struct host1x {
|
||||
struct mutex devices_lock;
|
||||
struct list_head devices;
|
||||
|
||||
spinlock_t actmons_lock;
|
||||
struct list_head actmons;
|
||||
|
||||
struct list_head list;
|
||||
|
||||
struct device_dma_parameters dma_parms;
|
||||
@@ -193,6 +205,7 @@ struct host1x {
|
||||
};
|
||||
|
||||
void host1x_common_writel(struct host1x *host1x, u32 v, u32 r);
|
||||
u32 host1x_common_readl(struct host1x *host1x, u32 r);
|
||||
void host1x_hypervisor_writel(struct host1x *host1x, u32 r, u32 v);
|
||||
u32 host1x_hypervisor_readl(struct host1x *host1x, u32 r);
|
||||
void host1x_sync_writel(struct host1x *host1x, u32 r, u32 v);
|
||||
@@ -242,6 +255,30 @@ static inline void host1x_hw_syncpt_enable_protection(struct host1x *host)
|
||||
return host->syncpt_op->enable_protection(host);
|
||||
}
|
||||
|
||||
static inline int host1x_hw_intr_init_host_general(struct host1x *host)
|
||||
{
|
||||
if (!host->intr_general_op)
|
||||
return -EPERM;
|
||||
|
||||
return host->intr_general_op->init_host_general(host);
|
||||
}
|
||||
|
||||
static inline void host1x_hw_intr_enable_general_intrs(struct host1x *host)
|
||||
{
|
||||
if (!host->intr_general_op)
|
||||
return;
|
||||
|
||||
host->intr_general_op->enable_general_intrs(host);
|
||||
}
|
||||
|
||||
static inline void host1x_hw_intr_disable_all_general_intrs(struct host1x *host)
|
||||
{
|
||||
if (!host->intr_general_op)
|
||||
return;
|
||||
|
||||
host->intr_general_op->disable_all_general_intrs(host);
|
||||
}
|
||||
|
||||
static inline int host1x_hw_intr_init_host_sync(struct host1x *host, u32 cpm)
|
||||
{
|
||||
return host->intr_op->init_host_sync(host, cpm);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#define HOST1X_ACTMON_CTRL_REG 0x0
|
||||
#define HOST1X_ACTMON_INTR_ENB_REG 0x4
|
||||
#define HOST1X_ACTMON_INTR_STATUS_REG 0x8
|
||||
#define HOST1X_ACTMON_MODULE_INIT_AVG_REG 0x14
|
||||
#define HOST1X_ACTMON_MODULE_CTRL_REG 0x80
|
||||
#define HOST1X_ACTMON_MODULE_INTR_ENB_REG 0x84
|
||||
@@ -31,14 +32,19 @@
|
||||
#define HOST1X_ACTMON_MODULE_CTRL_CONSEC_LOWER_NUM(v) ((v & 0x7) << 21)
|
||||
#define HOST1X_ACTMON_MODULE_CTRL_ENB_PERIODIC(v) ((v & 0x1) << 13)
|
||||
#define HOST1X_ACTMON_MODULE_CTRL_K_VAL(v) ((v & 0x7) << 10)
|
||||
#define HOST1X_ACTMON_MODULE_INTR_CONSEC_ABOVE_WORK_ENB(v) ((v & 0x1) << 31)
|
||||
#define HOST1X_ACTMON_MODULE_INTR_CONSEC_BELOW_WORK_ENB(v) ((v & 0x1) << 30)
|
||||
#define HOST1X_ACTMON_MODULE_INTR_AVG_ABOVE_WORK_ENB(v) ((v & 0x1) << 29)
|
||||
#define HOST1X_ACTMON_MODULE_INTR_AVG_BELOW_WORK_ENB(v) ((v & 0x1) << 28)
|
||||
#define HOST1X_ACTMON_MODULE_INTR_CONSEC_WMARK_ABOVE_ENB(v) ((v & 0x1) << 31)
|
||||
#define HOST1X_ACTMON_MODULE_INTR_CONSEC_WMARK_BELOW_ENB(v) ((v & 0x1) << 30)
|
||||
#define HOST1X_ACTMON_MODULE_INTR_AVG_WMARK_ABOVE_ENB(v) ((v & 0x1) << 29)
|
||||
#define HOST1X_ACTMON_MODULE_INTR_AVG_WMARK_BELOW_ENB(v) ((v & 0x1) << 28)
|
||||
|
||||
#define HOST1X_ACTMON_CTRL_SAMPLE_PERIOD_MASK 0xff
|
||||
#define HOST1X_ACTMON_MODULE_CTRL_CONSEC_UPPER_NUM_MASK (0x7 << 26)
|
||||
#define HOST1X_ACTMON_MODULE_CTRL_CONSEC_LOWER_NUM_MASK (0x7 << 21)
|
||||
#define HOST1X_ACTMON_MODULE_CTRL_K_VAL_MASK (0x7 << 10)
|
||||
|
||||
#define HOST1X_ACTMON_MODULE_INTR_CONSEC_WMARK_ABOVE BIT(31)
|
||||
#define HOST1X_ACTMON_MODULE_INTR_CONSEC_WMARK_BELOW BIT(30)
|
||||
#define HOST1X_ACTMON_MODULE_INTR_AVG_WMARK_ABOVE BIT(29)
|
||||
#define HOST1X_ACTMON_MODULE_INTR_AVG_WMARK_BELOW BIT(28)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/*
|
||||
* Host1x init for Tegra234 SoCs
|
||||
*
|
||||
* Copyright (c) 2022 NVIDIA Corporation.
|
||||
* Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/* include hw specification */
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "cdma_hw.c"
|
||||
#include "channel_hw.c"
|
||||
#include "debug_hw.c"
|
||||
#include "intr_general_hw.c"
|
||||
#include "intr_hw.c"
|
||||
#include "syncpt_hw.c"
|
||||
|
||||
@@ -26,6 +27,7 @@ int host1x08_init(struct host1x *host)
|
||||
host->cdma_op = &host1x_cdma_ops;
|
||||
host->cdma_pb_op = &host1x_pushbuffer_ops;
|
||||
host->syncpt_op = &host1x_syncpt_ops;
|
||||
host->intr_general_op = &host1x_intr_general_ops;
|
||||
host->intr_op = &host1x_intr_ops;
|
||||
host->debug_op = &host1x_debug_ops;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2022 NVIDIA Corporation.
|
||||
* Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
*/
|
||||
|
||||
#define HOST1X_COMMON_OFA_MLOCK 0x4050
|
||||
@@ -9,3 +9,20 @@
|
||||
#define HOST1X_COMMON_NVENC_MLOCK 0x407c
|
||||
#define HOST1X_COMMON_NVDEC_MLOCK 0x4080
|
||||
#define HOST1X_COMMON_NVJPG_MLOCK 0x4084
|
||||
|
||||
#define HOST1X_COMMON_INTR_CPU0_MASK 0x4
|
||||
#define HOST1X_COMMON_THOST_INTRSTATUS 0x1c
|
||||
#define HOST1X_COMMON_THOST_INTRMASK 0x30
|
||||
#define HOST1X_COMMON_THOST_GLOBAL_INTRMASK 0x44
|
||||
|
||||
#define HOST1X_COMMON_THOST_INTRMASK_NVENC_ACTMON(v) (v << 2)
|
||||
#define HOST1X_COMMON_THOST_INTRMASK_VIC_ACTMON(v) (v << 3)
|
||||
#define HOST1X_COMMON_THOST_INTRMASK_NVDEC_ACTMON(v) (v << 4)
|
||||
#define HOST1X_COMMON_THOST_INTRMASK_NVJPG_ACTMON(v) (v << 5)
|
||||
#define HOST1X_COMMON_THOST_INTRMASK_NVJPG1_ACTMON(v) (v << 6)
|
||||
|
||||
#define HOST1X_COMMON_THOST_INTRSTATUS_NVENC_ACTMON_INTR BIT(2)
|
||||
#define HOST1X_COMMON_THOST_INTRSTATUS_VIC_ACTMON_INTR BIT(3)
|
||||
#define HOST1X_COMMON_THOST_INTRSTATUS_NVDEC_ACTMON_INTR BIT(4)
|
||||
#define HOST1X_COMMON_THOST_INTRSTATUS_NVJPG_ACTMON_INTR BIT(5)
|
||||
#define HOST1X_COMMON_THOST_INTRSTATUS_NVJPG1_ACTMON_INTR BIT(6)
|
||||
|
||||
91
drivers/gpu/host1x/hw/intr_general_hw.c
Normal file
91
drivers/gpu/host1x/hw/intr_general_hw.c
Normal file
@@ -0,0 +1,91 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Tegra host1x General Interrupt Management
|
||||
*
|
||||
* Copyright (C) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "../dev.h"
|
||||
|
||||
static irqreturn_t host1x_general_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct host1x *host = dev_id;
|
||||
unsigned long status;
|
||||
|
||||
status = host1x_common_readl(host, HOST1X_COMMON_THOST_INTRSTATUS);
|
||||
|
||||
if (status & HOST1X_COMMON_THOST_INTRSTATUS_NVENC_ACTMON_INTR)
|
||||
host1x_actmon_handle_interrupt(host, HOST1X_CLASS_NVENC);
|
||||
|
||||
if (status & HOST1X_COMMON_THOST_INTRSTATUS_VIC_ACTMON_INTR)
|
||||
host1x_actmon_handle_interrupt(host, HOST1X_CLASS_VIC);
|
||||
|
||||
if (status & HOST1X_COMMON_THOST_INTRSTATUS_NVDEC_ACTMON_INTR)
|
||||
host1x_actmon_handle_interrupt(host, HOST1X_CLASS_NVDEC);
|
||||
|
||||
if (status & HOST1X_COMMON_THOST_INTRSTATUS_NVJPG_ACTMON_INTR)
|
||||
host1x_actmon_handle_interrupt(host, HOST1X_CLASS_NVJPG);
|
||||
|
||||
if (status & HOST1X_COMMON_THOST_INTRSTATUS_NVJPG1_ACTMON_INTR)
|
||||
host1x_actmon_handle_interrupt(host, HOST1X_CLASS_NVJPG1);
|
||||
|
||||
host1x_common_writel(host, status, HOST1X_COMMON_THOST_INTRSTATUS);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int host1x_intr_init_host_general(struct host1x *host)
|
||||
{
|
||||
int err;
|
||||
|
||||
host1x_hw_intr_disable_all_general_intrs(host);
|
||||
|
||||
err = devm_request_threaded_irq(host->dev,
|
||||
host->general_irq,
|
||||
NULL, host1x_general_isr,
|
||||
IRQF_ONESHOT, "host1x_general",
|
||||
host);
|
||||
if (err < 0) {
|
||||
devm_free_irq(host->dev, host->general_irq, host);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void host1x_intr_enable_general_intrs(struct host1x *host)
|
||||
{
|
||||
if (!host->common_regs)
|
||||
return;
|
||||
|
||||
/* Assign CPU0 for host1x general interrupts */
|
||||
host1x_common_writel(host, 0x1, HOST1X_COMMON_INTR_CPU0_MASK);
|
||||
|
||||
/* Allow host1x general interrupts go to CPU0 only */
|
||||
host1x_common_writel(host, 0x1, HOST1X_COMMON_THOST_GLOBAL_INTRMASK);
|
||||
|
||||
/* Enable host1x general interrupts */
|
||||
host1x_common_writel(host,
|
||||
HOST1X_COMMON_THOST_INTRMASK_NVENC_ACTMON(1) |
|
||||
HOST1X_COMMON_THOST_INTRMASK_VIC_ACTMON(1) |
|
||||
HOST1X_COMMON_THOST_INTRMASK_NVDEC_ACTMON(1) |
|
||||
HOST1X_COMMON_THOST_INTRMASK_NVJPG_ACTMON(1) |
|
||||
HOST1X_COMMON_THOST_INTRMASK_NVJPG1_ACTMON(1),
|
||||
HOST1X_COMMON_THOST_INTRMASK);
|
||||
}
|
||||
|
||||
static void host1x_intr_disable_all_general_intrs(struct host1x *host)
|
||||
{
|
||||
if (!host->common_regs)
|
||||
return;
|
||||
|
||||
host1x_common_writel(host, 0x0, HOST1X_COMMON_THOST_INTRMASK);
|
||||
}
|
||||
|
||||
static const struct host1x_intr_general_ops host1x_intr_general_ops = {
|
||||
.init_host_general = host1x_intr_init_host_general,
|
||||
.enable_general_intrs = host1x_intr_enable_general_intrs,
|
||||
.disable_all_general_intrs = host1x_intr_disable_all_general_intrs,
|
||||
};
|
||||
@@ -27,6 +27,13 @@ enum host1x_class {
|
||||
HOST1X_CLASS_NVDEC1 = 0xF5,
|
||||
};
|
||||
|
||||
enum host1x_actmon_wmark_event {
|
||||
HOST1X_ACTMON_AVG_WMARK_BELOW,
|
||||
HOST1X_ACTMON_AVG_WMARK_ABOVE,
|
||||
HOST1X_ACTMON_CONSEC_WMARK_BELOW,
|
||||
HOST1X_ACTMON_CONSEC_WMARK_ABOVE,
|
||||
};
|
||||
|
||||
struct host1x;
|
||||
struct host1x_client;
|
||||
struct iommu_group;
|
||||
@@ -69,6 +76,7 @@ static inline void host1x_bo_cache_destroy(struct host1x_bo_cache *cache)
|
||||
* @suspend: host1x client suspend code
|
||||
* @resume: host1x client resume code
|
||||
* @get_rate: host1x client get clock rate code
|
||||
* @actmon_event: host1x client actmon event handling code in threaded interrupt context
|
||||
*/
|
||||
struct host1x_client_ops {
|
||||
int (*early_init)(struct host1x_client *client);
|
||||
@@ -78,6 +86,8 @@ struct host1x_client_ops {
|
||||
int (*suspend)(struct host1x_client *client);
|
||||
int (*resume)(struct host1x_client *client);
|
||||
unsigned long (*get_rate)(struct host1x_client *client);
|
||||
void (*actmon_event)(struct host1x_client *client,
|
||||
enum host1x_actmon_wmark_event event);
|
||||
};
|
||||
|
||||
struct host1x_actmon;
|
||||
|
||||
Reference in New Issue
Block a user