drivers:nvpps: Add support for configurable inital operating mode

Add support to select initial operating mode (GPIO or TIMER)
through DT property "nvpps-event-mode-init".

This allows users to specify which mode the driver should
start in rather than always defaulting to GPIO mode if gpios
property is specified in DT.

Key changes:
- Add DT property parsing for initial event mode
- Add validation to ensure selected mode is supported
- If this property is not specified, default mode selection
  happens based on if nvpps-gpios property is defined or not
- Add informative debug messages about selected mode
- Add error handling for invalid configurations(eg: init
  mode is GPIO but gpios property is not defined). If
  validation fails, probe returns error instead of
  defaulting to TIMER mode.

bug 5253938

Change-Id: I64c2a6565eeb46d6b07cf266cd4189fba9f0fba3
Signed-off-by: Sheetal Tigadoli <stigadoli@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3352704
(cherry picked from commit 091bb3ff50972e8dc3d7b941d850b4c1457b2a9e)
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3361726
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Sumeet Gupta <sumeetg@nvidia.com>
This commit is contained in:
Sheetal Tigadoli
2025-04-30 17:39:43 +00:00
committed by Jon Hunter
parent 148c895a23
commit 5de17f758a

View File

@@ -1157,6 +1157,7 @@ static int nvpps_probe(struct platform_device *pdev)
const struct tegra_chip_data *cdata = NULL; const struct tegra_chip_data *cdata = NULL;
struct resource res; struct resource res;
int index; int index;
uint32_t initial_mode;
dev_info(&pdev->dev, "%s\n", __FUNCTION__); dev_info(&pdev->dev, "%s\n", __FUNCTION__);
@@ -1265,6 +1266,37 @@ static int nvpps_probe(struct platform_device *pdev)
if (err < 0) if (err < 0)
return err; return err;
/* Get initial operating mode from device tree, default to timer mode if not specified */
err = of_property_read_u32(np, "nvpps-event-mode-init", &initial_mode);
if (err < 0) {
if (pdev_data->only_timer_mode == true) {
dev_warn(&pdev->dev, "nvpps-event-mode-init property not specified err(%d), using default value 2 (TIMER mode)\n", err);
initial_mode = NVPPS_MODE_TIMER;
} else {
dev_warn(&pdev->dev, "nvpps-event-mode-init property not specified err(%d), using default value 1 (GPIO mode)\n", err);
initial_mode = NVPPS_MODE_GPIO;
}
}
/* Validate initial operation mode selected is valid */
if (initial_mode == NVPPS_MODE_GPIO) {
/* Validate if initial operation mode selected(GPIO) can be supported.
* If nvpps-gpios property is not specified, only_timer_mode is true and
* GPIO mode cannot be selected.
*/
if (pdev_data->only_timer_mode == true) {
dev_err(&pdev->dev, "GPIO mode as initial operating mode cannot be selected without defining nvpps-gpios property\n");
return -EINVAL;
}
dev_info(&pdev->dev, "Initial operating mode selected as GPIO\n");
} else if (initial_mode == NVPPS_MODE_TIMER) {
dev_info(&pdev->dev, "Initial operating mode selected as TIMER\n");
} else {
dev_err(&pdev->dev, "Invalid initial operating mode %u specified. Valid values are 1 (GPIO) and 2 (TIMER)\n",
initial_mode);
return -EINVAL;
}
/* character device setup */ /* character device setup */
#ifndef NVPPS_NO_DT #ifndef NVPPS_NO_DT
#if defined(NV_CLASS_CREATE_HAS_NO_OWNER_ARG) /* Linux v6.4 */ #if defined(NV_CLASS_CREATE_HAS_NO_OWNER_ARG) /* Linux v6.4 */
@@ -1327,14 +1359,13 @@ static int nvpps_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pdev_data); platform_set_drvdata(pdev, pdev_data);
/* setup PPS event hndler */ /* setup PPS event hndler */
err = set_mode(pdev_data, err = set_mode(pdev_data, initial_mode);
(pdev_data->only_timer_mode) ? NVPPS_MODE_TIMER : NVPPS_MODE_GPIO);
if (err) { if (err) {
dev_err(&pdev->dev, "set_mode failed err = %d\n", err); dev_err(&pdev->dev, "set_mode failed err = %d\n", err);
device_destroy(s_nvpps_class, pdev_data->dev->devt); device_destroy(s_nvpps_class, pdev_data->dev->devt);
goto error_ret; goto error_ret;
} }
pdev_data->evt_mode = (pdev_data->only_timer_mode) ? NVPPS_MODE_TIMER : NVPPS_MODE_GPIO; pdev_data->evt_mode = initial_mode;
if (pdev_data->support_tsc) { if (pdev_data->support_tsc) {
struct resource *tsc_mem; struct resource *tsc_mem;