bcm27xx: update 6.1 patches to latest version
[openwrt/staging/dangole.git] / target / linux / bcm27xx / patches-6.1 / 950-0921-hwmon-pwm-fan-Add-fan-speed-register-support.patch
1 From 96a8a4776cb142f5d2bb7f6379df9af40e727c0b Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.com>
3 Date: Tue, 11 Jul 2023 10:17:29 +0100
4 Subject: [PATCH] hwmon: (pwm-fan) Add fan speed register support
5
6 Some platforms include a fan-speed register that reports RPM directly
7 as an alternative to counting interrupts from the fan tachometer input.
8 Add support for reading a register at a given offset (rpm-offset) within
9 a block declared in another node (rpm-regmap). This indirection allows
10 the usual address mapping to be performed, and for address sharing with
11 another driver.
12
13 Signed-off-by: Phil Elwell <phil@raspberrypi.com>
14 ---
15 drivers/hwmon/pwm-fan.c | 59 ++++++++++++++++++++++++++++++++++++-----
16 1 file changed, 52 insertions(+), 7 deletions(-)
17
18 --- a/drivers/hwmon/pwm-fan.c
19 +++ b/drivers/hwmon/pwm-fan.c
20 @@ -12,6 +12,7 @@
21 #include <linux/module.h>
22 #include <linux/mutex.h>
23 #include <linux/of.h>
24 +#include <linux/of_address.h>
25 #include <linux/platform_device.h>
26 #include <linux/pwm.h>
27 #include <linux/regulator/consumer.h>
28 @@ -51,6 +52,9 @@ struct pwm_fan_ctx {
29 ktime_t sample_start;
30 struct timer_list rpm_timer;
31
32 + void __iomem *rpm_regbase;
33 + unsigned int rpm_offset;
34 +
35 unsigned int pwm_value;
36 unsigned int pwm_fan_state;
37 unsigned int pwm_fan_max_state;
38 @@ -61,6 +65,10 @@ struct pwm_fan_ctx {
39 struct hwmon_channel_info fan_channel;
40 };
41
42 +static const u32 rpm_reg_channel_config[] = {
43 + HWMON_F_INPUT, 0
44 +};
45 +
46 /* This handler assumes self resetting edge triggered interrupt. */
47 static irqreturn_t pulse_handler(int irq, void *dev_id)
48 {
49 @@ -335,7 +343,10 @@ static int pwm_fan_read(struct device *d
50 }
51 return -EOPNOTSUPP;
52 case hwmon_fan:
53 - *val = ctx->tachs[channel].rpm;
54 + if (ctx->rpm_regbase)
55 + *val = (long)readl(ctx->rpm_regbase + ctx->rpm_offset);
56 + else
57 + *val = ctx->tachs[channel].rpm;
58 return 0;
59
60 default:
61 @@ -470,6 +481,7 @@ static void pwm_fan_cleanup(void *__ctx)
62 /* Switch off everything */
63 ctx->enable_mode = pwm_disable_reg_disable;
64 pwm_fan_power_off(ctx);
65 + iounmap(ctx->rpm_regbase);
66 }
67
68 static int pwm_fan_probe(struct platform_device *pdev)
69 @@ -534,10 +546,23 @@ static int pwm_fan_probe(struct platform
70 return ret;
71
72 ctx->tach_count = platform_irq_count(pdev);
73 + if (ctx->tach_count == 0) {
74 + struct device_node *rpm_node;
75 +
76 + rpm_node = of_parse_phandle(dev->of_node, "rpm-regmap", 0);
77 + if (rpm_node)
78 + ctx->rpm_regbase = of_iomap(rpm_node, 0);
79 + }
80 +
81 if (ctx->tach_count < 0)
82 return dev_err_probe(dev, ctx->tach_count,
83 "Could not get number of fan tachometer inputs\n");
84 - dev_dbg(dev, "%d fan tachometer inputs\n", ctx->tach_count);
85 + if (IS_ERR(ctx->rpm_regbase))
86 + return dev_err_probe(dev, PTR_ERR(ctx->rpm_regbase),
87 + "Could not get rpm reg\n");
88 +
89 + dev_dbg(dev, "%d fan tachometer inputs, %d rpm regmap\n", ctx->tach_count,
90 + !!ctx->rpm_regbase);
91
92 if (ctx->tach_count) {
93 channel_count++; /* We also have a FAN channel. */
94 @@ -554,12 +579,24 @@ static int pwm_fan_probe(struct platform
95 if (!fan_channel_config)
96 return -ENOMEM;
97 ctx->fan_channel.config = fan_channel_config;
98 + } else if (ctx->rpm_regbase) {
99 + channel_count++; /* We also have a FAN channel. */
100 + ctx->fan_channel.type = hwmon_fan;
101 + ctx->fan_channel.config = rpm_reg_channel_config;
102 +
103 + if (of_property_read_u32(pdev->dev.of_node, "rpm-offset", &ctx->rpm_offset)) {
104 + dev_err(&pdev->dev, "unable to read 'rpm-offset'");
105 + ret = -EINVAL;
106 + goto error;
107 + }
108 }
109
110 channels = devm_kcalloc(dev, channel_count + 1,
111 sizeof(struct hwmon_channel_info *), GFP_KERNEL);
112 - if (!channels)
113 - return -ENOMEM;
114 + if (!channels) {
115 + ret = -ENOMEM;
116 + goto error;
117 + }
118
119 channels[0] = HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT | HWMON_PWM_ENABLE);
120
121 @@ -602,6 +639,8 @@ static int pwm_fan_probe(struct platform
122 mod_timer(&ctx->rpm_timer, jiffies + HZ);
123
124 channels[1] = &ctx->fan_channel;
125 + } else if (ctx->rpm_regbase) {
126 + channels[1] = &ctx->fan_channel;
127 }
128
129 ctx->info.ops = &pwm_fan_hwmon_ops;
130 @@ -611,12 +650,13 @@ static int pwm_fan_probe(struct platform
131 ctx, &ctx->info, NULL);
132 if (IS_ERR(hwmon)) {
133 dev_err(dev, "Failed to register hwmon device\n");
134 - return PTR_ERR(hwmon);
135 + ret = PTR_ERR(hwmon);
136 + goto error;
137 }
138
139 ret = pwm_fan_of_get_cooling_data(dev, ctx);
140 if (ret)
141 - return ret;
142 + goto error;
143
144 ctx->pwm_fan_state = ctx->pwm_fan_max_state;
145 if (IS_ENABLED(CONFIG_THERMAL)) {
146 @@ -627,12 +667,17 @@ static int pwm_fan_probe(struct platform
147 dev_err(dev,
148 "Failed to register pwm-fan as cooling device: %d\n",
149 ret);
150 - return ret;
151 + goto error;
152 }
153 ctx->cdev = cdev;
154 }
155
156 return 0;
157 +
158 +error:
159 + if (ctx->rpm_regbase)
160 + iounmap(ctx->rpm_regbase);
161 + return ret;
162 }
163
164 static void pwm_fan_shutdown(struct platform_device *pdev)