mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
nvidia-oot: cameraSW: add data validation to dt reads
+ Add the following data validation checks based on
gaps identified when inspecting code for
SHR-9320:
+ FSYNC: Add check to ensure existence of generators
property before parse
+ FSYNC: Add check to ensure generators in default
group adhere to LCM rule
+ CDI: Add check to ensure reg_len / dat_len do
not exceed 2 bytes
+ CDI: Ensure err is set before jumping to err_probe
+ CDI: Jump to err_probe if IOExpander i2c-bus read
fails
+ CDI-TCA: Return error if reg_len or dat_len
out of expected range
+ FuSaCap: Ensure isp/vi-max-channels validated
+ VI: Add check for vi-mapping index found (this was
already caught in existing code, but error message
was non-specific)
+ camera_common: Add check for err that was set but
never read
+ RTCPU: Add debug prints for properties not found
Jira CAMERASW-30537
Change-Id: I9953029f594c0153d6c335913944fb8906adedd9
Signed-off-by: kevixie <kevixie@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3280557
Reviewed-by: Vincent Chung <vincentc@nvidia.com>
Reviewed-by: Frank Chen <frankc@nvidia.com>
Reviewed-by: Mohit Ingale <mohiti@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
/* Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
* SPDX-License-Identifier: GPL-2.0-only
|
/*
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION & AFFILIATES.
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -1174,6 +1176,11 @@ static int cam_fsync_create_default_group(struct cam_fsync_controller *controlle
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
err = cam_fsync_group_verify_generators_lcm(group);
|
||||||
|
if (err != 0) {
|
||||||
|
dev_err(controller->dev, "Generator LCM check failed");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
list_add_tail(&group->list, &controller->groups);
|
list_add_tail(&group->list, &controller->groups);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
@@ -1238,6 +1245,10 @@ static int cam_fsync_find_and_add_groups(struct cam_fsync_controller *controller
|
|||||||
|
|
||||||
num_generators = of_property_count_elems_of_size(np, "generators",
|
num_generators = of_property_count_elems_of_size(np, "generators",
|
||||||
sizeof(u32));
|
sizeof(u32));
|
||||||
|
if (num_generators < 0) {
|
||||||
|
dev_err(controller->dev, "Unable to parse generators: %d\n", num_generators);
|
||||||
|
return num_generators;
|
||||||
|
}
|
||||||
for (i = 0; i < num_generators; i++) {
|
for (i = 0; i < num_generators; i++) {
|
||||||
gen = of_parse_phandle(np, "generators", i);
|
gen = of_parse_phandle(np, "generators", i);
|
||||||
err = cam_fsync_add_generator(group, gen);
|
err = cam_fsync_add_generator(group, gen);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES.
|
* SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION & AFFILIATES.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -271,6 +271,10 @@ int camera_common_parse_clocks(struct device *dev,
|
|||||||
}
|
}
|
||||||
err = of_property_read_u32(np, "parent-clk-index",
|
err = of_property_read_u32(np, "parent-clk-index",
|
||||||
&parentclk_index);
|
&parentclk_index);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "Failed to find parent clk index\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < numclocks; i++) {
|
for (i = 0; i < numclocks; i++) {
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
// SPDX-FileCopyrightText: Copyright (c) 2017-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
/* SPDX-FileCopyrightText: Copyright (c) 2017-2025 NVIDIA CORPORATION & AFFILIATES.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file drivers/media/platform/tegra/camera/fusa-capture/capture-isp.c
|
* @file drivers/media/platform/tegra/camera/fusa-capture/capture-isp.c
|
||||||
@@ -36,15 +48,18 @@
|
|||||||
#define CAPTURE_CHANNEL_ISP_INVALID_ID U16_C(0xFFFF)
|
#define CAPTURE_CHANNEL_ISP_INVALID_ID U16_C(0xFFFF)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The default number of ISP channels to be used if not specified in
|
* @brief Maximum number of ISP channels supported by KMD
|
||||||
* the device tree.
|
|
||||||
*/
|
*/
|
||||||
#define DEFAULT_ISP_CHANNELS U32_C(16)
|
#define NUM_ISP_CHANNELS U32_C(16)
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of ISP channels supported by KMD for T26x
|
||||||
|
*/
|
||||||
|
#define NUM_ISP_CHANNELS_T26x U32_C(32)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Maximum number of ISP devices supported.
|
* @brief Maximum number of ISP devices supported.
|
||||||
*/
|
*/
|
||||||
#define MAX_ISP_UNITS U32_C(0x2)
|
#define MAX_ISP_UNITS U32_C(0x2)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The Capture-ISP standalone driver context.
|
* @brief The Capture-ISP standalone driver context.
|
||||||
@@ -2330,6 +2345,36 @@ int isp_capture_buffer_request(
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper to parse isp-devices Chip ID
|
||||||
|
*
|
||||||
|
* @param[in] of_node Pointer to @ref device_node
|
||||||
|
* containing isp-devices phandle
|
||||||
|
* @returns true If isp-devices is configured for T26X.
|
||||||
|
* @returns false If T26X not mentioned.
|
||||||
|
*/
|
||||||
|
static inline bool isp_capture_is_t26x(struct device_node *of_node)
|
||||||
|
{
|
||||||
|
struct device_node *node;
|
||||||
|
const char *compatible;
|
||||||
|
int ret = 0;
|
||||||
|
bool is_t26x = false;
|
||||||
|
|
||||||
|
node = of_parse_phandle(of_node, "nvidia,isp-devices", 0);
|
||||||
|
if (node == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ret = of_property_read_string(node, "compatible", &compatible);
|
||||||
|
if (ret != 0) {
|
||||||
|
of_node_put(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_t26x = (strstr(compatible, "tegra26") != NULL);
|
||||||
|
of_node_put(node);
|
||||||
|
return is_t26x;
|
||||||
|
}
|
||||||
|
|
||||||
static int capture_isp_probe(struct platform_device *pdev)
|
static int capture_isp_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
@@ -2345,10 +2390,23 @@ static int capture_isp_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
info->num_isp_devices = 0;
|
info->num_isp_devices = 0;
|
||||||
|
|
||||||
(void)of_property_read_u32(dev->of_node, "nvidia,isp-max-channels",
|
err = of_property_read_u32(dev->of_node, "nvidia,isp-max-channels",
|
||||||
&info->max_isp_channels);
|
&info->max_isp_channels);
|
||||||
if (info->max_isp_channels == 0)
|
if (err < 0) {
|
||||||
info->max_isp_channels = DEFAULT_ISP_CHANNELS;
|
err = -EINVAL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (isp_capture_is_t26x(dev->of_node)) {
|
||||||
|
if (info->max_isp_channels > NUM_ISP_CHANNELS_T26x) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((info->max_isp_channels == 0) || (info->max_isp_channels > NUM_ISP_CHANNELS)) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; ; i++) {
|
for (i = 0; ; i++) {
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
|
|||||||
@@ -70,6 +70,11 @@
|
|||||||
*/
|
*/
|
||||||
#define DEFAULT_VI_CHANNELS U32_C(64)
|
#define DEFAULT_VI_CHANNELS U32_C(64)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maximum number of VI channels supported by KMD in total
|
||||||
|
*/
|
||||||
|
#define NUM_VI_CHANNELS U32_C(72)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Maximum number of VI devices supported.
|
* @brief Maximum number of VI devices supported.
|
||||||
*/
|
*/
|
||||||
@@ -1621,6 +1626,7 @@ EXPORT_SYMBOL_GPL(vi_capture_set_progress_status_notifier);
|
|||||||
static int csi_vi_get_mapping_table(struct platform_device *pdev)
|
static int csi_vi_get_mapping_table(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
|
int err = 0;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct tegra_capture_vi_data *info = platform_get_drvdata(pdev);
|
struct tegra_capture_vi_data *info = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
@@ -1659,10 +1665,16 @@ static int csi_vi_get_mapping_table(struct platform_device *pdev)
|
|||||||
uint32_t stream_index = NVCSI_STREAM_INVALID_ID;
|
uint32_t stream_index = NVCSI_STREAM_INVALID_ID;
|
||||||
uint32_t vi_unit_id = INVALID_VI_UNIT_ID;
|
uint32_t vi_unit_id = INVALID_VI_UNIT_ID;
|
||||||
|
|
||||||
(void)of_property_read_u32_index(np,
|
err = of_property_read_u32_index(np,
|
||||||
"nvidia,vi-mapping",
|
"nvidia,vi-mapping",
|
||||||
2 * index,
|
2 * index,
|
||||||
&stream_index);
|
&stream_index);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev,
|
||||||
|
"%s: ERR %d: missing property nvidia,vi-mapping or csi_stream_id at index %d",
|
||||||
|
__func__, err, index);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for valid/duplicate csi-stream-id */
|
/* Check for valid/duplicate csi-stream-id */
|
||||||
if (stream_index >= MAX_NVCSI_STREAM_IDS ||
|
if (stream_index >= MAX_NVCSI_STREAM_IDS ||
|
||||||
@@ -1672,10 +1684,16 @@ static int csi_vi_get_mapping_table(struct platform_device *pdev)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void)of_property_read_u32_index(np,
|
err = of_property_read_u32_index(np,
|
||||||
"nvidia,vi-mapping",
|
"nvidia,vi-mapping",
|
||||||
2 * index + 1,
|
2 * index + 1,
|
||||||
&vi_unit_id);
|
&vi_unit_id);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev,
|
||||||
|
"%s: ERR %d: missing property nvidia,vi-mapping or vi_unit_id at index %d",
|
||||||
|
__func__, err, index);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/* check for valid vi-unit-id */
|
/* check for valid vi-unit-id */
|
||||||
if (vi_unit_id >= MAX_VI_UNITS) {
|
if (vi_unit_id >= MAX_VI_UNITS) {
|
||||||
@@ -1713,8 +1731,13 @@ static int capture_vi_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
info->num_vi_devices = 0;
|
info->num_vi_devices = 0;
|
||||||
|
|
||||||
(void)of_property_read_u32(dev->of_node, "nvidia,vi-max-channels",
|
err = of_property_read_u32(dev->of_node, "nvidia,vi-max-channels",
|
||||||
&info->max_vi_channels);
|
&info->max_vi_channels);
|
||||||
|
if (err || info->max_vi_channels > NUM_VI_CHANNELS) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if (info->max_vi_channels == 0)
|
if (info->max_vi_channels == 0)
|
||||||
info->max_vi_channels = DEFAULT_VI_CHANNELS;
|
info->max_vi_channels = DEFAULT_VI_CHANNELS;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
// Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
/* SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION & AFFILIATES.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef __CDI_TCA9539_PRIV_H__
|
#ifndef __CDI_TCA9539_PRIV_H__
|
||||||
#define __CDI_TCA9539_PRIV_H__
|
#define __CDI_TCA9539_PRIV_H__
|
||||||
@@ -31,19 +43,15 @@ static int tca9539_raw_wr(
|
|||||||
|
|
||||||
dev_dbg(dev, "%s\n", __func__);
|
dev_dbg(dev, "%s\n", __func__);
|
||||||
|
|
||||||
if (tca9539->reg_len == 2) {
|
if (tca9539->dat_len != 1)
|
||||||
data[0] = (u8)((offset >> 8) & 0xff);
|
return -EINVAL;
|
||||||
data[1] = (u8)(offset & 0xff);
|
|
||||||
data[2] = val;
|
if (tca9539->reg_len != 1)
|
||||||
size += 2;
|
return -EINVAL;
|
||||||
} else if (tca9539->reg_len == 1) {
|
|
||||||
data[0] = (u8)(offset & 0xff);
|
data[0] = (u8)(offset & 0xff);
|
||||||
data[1] = val;
|
data[1] = val;
|
||||||
size += 1;
|
size += 1;
|
||||||
} else if ((tca9539->reg_len == 0) ||
|
|
||||||
(tca9539->reg_len > 3)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
num_msgs = size / MAX_MSG_SIZE;
|
num_msgs = size / MAX_MSG_SIZE;
|
||||||
num_msgs += (size % MAX_MSG_SIZE) ? 1 : 0;
|
num_msgs += (size % MAX_MSG_SIZE) ? 1 : 0;
|
||||||
@@ -96,11 +104,13 @@ static int tca9539_raw_rd(
|
|||||||
|
|
||||||
dev_dbg(dev, "%s\n", __func__);
|
dev_dbg(dev, "%s\n", __func__);
|
||||||
|
|
||||||
if (tca9539->reg_len == 2) {
|
if (tca9539->dat_len != 1)
|
||||||
data[0] = (u8)((offset >> 8) & 0xff);
|
return -EINVAL;
|
||||||
data[1] = (u8)(offset & 0xff);
|
|
||||||
} else if (tca9539->reg_len == 1)
|
if (tca9539->reg_len != 1)
|
||||||
data[0] = (u8)(offset & 0xff);
|
return -EINVAL;
|
||||||
|
|
||||||
|
data[0] = (u8)(offset & 0xff);
|
||||||
|
|
||||||
i2cmsg[0].addr = tca9539->addr;
|
i2cmsg[0].addr = tca9539->addr;
|
||||||
i2cmsg[0].len = tca9539->reg_len;
|
i2cmsg[0].len = tca9539->reg_len;
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
// SPDX-FileCopyrightText: Copyright (C) 2015-2024 NVIDIA CORPORATION. All rights reserved.
|
/* SPDX-FileCopyrightText: Copyright (c) 2015-2025 NVIDIA CORPORATION & AFFILIATES.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <nvidia/conftest.h>
|
#include <nvidia/conftest.h>
|
||||||
|
|
||||||
@@ -1794,10 +1806,13 @@ static int cdi_mgr_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
if (pd->num_pwr_gpios > 0) {
|
if (pd->num_pwr_gpios > 0) {
|
||||||
for (i = 0; i < pd->num_pwr_gpios; i++) {
|
for (i = 0; i < pd->num_pwr_gpios; i++) {
|
||||||
if (!gpio_is_valid(pd->pwr_gpios[i]))
|
if (!gpio_is_valid(pd->pwr_gpios[i])) {
|
||||||
|
err = -EINVAL;
|
||||||
goto err_probe;
|
goto err_probe;
|
||||||
|
}
|
||||||
|
|
||||||
if (gpio_request(pd->pwr_gpios[i], "pwdn-gpios")) {
|
err = gpio_request(pd->pwr_gpios[i], "pwdn-gpios");
|
||||||
|
if (err) {
|
||||||
dev_err(&pdev->dev, "failed to req GPIO: %d\n",
|
dev_err(&pdev->dev, "failed to req GPIO: %d\n",
|
||||||
pd->pwr_gpios[i]);
|
pd->pwr_gpios[i]);
|
||||||
goto err_probe;
|
goto err_probe;
|
||||||
@@ -1905,14 +1920,18 @@ static int cdi_mgr_probe(struct platform_device *pdev)
|
|||||||
if (child_tca9539 != NULL) {
|
if (child_tca9539 != NULL) {
|
||||||
err = of_property_read_u32(child_tca9539, "i2c-bus",
|
err = of_property_read_u32(child_tca9539, "i2c-bus",
|
||||||
&cdi_mgr->tca9539.bus);
|
&cdi_mgr->tca9539.bus);
|
||||||
if (err)
|
if (err) {
|
||||||
cdi_mgr->tca9539.bus = pd->bus;
|
dev_err(&pdev->dev, "%s: ERROR %d failed to find IOExpander i2c-bus property\n",
|
||||||
|
__func__, err);
|
||||||
|
goto err_probe;
|
||||||
|
}
|
||||||
err = of_property_read_u32(child_tca9539, "addr",
|
err = of_property_read_u32(child_tca9539, "addr",
|
||||||
&cdi_mgr->tca9539.addr);
|
&cdi_mgr->tca9539.addr);
|
||||||
if (err || !cdi_mgr->tca9539.addr) {
|
if (err || !cdi_mgr->tca9539.addr) {
|
||||||
dev_err(&pdev->dev, "%s: ERROR %d addr = %d\n",
|
dev_err(&pdev->dev, "%s: ERROR %d addr = %d\n",
|
||||||
__func__, err,
|
__func__, err,
|
||||||
cdi_mgr->tca9539.addr);
|
cdi_mgr->tca9539.addr);
|
||||||
|
err = -EINVAL;
|
||||||
goto err_probe;
|
goto err_probe;
|
||||||
}
|
}
|
||||||
err = of_property_read_u32(child_tca9539, "reg_len",
|
err = of_property_read_u32(child_tca9539, "reg_len",
|
||||||
@@ -1921,6 +1940,7 @@ static int cdi_mgr_probe(struct platform_device *pdev)
|
|||||||
dev_err(&pdev->dev, "%s: ERROR %d reg_len = %d\n",
|
dev_err(&pdev->dev, "%s: ERROR %d reg_len = %d\n",
|
||||||
__func__, err,
|
__func__, err,
|
||||||
cdi_mgr->tca9539.reg_len);
|
cdi_mgr->tca9539.reg_len);
|
||||||
|
err = -EINVAL;
|
||||||
goto err_probe;
|
goto err_probe;
|
||||||
}
|
}
|
||||||
err = of_property_read_u32(child_tca9539, "dat_len",
|
err = of_property_read_u32(child_tca9539, "dat_len",
|
||||||
@@ -1929,6 +1949,7 @@ static int cdi_mgr_probe(struct platform_device *pdev)
|
|||||||
dev_err(&pdev->dev, "%s: ERROR %d dat_len = %d\n",
|
dev_err(&pdev->dev, "%s: ERROR %d dat_len = %d\n",
|
||||||
__func__, err,
|
__func__, err,
|
||||||
cdi_mgr->tca9539.dat_len);
|
cdi_mgr->tca9539.dat_len);
|
||||||
|
err = -EINVAL;
|
||||||
goto err_probe;
|
goto err_probe;
|
||||||
}
|
}
|
||||||
err = of_property_read_u32(child_tca9539->parent,
|
err = of_property_read_u32(child_tca9539->parent,
|
||||||
@@ -1954,11 +1975,19 @@ static int cdi_mgr_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
cdi_mgr->tca9539.reg_len /= 8;
|
cdi_mgr->tca9539.reg_len /= 8;
|
||||||
cdi_mgr->tca9539.dat_len /= 8;
|
cdi_mgr->tca9539.dat_len /= 8;
|
||||||
|
if (cdi_mgr->tca9539.reg_len != 1 || cdi_mgr->tca9539.dat_len != 1) {
|
||||||
|
dev_err(&pdev->dev, "%s invalid reg_len = %d or dat_len = %d\n",
|
||||||
|
__func__, cdi_mgr->tca9539.reg_len,
|
||||||
|
cdi_mgr->tca9539.dat_len);
|
||||||
|
err = -EINVAL;
|
||||||
|
goto err_probe;
|
||||||
|
}
|
||||||
cdi_mgr->tca9539.enable = 1;
|
cdi_mgr->tca9539.enable = 1;
|
||||||
cdi_mgr->tca9539.adap = i2c_get_adapter(cdi_mgr->tca9539.bus);
|
cdi_mgr->tca9539.adap = i2c_get_adapter(cdi_mgr->tca9539.bus);
|
||||||
if (!cdi_mgr->tca9539.adap) {
|
if (!cdi_mgr->tca9539.adap) {
|
||||||
dev_err(&pdev->dev, "%s no such i2c bus %d\n",
|
dev_err(&pdev->dev, "%s no such i2c bus %d\n",
|
||||||
__func__, cdi_mgr->tca9539.bus);
|
__func__, cdi_mgr->tca9539.bus);
|
||||||
|
err = -EINVAL;
|
||||||
goto err_probe;
|
goto err_probe;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1969,27 +1998,31 @@ static int cdi_mgr_probe(struct platform_device *pdev)
|
|||||||
/* the registers in TCA9539 */
|
/* the registers in TCA9539 */
|
||||||
/* Use the IO expander to control PWDN signals */
|
/* Use the IO expander to control PWDN signals */
|
||||||
if (cdi_mgr->cim_ver == 1U) { /* P3714 A01 */
|
if (cdi_mgr->cim_ver == 1U) { /* P3714 A01 */
|
||||||
if (tca9539_wr(cdi_mgr, 0x6, 0x0E) != 0) {
|
err = tca9539_wr(cdi_mgr, 0x6, 0x0E);
|
||||||
|
if (err != 0) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"%s: ERR %d: TCA9539: Failed to select PWDN signal source\n",
|
"%s: ERR %d: TCA9539: Failed to select PWDN signal source\n",
|
||||||
__func__, err);
|
__func__, err);
|
||||||
goto err_probe;
|
goto err_probe;
|
||||||
}
|
}
|
||||||
/* Output low for AGGA/B/C/D_PWRDN */
|
/* Output low for AGGA/B/C/D_PWRDN */
|
||||||
if (tca9539_wr(cdi_mgr, 0x2, 0x0E) != 0) {
|
err = tca9539_wr(cdi_mgr, 0x2, 0x0E);
|
||||||
|
if (err != 0) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"%s: ERR %d: TCA9539: Failed to set the output level\n",
|
"%s: ERR %d: TCA9539: Failed to set the output level\n",
|
||||||
__func__, err);
|
__func__, err);
|
||||||
goto err_probe;
|
goto err_probe;
|
||||||
}
|
}
|
||||||
} else if (cdi_mgr->cim_ver == 2U) { /* P3714 A02 */
|
} else if (cdi_mgr->cim_ver == 2U) { /* P3714 A02 */
|
||||||
if (tca9539_wr(cdi_mgr, 0x6, 0xC0) != 0) {
|
err = tca9539_wr(cdi_mgr, 0x6, 0xC0);
|
||||||
|
if (err != 0) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"%s: ERR %d: TCA9539: Failed to select FS selection signal source\n",
|
"%s: ERR %d: TCA9539: Failed to select FS selection signal source\n",
|
||||||
__func__, err);
|
__func__, err);
|
||||||
goto err_probe;
|
goto err_probe;
|
||||||
}
|
}
|
||||||
if (tca9539_wr(cdi_mgr, 0x7, 0x70) != 0) {
|
err = tca9539_wr(cdi_mgr, 0x7, 0x70);
|
||||||
|
if (err != 0) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"%s: ERR %d: TCA9539: Failed to select PWDN signal source\n",
|
"%s: ERR %d: TCA9539: Failed to select PWDN signal source\n",
|
||||||
__func__, err);
|
__func__, err);
|
||||||
@@ -2002,17 +2035,19 @@ static int cdi_mgr_probe(struct platform_device *pdev)
|
|||||||
cdi_mgr->cim_frsync[0],
|
cdi_mgr->cim_frsync[0],
|
||||||
cdi_mgr->cim_frsync[1],
|
cdi_mgr->cim_frsync[1],
|
||||||
cdi_mgr->cim_frsync[2]);
|
cdi_mgr->cim_frsync[2]);
|
||||||
if (tca9539_wr(cdi_mgr, 0x2,
|
err = tca9539_wr(cdi_mgr, 0x2,
|
||||||
(cdi_mgr->cim_frsync[2] << 4) |
|
(cdi_mgr->cim_frsync[2] << 4) |
|
||||||
(cdi_mgr->cim_frsync[1] << 2) |
|
(cdi_mgr->cim_frsync[1] << 2) |
|
||||||
(cdi_mgr->cim_frsync[0])) < 0) {
|
(cdi_mgr->cim_frsync[0]));
|
||||||
|
if (err < 0) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"%s: ERR %d: TCA9539: Failed to set FRSYNC control logic\n",
|
"%s: ERR %d: TCA9539: Failed to set FRSYNC control logic\n",
|
||||||
__func__, err);
|
__func__, err);
|
||||||
goto err_probe;
|
goto err_probe;
|
||||||
}
|
}
|
||||||
/* Output low for AGGA/B/C/D_PWRDN */
|
/* Output low for AGGA/B/C/D_PWRDN */
|
||||||
if (tca9539_wr(cdi_mgr, 0x3, 0x00) != 0) {
|
err = tca9539_wr(cdi_mgr, 0x3, 0x00);
|
||||||
|
if (err != 0) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"%s: ERR %d: TCA9539: Failed to set the output level\n",
|
"%s: ERR %d: TCA9539: Failed to set the output level\n",
|
||||||
__func__, err);
|
__func__, err);
|
||||||
|
|||||||
@@ -1,5 +1,17 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
// SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
/* SPDX-FileCopyrightText: Copyright (c) 2022-2025 NVIDIA CORPORATION & AFFILIATES.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <nvidia/conftest.h>
|
#include <nvidia/conftest.h>
|
||||||
#include <linux/tegra-camera-rtcpu.h>
|
#include <linux/tegra-camera-rtcpu.h>
|
||||||
@@ -832,7 +844,9 @@ static int tegra_cam_rtcpu_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
name = pdata->name;
|
name = pdata->name;
|
||||||
of_property_read_string(dev->of_node, "nvidia,cpu-name", &name);
|
ret = of_property_read_string(dev->of_node, "nvidia,cpu-name", &name);
|
||||||
|
if (ret)
|
||||||
|
dev_dbg(dev, "no device property, cpu-name, setting to parent name\n");
|
||||||
|
|
||||||
dev_dbg(dev, "probing RTCPU on %s\n", name);
|
dev_dbg(dev, "probing RTCPU on %s\n", name);
|
||||||
|
|
||||||
@@ -854,11 +868,15 @@ static int tegra_cam_rtcpu_probe(struct platform_device *pdev)
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
rtcpu->max_reboot_retry = 3;
|
rtcpu->max_reboot_retry = 3;
|
||||||
(void)of_property_read_u32(dev->of_node, NV(max-reboot),
|
ret = of_property_read_u32(dev->of_node, NV(max-reboot),
|
||||||
&rtcpu->max_reboot_retry);
|
&rtcpu->max_reboot_retry);
|
||||||
|
if (ret)
|
||||||
|
dev_dbg(dev, "no device property, max-reboot, setting to default (3)\n");
|
||||||
timeout = 2000;
|
timeout = 2000;
|
||||||
|
|
||||||
(void)of_property_read_u32(dev->of_node, "nvidia,cmd-timeout", &timeout);
|
ret = of_property_read_u32(dev->of_node, "nvidia,cmd-timeout", &timeout);
|
||||||
|
if (ret)
|
||||||
|
dev_dbg(dev, "no device property, cmd-timeout, setting to default (2000)\n");
|
||||||
|
|
||||||
rtcpu->cmd_timeout = msecs_to_jiffies(timeout);
|
rtcpu->cmd_timeout = msecs_to_jiffies(timeout);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user