1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (C) 2022 Hewlett-Packard Enterprise Development Company, L.P. */
4 #include <linux/bits.h>
6 #include <linux/hwmon.h>
8 #include <linux/module.h>
9 #include <linux/mod_devicetable.h>
10 #include <linux/platform_device.h>
12 #define OFS_FAN_INST 0 /* Is 0 because plreg base will be set at INST */
13 #define OFS_FAN_FAIL 2 /* Is 2 bytes after base */
14 #define OFS_SEVSTAT 0 /* Is 0 because fn2 base will be set at SEVSTAT */
17 struct gxp_fan_ctrl_drvdata
{
23 static bool fan_installed(struct device
*dev
, int fan
)
25 struct gxp_fan_ctrl_drvdata
*drvdata
= dev_get_drvdata(dev
);
28 val
= readb(drvdata
->plreg
+ OFS_FAN_INST
);
30 return !!(val
& BIT(fan
));
33 static long fan_failed(struct device
*dev
, int fan
)
35 struct gxp_fan_ctrl_drvdata
*drvdata
= dev_get_drvdata(dev
);
38 val
= readb(drvdata
->plreg
+ OFS_FAN_FAIL
);
40 return !!(val
& BIT(fan
));
43 static long fan_enabled(struct device
*dev
, int fan
)
45 struct gxp_fan_ctrl_drvdata
*drvdata
= dev_get_drvdata(dev
);
49 * Check the power status as if the platform is off the value
50 * reported for the PWM will be incorrect. Report fan as
53 val
= readl(drvdata
->fn2
+ OFS_SEVSTAT
);
55 return !!((val
& BIT(POWER_BIT
)) && fan_installed(dev
, fan
));
58 static int gxp_pwm_write(struct device
*dev
, u32 attr
, int channel
, long val
)
60 struct gxp_fan_ctrl_drvdata
*drvdata
= dev_get_drvdata(dev
);
64 if (val
> 255 || val
< 0)
66 writeb(val
, drvdata
->base
+ channel
);
73 static int gxp_fan_ctrl_write(struct device
*dev
, enum hwmon_sensor_types type
,
74 u32 attr
, int channel
, long val
)
78 return gxp_pwm_write(dev
, attr
, channel
, val
);
84 static int gxp_fan_read(struct device
*dev
, u32 attr
, int channel
, long *val
)
87 case hwmon_fan_enable
:
88 *val
= fan_enabled(dev
, channel
);
91 *val
= fan_failed(dev
, channel
);
98 static int gxp_pwm_read(struct device
*dev
, u32 attr
, int channel
, long *val
)
100 struct gxp_fan_ctrl_drvdata
*drvdata
= dev_get_drvdata(dev
);
104 * Check the power status of the platform. If the platform is off
105 * the value reported for the PWM will be incorrect. In this case
106 * report a PWM of zero.
109 reg
= readl(drvdata
->fn2
+ OFS_SEVSTAT
);
111 if (reg
& BIT(POWER_BIT
))
112 *val
= fan_installed(dev
, channel
) ? readb(drvdata
->base
+ channel
) : 0;
119 static int gxp_fan_ctrl_read(struct device
*dev
, enum hwmon_sensor_types type
,
120 u32 attr
, int channel
, long *val
)
124 return gxp_fan_read(dev
, attr
, channel
, val
);
126 return gxp_pwm_read(dev
, attr
, channel
, val
);
132 static umode_t
gxp_fan_ctrl_is_visible(const void *_data
,
133 enum hwmon_sensor_types type
,
134 u32 attr
, int channel
)
141 case hwmon_fan_enable
:
142 case hwmon_fan_fault
:
151 case hwmon_pwm_input
:
165 static const struct hwmon_ops gxp_fan_ctrl_ops
= {
166 .is_visible
= gxp_fan_ctrl_is_visible
,
167 .read
= gxp_fan_ctrl_read
,
168 .write
= gxp_fan_ctrl_write
,
171 static const struct hwmon_channel_info
* const gxp_fan_ctrl_info
[] = {
172 HWMON_CHANNEL_INFO(fan
,
173 HWMON_F_FAULT
| HWMON_F_ENABLE
,
174 HWMON_F_FAULT
| HWMON_F_ENABLE
,
175 HWMON_F_FAULT
| HWMON_F_ENABLE
,
176 HWMON_F_FAULT
| HWMON_F_ENABLE
,
177 HWMON_F_FAULT
| HWMON_F_ENABLE
,
178 HWMON_F_FAULT
| HWMON_F_ENABLE
,
179 HWMON_F_FAULT
| HWMON_F_ENABLE
,
180 HWMON_F_FAULT
| HWMON_F_ENABLE
),
181 HWMON_CHANNEL_INFO(pwm
,
193 static const struct hwmon_chip_info gxp_fan_ctrl_chip_info
= {
194 .ops
= &gxp_fan_ctrl_ops
,
195 .info
= gxp_fan_ctrl_info
,
199 static int gxp_fan_ctrl_probe(struct platform_device
*pdev
)
201 struct gxp_fan_ctrl_drvdata
*drvdata
;
202 struct device
*dev
= &pdev
->dev
;
203 struct device
*hwmon_dev
;
205 drvdata
= devm_kzalloc(dev
, sizeof(struct gxp_fan_ctrl_drvdata
),
210 drvdata
->base
= devm_platform_get_and_ioremap_resource(pdev
, 0, NULL
);
211 if (IS_ERR(drvdata
->base
))
212 return dev_err_probe(dev
, PTR_ERR(drvdata
->base
),
213 "failed to map base\n");
215 drvdata
->plreg
= devm_platform_ioremap_resource_byname(pdev
,
217 if (IS_ERR(drvdata
->plreg
))
218 return dev_err_probe(dev
, PTR_ERR(drvdata
->plreg
),
219 "failed to map plreg\n");
221 drvdata
->fn2
= devm_platform_ioremap_resource_byname(pdev
,
223 if (IS_ERR(drvdata
->fn2
))
224 return dev_err_probe(dev
, PTR_ERR(drvdata
->fn2
),
225 "failed to map fn2\n");
227 hwmon_dev
= devm_hwmon_device_register_with_info(&pdev
->dev
,
230 &gxp_fan_ctrl_chip_info
,
233 return PTR_ERR_OR_ZERO(hwmon_dev
);
236 static const struct of_device_id gxp_fan_ctrl_of_match
[] = {
237 { .compatible
= "hpe,gxp-fan-ctrl", },
240 MODULE_DEVICE_TABLE(of
, gxp_fan_ctrl_of_match
);
242 static struct platform_driver gxp_fan_ctrl_driver
= {
243 .probe
= gxp_fan_ctrl_probe
,
245 .name
= "gxp-fan-ctrl",
246 .of_match_table
= gxp_fan_ctrl_of_match
,
249 module_platform_driver(gxp_fan_ctrl_driver
);
251 MODULE_AUTHOR("Nick Hawkins <nick.hawkins@hpe.com>");
252 MODULE_DESCRIPTION("HPE GXP fan controller");
253 MODULE_LICENSE("GPL");