rtcpu: set op point via sysfs

Create and register set and get operating point sysfs functions.

The operating point notification will contain the requested
operating point.

The nvcap resource manager will extract the operating point
from the notfication and send it to rce via the hsp command
interface.

In turn, rce will apply the operating point by adjusting the
functional clock frequencies for the following camera ip:

- rce hardware
- vi hardware
- isp hardware
- nvcsi

Jira CAMERASW-26378

Signed-off-by: Robert Kelly <rkelly@nvidia.com>
Change-Id: Ia814b2716d3738efb3cbc37307a267140b555f42
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3179593
(cherry picked from commit d259727a57ecf4b9463030b3418715891b3b1209)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3189078
Reviewed-by: Semi Malinen <smalinen@nvidia.com>
Reviewed-by: Frank Chen <frankc@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Robert Kelly
2024-07-22 16:30:07 +00:00
committed by mobile promotions
parent d7a9c5b734
commit 98be04181c
4 changed files with 160 additions and 7 deletions

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include "linux/tegra-hsp-combo.h"
@@ -51,6 +51,7 @@ struct camrtc_hsp_op {
int (*ch_setup)(struct camrtc_hsp *, dma_addr_t iova, long *timeout);
int (*ping)(struct camrtc_hsp *, u32 data, long *timeout);
int (*get_fw_hash)(struct camrtc_hsp *, u32 index, long *timeout);
int (*set_operating_point)(struct camrtc_hsp *, u32 operating_point, long *timeout);
};
static int camrtc_hsp_send(struct camrtc_hsp *camhsp,
@@ -163,6 +164,8 @@ static int camrtc_hsp_vm_ping(struct camrtc_hsp *camhsp,
u32 data, long *timeout);
static int camrtc_hsp_vm_get_fw_hash(struct camrtc_hsp *camhsp,
u32 index, long *timeout);
static int camrtc_hsp_vm_set_operating_point(struct camrtc_hsp *camhsp,
u32 operating_point, long *timeout);
static const struct camrtc_hsp_op camrtc_hsp_vm_ops = {
.send = camrtc_hsp_vm_send,
@@ -174,6 +177,7 @@ static const struct camrtc_hsp_op camrtc_hsp_vm_ops = {
.ping = camrtc_hsp_vm_ping,
.ch_setup = camrtc_hsp_vm_ch_setup,
.get_fw_hash = camrtc_hsp_vm_get_fw_hash,
.set_operating_point = camrtc_hsp_vm_set_operating_point,
};
static int camrtc_hsp_vm_send(struct camrtc_hsp *camhsp,
@@ -326,6 +330,14 @@ static int camrtc_hsp_vm_get_fw_hash(struct camrtc_hsp *camhsp, u32 index,
return camrtc_hsp_vm_sendrecv(camhsp, request, timeout);
}
static int camrtc_hsp_vm_set_operating_point(struct camrtc_hsp *camhsp, u32 operating_point,
long *timeout)
{
u32 request = CAMRTC_HSP_MSG(CAMRTC_HSP_SET_OP_POINT, operating_point);
return camrtc_hsp_vm_sendrecv(camhsp, request, timeout);
}
static struct device_node *hsp_vm_get_available(const struct device_node *parent)
{
const char *compatible = "nvidia,tegra-camrtc-hsp-vm";
@@ -457,6 +469,30 @@ int camrtc_hsp_suspend(struct camrtc_hsp *camhsp)
}
EXPORT_SYMBOL(camrtc_hsp_suspend);
/*
* Set Operating Point: set operating point
*/
int camrtc_hsp_set_operating_point(struct camrtc_hsp *camhsp, uint32_t operating_point)
{
long timeout;
int response;
if (WARN_ON(camhsp == NULL))
return -EINVAL;
timeout = camhsp->timeout;
mutex_lock(&camhsp->mutex);
response = camhsp->op->set_operating_point(camhsp, operating_point, &timeout);
mutex_unlock(&camhsp->mutex);
if (response != 0)
dev_info(&camhsp->dev, "HSP_SET_OP_POINT failed: 0x%08x\n",
response);
return response <= 0 ? response : -EIO;
}
EXPORT_SYMBOL(camrtc_hsp_set_operating_point);
/*
* Bye: tell firmware that VM mappings are going away
*/

View File

@@ -2,9 +2,7 @@
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h>
#include <linux/tegra-camera-rtcpu.h>
#include <linux/bitops.h>
#include <linux/completion.h>
#include <linux/delay.h>
@@ -31,6 +29,8 @@
#include <linux/tegra-rtcpu-trace.h>
#include <linux/version.h>
#include <linux/wait.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include "clk-group.h"
#include "device-group.h"
@@ -69,6 +69,7 @@ struct tegra_cam_rtcpu_pdata {
static int tegra_rce_cam_wait_for_idle(struct device *dev);
static void tegra_rce_cam_assert_resets(struct device *dev);
static int tegra_rce_cam_deassert_resets(struct device *dev);
static int tegra_camrtc_fw_set_operating_point(struct device *dev, uint32_t op);
static const char * const rce_reset_names[] = {
"reset-names", /* all named resets */
@@ -126,6 +127,66 @@ struct tegra_cam_rtcpu {
bool online;
};
static struct device *s_dev;
static uint32_t operating_point;
static ssize_t show_operating_point(struct kobject *kobj, struct kobj_attribute *attr, char *buff)
{
sprintf(buff, "%d", operating_point);
return strlen(buff);
}
static ssize_t store_operating_point(struct kobject *kobj, struct kobj_attribute *attr,
const char *buff, size_t count)
{
u32 temp;
if (kstrtou32(buff, 10, &temp) == 0) {
if ((temp == 0) || (temp == 6)) {
operating_point = (uint32_t)temp;
tegra_camrtc_fw_set_operating_point(s_dev, operating_point);
}
}
return count;
}
static struct kobj_attribute operating_point_attribute =
__ATTR(operating_point, 0644, show_operating_point, store_operating_point);
static struct attribute *attrs[] = {
&operating_point_attribute.attr,
NULL,
};
static struct attribute_group attr_group = {
.attrs = attrs,
};
static struct kobject *kobj;
static int init_operating_point_sysfs(void)
{
int ret;
operating_point = 0;
kobj = kobject_create_and_add("operating_point", kernel_kobj);
if (!kobj)
return -ENOMEM;
ret = sysfs_create_group(kobj, &attr_group);
if (ret)
kobject_put(kobj);
return ret;
}
static void deinit_operating_point_sysfs(void)
{
kobject_put(kobj);
}
static void __iomem *tegra_cam_ioremap(struct device *dev, int index)
{
struct resource mem;
@@ -350,6 +411,16 @@ static int tegra_rce_cam_wait_for_idle(struct device *dev)
return 0;
}
static int tegra_camrtc_fw_set_operating_point(struct device *dev, uint32_t op)
{
struct tegra_cam_rtcpu *rtcpu = dev_get_drvdata(dev);
if (!rtcpu->hsp)
return 0;
return camrtc_hsp_set_operating_point(rtcpu->hsp, op);
}
static int tegra_rce_cam_deassert_resets(struct device *dev)
{
struct tegra_cam_rtcpu *rtcpu = dev_get_drvdata(dev);
@@ -707,11 +778,11 @@ static int tegra_cam_rtcpu_remove(struct platform_device *pdev)
pdev->dev.dma_parms = NULL;
deinit_operating_point_sysfs();
return 0;
}
static struct device *s_dev;
static int tegra_cam_rtcpu_probe(struct platform_device *pdev)
{
struct tegra_cam_rtcpu *rtcpu;
@@ -810,6 +881,8 @@ static int tegra_cam_rtcpu_probe(struct platform_device *pdev)
s_dev = dev;
init_operating_point_sysfs();
dev_dbg(dev, "successfully probed RTCPU on %s\n", name);
return 0;

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#ifndef INCLUDE_RTCPU_HSP_COMBO_H
@@ -29,6 +29,8 @@ int camrtc_hsp_ch_setup(struct camrtc_hsp *camhsp, dma_addr_t iova);
int camrtc_hsp_ping(struct camrtc_hsp *camhsp, u32 data, long timeout);
int camrtc_hsp_get_fw_hash(struct camrtc_hsp *camhsp,
u8 hash[], size_t hash_size);
int camrtc_hsp_set_operating_point(struct camrtc_hsp *camhsp,
uint32_t operating_point);
#endif /* INCLUDE_RTCPU_HSP_COMBO_H */

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
/**
@@ -464,6 +464,48 @@
*/
#define CAMRTC_HSP_PROTOCOL MK_U32(0x47)
/**
* @brief SET_OP_POINT message
*
* The CAMRTC_HSP_SET_OP_POINT message is used to apply the
* specified operating point to Camera IP. Two operating points
* are supported:
*
* Operating Point 0: Camera IP runs at maximum clock speeds.
* Operating Point 6: Camera IP runs at reduced clock speeds.
*
* Camera IP:
* - RCE HW
* - VI HW
* - ISP HW
* - NVCSI
*
* @pre @ref CAMRTC_HSP_HELLO exchange has been completed.
*
* @par Request
* @rststar
* +-------+---------------------------------------------------+
* | Bits | Description |
* +=======+===================================================+
* | 30:24 | CAMRTC_HSP_SET_OP_POINT |
* +-------+---------------------------------------------------+
* | 23:0 | Operating Point {0, 6} |
* +-------+---------------------------------------------------+
* @endrst
*
* @par Response
* @rststar
* +-------+---------------------------------------------------+
* | Bits | Description |
* +=======+===================================================+
* | 30:24 | CAMRTC_HSP_SET_OP_POINT |
* +-------+---------------------------------------------------+
* | 23:0 | 0x000000 |
* +-------+---------------------------------------------------+
* @endrst
*/
#define CAMRTC_HSP_SET_OP_POINT MK_U32(0x48)
/** Reserved, not to be used. */
#define CAMRTC_HSP_RESERVED_5E MK_U32(0x5E) /* bug 200395605 */