diff --git a/drivers/platform/tegra/rtcpu/hsp-mailbox-client.c b/drivers/platform/tegra/rtcpu/hsp-mailbox-client.c index 36d97a07..7a1fa70c 100644 --- a/drivers/platform/tegra/rtcpu/hsp-mailbox-client.c +++ b/drivers/platform/tegra/rtcpu/hsp-mailbox-client.c @@ -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 */ diff --git a/drivers/platform/tegra/rtcpu/tegra-camera-rtcpu-base.c b/drivers/platform/tegra/rtcpu/tegra-camera-rtcpu-base.c index 2bfa5440..d8f3289b 100644 --- a/drivers/platform/tegra/rtcpu/tegra-camera-rtcpu-base.c +++ b/drivers/platform/tegra/rtcpu/tegra-camera-rtcpu-base.c @@ -2,9 +2,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. #include - #include - #include #include #include @@ -31,6 +29,8 @@ #include #include #include +#include +#include #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; diff --git a/include/linux/tegra-hsp-combo.h b/include/linux/tegra-hsp-combo.h index 7c72da06..adecb2aa 100644 --- a/include/linux/tegra-hsp-combo.h +++ b/include/linux/tegra-hsp-combo.h @@ -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 */ diff --git a/include/soc/tegra/camrtc-commands.h b/include/soc/tegra/camrtc-commands.h index 9612a743..e9995064 100644 --- a/include/soc/tegra/camrtc-commands.h +++ b/include/soc/tegra/camrtc-commands.h @@ -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 */