pwm: tachometer: Fix build for Linux v6.10

In Linux v6.10, a pointer to a dynamically allocated 'struct device'
was replaced with a statically allocated 'struct device' in the
'pwm_chip' structure. Update the Tegra PWM Tachometer driver accordingly
to fix the build for Linux v6.10.

Bug 4593750

Change-Id: I9d629746290282b5c1858f8308128d94ff155c49
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3123219
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Brad Griffis <bgriffis@nvidia.com>
This commit is contained in:
Jon Hunter
2024-04-10 15:08:06 +01:00
committed by mobile promotions
parent 39e07fb02b
commit 0104837e60
3 changed files with 67 additions and 27 deletions

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2022-2024, NVIDIA CORPORATION. All rights reserved. // SPDX-FileCopyrightText: Copyright (c) 2022-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <nvidia/conftest.h> #include <nvidia/conftest.h>
@@ -93,22 +93,33 @@ struct pwm_tegra_tach {
unsigned int capture_win_len; unsigned int capture_win_len;
unsigned int upper_threshold; unsigned int upper_threshold;
unsigned int lower_threshold; unsigned int lower_threshold;
#if !defined(NV_PWM_CHIP_STRUCT_HAS_STRUCT_DEVICE)
struct pwm_chip chip; struct pwm_chip chip;
#endif
const struct pwm_tegra_tach_soc_data *soc_data; const struct pwm_tegra_tach_soc_data *soc_data;
}; };
static struct pwm_tegra_tach *to_tegra_pwm_chip(struct pwm_chip *chip)
{
#if defined(NV_PWM_CHIP_STRUCT_HAS_STRUCT_DEVICE)
return pwmchip_get_drvdata(chip);
#else
return container_of(chip, struct pwm_tegra_tach, chip);
#endif
}
static ssize_t rpm_show(struct device *dev, struct device_attribute *attr, static ssize_t rpm_show(struct device *dev, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct pwm_tegra_tach *ptt = dev_get_drvdata(dev); struct pwm_chip *chip = dev_get_drvdata(dev);
struct pwm_device *pwm = &ptt->chip.pwms[0]; struct pwm_device *pwm = &chip->pwms[0];
struct pwm_capture result; struct pwm_capture result;
unsigned int rpm = 0; unsigned int rpm = 0;
int ret; int ret;
ret = pwm_capture(pwm, &result, 0); ret = pwm_capture(pwm, &result, 0);
if (ret < 0) { if (ret < 0) {
dev_err(ptt->dev, "Failed to capture PWM: %d\n", ret); dev_err(dev, "Failed to capture PWM: %d\n", ret);
return ret; return ret;
} }
@@ -128,11 +139,6 @@ static struct attribute *pwm_tach_attrs[] = {
ATTRIBUTE_GROUPS(pwm_tach); ATTRIBUTE_GROUPS(pwm_tach);
static struct pwm_tegra_tach *to_tegra_pwm_chip(struct pwm_chip *chip)
{
return container_of(chip, struct pwm_tegra_tach, chip);
}
static u32 tachometer_readl(struct pwm_tegra_tach *ptt, unsigned long reg) static u32 tachometer_readl(struct pwm_tegra_tach *ptt, unsigned long reg)
{ {
return readl(ptt->regs + reg); return readl(ptt->regs + reg);
@@ -349,16 +355,33 @@ static void pwm_tegra_tach_read_platform_data(struct pwm_tegra_tach *ptt)
static int pwm_tegra_tach_probe(struct platform_device *pdev) static int pwm_tegra_tach_probe(struct platform_device *pdev)
{ {
struct pwm_chip *chip;
struct pwm_tegra_tach *ptt; struct pwm_tegra_tach *ptt;
struct pwm_device *pwm; struct pwm_device *pwm;
struct device *hwmon; struct device *hwmon;
struct resource *r; struct resource *r;
int ret; int ret;
#if defined(NV_PWM_CHIP_STRUCT_HAS_STRUCT_DEVICE)
chip = devm_pwmchip_alloc(&pdev->dev, 1, sizeof(*ptt));
if (IS_ERR(chip))
return PTR_ERR(chip);
ptt = to_tegra_pwm_chip(chip);
#else
ptt = devm_kzalloc(&pdev->dev, sizeof(*ptt), GFP_KERNEL); ptt = devm_kzalloc(&pdev->dev, sizeof(*ptt), GFP_KERNEL);
if (!ptt) if (!ptt)
return -ENOMEM; return -ENOMEM;
chip = &ptt->chip;
chip->dev = &pdev->dev;
chip->npwm = 1;
#endif
chip->ops = &pwm_tegra_tach_ops;
#if defined(NV_PWM_CHIP_STRUCT_HAS_BASE_ARG)
chip->base = -1;
#endif
ptt->dev = &pdev->dev; ptt->dev = &pdev->dev;
ptt->soc_data = of_device_get_match_data(&pdev->dev); ptt->soc_data = of_device_get_match_data(&pdev->dev);
@@ -374,7 +397,7 @@ static int pwm_tegra_tach_probe(struct platform_device *pdev)
if (IS_ERR(ptt->regs)) if (IS_ERR(ptt->regs))
return PTR_ERR(ptt->regs); return PTR_ERR(ptt->regs);
platform_set_drvdata(pdev, ptt); platform_set_drvdata(pdev, chip);
ptt->clk = devm_clk_get(&pdev->dev, "tach"); ptt->clk = devm_clk_get(&pdev->dev, "tach");
if (IS_ERR(ptt->clk)) { if (IS_ERR(ptt->clk)) {
@@ -428,14 +451,7 @@ static int pwm_tegra_tach_probe(struct platform_device *pdev)
} }
} }
ptt->chip.dev = &pdev->dev; ret = pwmchip_add(chip);
ptt->chip.ops = &pwm_tegra_tach_ops;
#if defined(NV_PWM_CHIP_STRUCT_HAS_BASE_ARG)
ptt->chip.base = -1;
#endif
ptt->chip.npwm = 1;
ret = pwmchip_add(&ptt->chip);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "Failed to add tachometer PWM: %d\n", ret); dev_err(&pdev->dev, "Failed to add tachometer PWM: %d\n", ret);
goto reset_assert; goto reset_assert;
@@ -445,11 +461,11 @@ static int pwm_tegra_tach_probe(struct platform_device *pdev)
* Pulse Per Revolution Value to measure the accurate time period values * Pulse Per Revolution Value to measure the accurate time period values
*/ */
pwm = &ptt->chip.pwms[0]; pwm = &chip->pwms[0];
if (ptt->pulse_per_rev > ptt->capture_win_len) if (ptt->pulse_per_rev > ptt->capture_win_len)
ptt->capture_win_len = ptt->pulse_per_rev; ptt->capture_win_len = ptt->pulse_per_rev;
ret = pwm_tegra_tacho_set_capture_wlen(&ptt->chip, pwm, ptt->capture_win_len); ret = pwm_tegra_tacho_set_capture_wlen(chip, pwm, ptt->capture_win_len);
if (ret < 0) { if (ret < 0) {
dev_err(ptt->dev, "Failed to set window length: %d\n", ret); dev_err(ptt->dev, "Failed to set window length: %d\n", ret);
goto pwm_remove; goto pwm_remove;
@@ -457,7 +473,7 @@ static int pwm_tegra_tach_probe(struct platform_device *pdev)
if (ptt->soc_data->has_interrupt_support) { if (ptt->soc_data->has_interrupt_support) {
/* set upper and lower threshold values */ /* set upper and lower threshold values */
pwm_tegra_tacho_set_threshold(&ptt->chip); pwm_tegra_tacho_set_threshold(chip);
/* program tach fan control reg */ /* program tach fan control reg */
tach_update_mask(ptt, TACH_ERR_CONFIG_MONITOR_PERIOD_VAL, tach_update_mask(ptt, TACH_ERR_CONFIG_MONITOR_PERIOD_VAL,
@@ -473,7 +489,7 @@ static int pwm_tegra_tach_probe(struct platform_device *pdev)
} }
hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, DRIVER_NAME, ptt, pwm_tach_groups); hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, DRIVER_NAME, chip, pwm_tach_groups);
if (IS_ERR(hwmon)) { if (IS_ERR(hwmon)) {
dev_warn(&pdev->dev, "Failed to register hwmon device: %d\n", PTR_ERR_OR_ZERO(hwmon)); dev_warn(&pdev->dev, "Failed to register hwmon device: %d\n", PTR_ERR_OR_ZERO(hwmon));
dev_warn(&pdev->dev, "Tegra Tachometer got registered witout hwmon sysfs support\n"); dev_warn(&pdev->dev, "Tegra Tachometer got registered witout hwmon sysfs support\n");
@@ -482,7 +498,7 @@ static int pwm_tegra_tach_probe(struct platform_device *pdev)
return 0; return 0;
pwm_remove: pwm_remove:
pwmchip_remove(&ptt->chip); pwmchip_remove(chip);
reset_assert: reset_assert:
reset_control_assert(ptt->rst); reset_control_assert(ptt->rst);
@@ -495,7 +511,8 @@ clk_unprep:
static int pwm_tegra_tach_remove(struct platform_device *pdev) static int pwm_tegra_tach_remove(struct platform_device *pdev)
{ {
struct pwm_tegra_tach *ptt = platform_get_drvdata(pdev); struct pwm_chip *chip = platform_get_drvdata(pdev);
struct pwm_tegra_tach *ptt = to_tegra_pwm_chip(chip);
if (WARN_ON(!ptt)) if (WARN_ON(!ptt))
return -ENODEV; return -ENODEV;
@@ -504,7 +521,7 @@ static int pwm_tegra_tach_remove(struct platform_device *pdev)
clk_disable_unprepare(ptt->clk); clk_disable_unprepare(ptt->clk);
pwmchip_remove(&ptt->chip); pwmchip_remove(chip);
return 0; return 0;
} }
@@ -516,7 +533,8 @@ static int pwm_tegra_tach_suspend(struct device *dev)
static int pwm_tegra_tach_resume(struct device *dev) static int pwm_tegra_tach_resume(struct device *dev)
{ {
struct pwm_tegra_tach *ptt = dev_get_drvdata(dev); struct pwm_chip *chip = dev_get_drvdata(dev);
struct pwm_tegra_tach *ptt = to_tegra_pwm_chip(chip);
pwm_tegra_tacho_set_wlen(ptt, ptt->capture_win_len); pwm_tegra_tacho_set_wlen(ptt, ptt->capture_win_len);

View File

@@ -139,6 +139,7 @@ NV_CONFTEST_FUNCTION_COMPILE_TESTS += gpio_device_find
NV_CONFTEST_FUNCTION_COMPILE_TESTS += gpio_device_get_chip NV_CONFTEST_FUNCTION_COMPILE_TESTS += gpio_device_get_chip
NV_CONFTEST_FUNCTION_COMPILE_TESTS += pde_data NV_CONFTEST_FUNCTION_COMPILE_TESTS += pde_data
NV_CONFTEST_FUNCTION_COMPILE_TESTS += pwm_chip_struct_has_base_arg NV_CONFTEST_FUNCTION_COMPILE_TESTS += pwm_chip_struct_has_base_arg
NV_CONFTEST_FUNCTION_COMPILE_TESTS += pwm_chip_struct_has_struct_device
NV_CONFTEST_FUNCTION_COMPILE_TESTS += pwm_ops_struct_has_owner NV_CONFTEST_FUNCTION_COMPILE_TESTS += pwm_ops_struct_has_owner
NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_disable_pcie_error_reporting NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_disable_pcie_error_reporting
NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_enable_pcie_error_reporting NV_CONFTEST_FUNCTION_COMPILE_TESTS += pci_enable_pcie_error_reporting

View File

@@ -6713,6 +6713,27 @@ compile_test() {
compile_check_conftest "$CODE" "NV_DEVICE_ADD_DISK_HAS_INT_RETURN_TYPE" "" "types" compile_check_conftest "$CODE" "NV_DEVICE_ADD_DISK_HAS_INT_RETURN_TYPE" "" "types"
;; ;;
pwm_chip_struct_has_struct_device)
#
# Determine whether the pwm_chip structure has a 'struct device'
# member and not a pointer to a dynamically allocated
# 'struct device'.
#
# Commit 4c56b1434b81 ("pwm: Add a struct device to struct
# pwm_chip") replaced a pointer to a dynamically allocated
# 'struct device' with a statically allocated 'struct device'.
# Note that this is part of a large re-work of the PWM core to
# move the allocation of the pwm_chip structure into the PWM core.
#
CODE="
#include <linux/pwm.h>
void conftest_pwm_chip_struct_has_struct_device(struct pwm_chip *chip) {
struct device *dev = &chip->dev;
}"
compile_check_conftest "$CODE" "NV_PWM_CHIP_STRUCT_HAS_STRUCT_DEVICE" "" "types"
;;
devm_tegra_core_dev_init_opp_table_common) devm_tegra_core_dev_init_opp_table_common)
# #
# Determine whether devm_tegra_core_dev_init_opp_table_common is # Determine whether devm_tegra_core_dev_init_opp_table_common is