From: Zev Weiss <zev@bewilderbeest.net> To: linux-hwmon@vger.kernel.org Cc: Guenter Roeck <linux@roeck-us.net>, Jean Delvare <jdelvare@suse.com>, openbmc@lists.ozlabs.org, linux-kernel@vger.kernel.org, Zev Weiss <zev@bewilderbeest.net> Subject: [PATCH v2 1/2] hwmon: add Delta AHE-50DC fan control module driver Date: Mon, 6 Dec 2021 15:01:52 -0800 [thread overview] Message-ID: <20211206230153.16891-2-zev@bewilderbeest.net> (raw) In-Reply-To: <20211206230153.16891-1-zev@bewilderbeest.net> This device is an integrated module of the Delta AHE-50DC Open19 power shelf. For lack of proper documentation, this driver has been developed referencing an existing (GPL) driver that was included in a code release from LinkedIn [1]. It provides four fan speeds, four temperatures, and one voltage reading, as well as a handful of warning and fault indicators. [1] https://github.com/linkedin/o19-bmc-firmware/blob/master/meta-openbmc/meta-linkedin/meta-deltapower/recipes-kernel/fancontrol-mod/files/fancontrol.c Signed-off-by: Zev Weiss <zev@bewilderbeest.net> --- MAINTAINERS | 6 + drivers/hwmon/Kconfig | 11 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/delta-ahe50dc-fan.c | 265 ++++++++++++++++++++++++++++++ 4 files changed, 283 insertions(+) create mode 100644 drivers/hwmon/delta-ahe50dc-fan.c diff --git a/MAINTAINERS b/MAINTAINERS index 0ac052200ecb..d3f54b6f9550 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5425,6 +5425,12 @@ W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git F: drivers/media/platform/sti/delta +DELTA AHE-50DC FAN CONTROL MODULE DRIVER +M: Zev Weiss <zev@bewilderbeest.net> +L: linux-hwmon@vger.kernel.org +S: Maintained +F: drivers/hwmon/delta-ahe50dc-fan.c + DELTA DPS920AB PSU DRIVER M: Robert Marko <robert.marko@sartura.hr> L: linux-hwmon@vger.kernel.org diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 43e5245874ad..394a9e99fedc 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -505,6 +505,17 @@ config SENSORS_DELL_SMM When option I8K is also enabled this driver provides legacy /proc/i8k userspace interface for i8kutils package. +config SENSORS_DELTA_AHE50DC_FAN + tristate "Delta AHE-50DC fan control module" + depends on I2C + select REGMAP_I2C + help + If you say yes here you get support for the fan control + module of the Delta AHE-50DC Open19 power shelf. + + This driver can also be built as a module. If so, the module + will be called delta-ahe50dc-fan. + config SENSORS_DA9052_ADC tristate "Dialog DA9052/DA9053 ADC" depends on PMIC_DA9052 diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 3a1551b3d570..ea73ddab5fd3 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_SENSORS_CORSAIR_PSU) += corsair-psu.o obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o obj-$(CONFIG_SENSORS_DELL_SMM) += dell-smm-hwmon.o +obj-$(CONFIG_SENSORS_DELTA_AHE50DC_FAN) += delta-ahe50dc-fan.o obj-$(CONFIG_SENSORS_DME1737) += dme1737.o obj-$(CONFIG_SENSORS_DRIVETEMP) += drivetemp.o obj-$(CONFIG_SENSORS_DS620) += ds620.o diff --git a/drivers/hwmon/delta-ahe50dc-fan.c b/drivers/hwmon/delta-ahe50dc-fan.c new file mode 100644 index 000000000000..d76301d9128a --- /dev/null +++ b/drivers/hwmon/delta-ahe50dc-fan.c @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Delta AHE-50DC power shelf fan control module driver + * + * Copyright 2021 Zev Weiss <zev@bewilderbeest.net> + */ + +#include <linux/module.h> +#include <linux/hwmon.h> +#include <linux/i2c.h> +#include <linux/regmap.h> + +static const u8 AHE50DC_FAN_TEMP_REGS[] = { 0x8d, 0x8e, 0x8f, 0xd0 }; +static const u8 AHE50DC_FAN_SPEED_REGS[] = { 0x90, 0x91, 0x92, 0x93 }; +static const u8 AHE50DC_FAN_FAN_STATUS_REGS[] = { 0x81, 0x82 }; +#define AHE50DC_FAN_VIN_REG 0x88 +#define AHE50DC_FAN_CHIP_STATUS_REG 0x79 + +static int ahe50dc_fan_get_temp(struct regmap *regmap, int channel, long *val) +{ + int ret; + unsigned int reg; + + if (channel >= ARRAY_SIZE(AHE50DC_FAN_TEMP_REGS)) + return -EINVAL; + + ret = regmap_read(regmap, AHE50DC_FAN_TEMP_REGS[channel], ®); + if (ret < 0) + return ret; + + /* Temp regs report tenths of a degree C; convert to millidegrees */ + *val = reg * 100; + + return 0; +} + +static int ahe50dc_fan_get_fan(struct regmap *regmap, int channel, long *val) +{ + int ret; + unsigned int reg; + + if (channel >= ARRAY_SIZE(AHE50DC_FAN_SPEED_REGS)) + return -EINVAL; + + ret = regmap_read(regmap, AHE50DC_FAN_SPEED_REGS[channel], ®); + if (ret < 0) + return ret; + + *val = reg; + + return 0; +} + +static int ahe50dc_fan_get_fan_status(struct regmap *regmap, int channel, u32 attr, long *val) +{ + int ret; + unsigned int reg, bit; + int regidx = channel / 2; + + if (regidx >= ARRAY_SIZE(AHE50DC_FAN_FAN_STATUS_REGS) || + (attr != hwmon_fan_fault && attr != hwmon_fan_alarm)) + return -EINVAL; + + ret = regmap_read(regmap, AHE50DC_FAN_FAN_STATUS_REGS[regidx], ®); + if (ret < 0) + return ret; + + /* + * Fan status register bits: + * bit 0: fan 1/3 fault + * bit 1: fan 1/3 warn + * bit 8: fan 2/4 fault + * bit 9: fan 2/4 warn + */ + bit = ((channel % 2) * 8) + (attr == hwmon_fan_alarm); + *val = !!(reg & BIT(bit)); + + return 0; +} + +static int ahe50dc_fan_get_vin(struct regmap *regmap, int channel, long *val) +{ + int ret; + unsigned int reg; + + if (channel) + return -EINVAL; + + ret = regmap_read(regmap, AHE50DC_FAN_VIN_REG, ®); + if (ret < 0) + return ret; + + *val = reg; + + return 0; +} + +static int ahe50dc_fan_get_chip_status(struct regmap *regmap, enum hwmon_sensor_types type, + int channel, u32 attr, long *val) +{ + int ret; + unsigned int reg, bit; + + if (type == hwmon_temp && attr == hwmon_temp_alarm && channel == 4) + bit = 2; + else if (type == hwmon_fan && attr == hwmon_fan_alarm && channel == 4) + bit = 11; + else if (type == hwmon_in && attr == hwmon_in_alarm && channel == 1) + bit = 15; + else + return -EINVAL; + + ret = regmap_read(regmap, AHE50DC_FAN_CHIP_STATUS_REG, ®); + if (ret < 0) + return ret; + + *val = !!(reg & BIT(bit)); + + return 0; +} + +static int ahe50dc_fan_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, + int channel, long *val) +{ + struct regmap *regmap = dev_get_drvdata(dev); + + switch (type) { + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: + return ahe50dc_fan_get_temp(regmap, channel, val); + case hwmon_temp_alarm: + return ahe50dc_fan_get_chip_status(regmap, type, channel, attr, val); + default: + return -EOPNOTSUPP; + } + + case hwmon_fan: + switch (attr) { + case hwmon_fan_input: + return ahe50dc_fan_get_fan(regmap, channel, val); + case hwmon_fan_alarm: + case hwmon_fan_fault: + if (channel == 4) + return ahe50dc_fan_get_chip_status(regmap, type, channel, + attr, val); + return ahe50dc_fan_get_fan_status(regmap, channel, attr, val); + default: + return -EOPNOTSUPP; + } + + case hwmon_in: + switch (attr) { + case hwmon_in_input: + return ahe50dc_fan_get_vin(regmap, channel, val); + case hwmon_in_alarm: + return ahe50dc_fan_get_chip_status(regmap, type, channel, attr, val); + default: + return -EOPNOTSUPP; + } + + default: + return -EOPNOTSUPP; + } +} + +static int ahe50dc_fan_read_labels(struct device *dev, enum hwmon_sensor_types type, u32 attr, + int channel, const char **str) +{ + if (attr == hwmon_in_input && channel < 2) { + *str = channel ? "vout" : "vin"; + return 0; + } + + return -EOPNOTSUPP; +} + +static umode_t ahe50dc_fan_is_visible(const void *data, enum hwmon_sensor_types type, + u32 attr, int channel) +{ + return 0444; +} + +static const struct hwmon_channel_info *ahe50dc_fan_info[] = { + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_ALARM), + HWMON_CHANNEL_INFO(fan, + HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_ALARM, + HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_ALARM, + HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_ALARM, + HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_ALARM, + HWMON_F_ALARM), + HWMON_CHANNEL_INFO(in, + HWMON_I_INPUT | HWMON_I_LABEL, + HWMON_I_ALARM | HWMON_I_LABEL), + NULL +}; + +static const struct hwmon_ops ahe50dc_fan_ops = { + .is_visible = ahe50dc_fan_is_visible, + .read = ahe50dc_fan_read, + .read_string = ahe50dc_fan_read_labels, +}; + +static const struct hwmon_chip_info ahe50dc_fan_chip_info = { + .ops = &ahe50dc_fan_ops, + .info = ahe50dc_fan_info, +}; + +static const struct regmap_config ahe50dc_fan_regmap_config = { + .reg_bits = 8, + .val_bits = 16, + .val_format_endian = REGMAP_ENDIAN_LITTLE, +}; + +static int ahe50dc_fan_probe(struct i2c_client *client) +{ + struct regmap *regmap; + struct device *hwmon_dev; + struct device *dev = &client->dev; + + regmap = devm_regmap_init_i2c(client, &ahe50dc_fan_regmap_config); + if (IS_ERR(regmap)) { + dev_err(dev, "regmap init failed\n"); + return PTR_ERR(regmap); + } + + i2c_set_clientdata(client, regmap); + + hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, regmap, + &ahe50dc_fan_chip_info, NULL); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static const struct i2c_device_id ahe50dc_fan_id[] = { + { "ahe50dc_fan" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ahe50dc_fan_id); + +const struct of_device_id __maybe_unused ahe50dc_fan_of_match[] = { + { .compatible = "delta,ahe50dc-fan" }, + { } +}; +MODULE_DEVICE_TABLE(of, ahe50dc_fan_of_match); + +static struct i2c_driver ahe50dc_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ahe50dc_fan", + .of_match_table = of_match_ptr(ahe50dc_fan_of_match), + }, + .probe_new = ahe50dc_fan_probe, + .id_table = ahe50dc_fan_id, +}; +module_i2c_driver(ahe50dc_fan_driver); + +MODULE_AUTHOR("Zev Weiss <zev@bewilderbeest.net>"); +MODULE_DESCRIPTION("Driver for Delta AHE-50DC power shelf fan control module"); +MODULE_LICENSE("GPL"); -- 2.34.1
WARNING: multiple messages have this Message-ID (diff)
From: Zev Weiss <zev@bewilderbeest.net> To: linux-hwmon@vger.kernel.org Cc: openbmc@lists.ozlabs.org, Jean Delvare <jdelvare@suse.com>, linux-kernel@vger.kernel.org, Guenter Roeck <linux@roeck-us.net>, Zev Weiss <zev@bewilderbeest.net> Subject: [PATCH v2 1/2] hwmon: add Delta AHE-50DC fan control module driver Date: Mon, 6 Dec 2021 15:01:52 -0800 [thread overview] Message-ID: <20211206230153.16891-2-zev@bewilderbeest.net> (raw) In-Reply-To: <20211206230153.16891-1-zev@bewilderbeest.net> This device is an integrated module of the Delta AHE-50DC Open19 power shelf. For lack of proper documentation, this driver has been developed referencing an existing (GPL) driver that was included in a code release from LinkedIn [1]. It provides four fan speeds, four temperatures, and one voltage reading, as well as a handful of warning and fault indicators. [1] https://github.com/linkedin/o19-bmc-firmware/blob/master/meta-openbmc/meta-linkedin/meta-deltapower/recipes-kernel/fancontrol-mod/files/fancontrol.c Signed-off-by: Zev Weiss <zev@bewilderbeest.net> --- MAINTAINERS | 6 + drivers/hwmon/Kconfig | 11 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/delta-ahe50dc-fan.c | 265 ++++++++++++++++++++++++++++++ 4 files changed, 283 insertions(+) create mode 100644 drivers/hwmon/delta-ahe50dc-fan.c diff --git a/MAINTAINERS b/MAINTAINERS index 0ac052200ecb..d3f54b6f9550 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5425,6 +5425,12 @@ W: https://linuxtv.org T: git git://linuxtv.org/media_tree.git F: drivers/media/platform/sti/delta +DELTA AHE-50DC FAN CONTROL MODULE DRIVER +M: Zev Weiss <zev@bewilderbeest.net> +L: linux-hwmon@vger.kernel.org +S: Maintained +F: drivers/hwmon/delta-ahe50dc-fan.c + DELTA DPS920AB PSU DRIVER M: Robert Marko <robert.marko@sartura.hr> L: linux-hwmon@vger.kernel.org diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 43e5245874ad..394a9e99fedc 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -505,6 +505,17 @@ config SENSORS_DELL_SMM When option I8K is also enabled this driver provides legacy /proc/i8k userspace interface for i8kutils package. +config SENSORS_DELTA_AHE50DC_FAN + tristate "Delta AHE-50DC fan control module" + depends on I2C + select REGMAP_I2C + help + If you say yes here you get support for the fan control + module of the Delta AHE-50DC Open19 power shelf. + + This driver can also be built as a module. If so, the module + will be called delta-ahe50dc-fan. + config SENSORS_DA9052_ADC tristate "Dialog DA9052/DA9053 ADC" depends on PMIC_DA9052 diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 3a1551b3d570..ea73ddab5fd3 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_SENSORS_CORSAIR_PSU) += corsair-psu.o obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o obj-$(CONFIG_SENSORS_DA9055)+= da9055-hwmon.o obj-$(CONFIG_SENSORS_DELL_SMM) += dell-smm-hwmon.o +obj-$(CONFIG_SENSORS_DELTA_AHE50DC_FAN) += delta-ahe50dc-fan.o obj-$(CONFIG_SENSORS_DME1737) += dme1737.o obj-$(CONFIG_SENSORS_DRIVETEMP) += drivetemp.o obj-$(CONFIG_SENSORS_DS620) += ds620.o diff --git a/drivers/hwmon/delta-ahe50dc-fan.c b/drivers/hwmon/delta-ahe50dc-fan.c new file mode 100644 index 000000000000..d76301d9128a --- /dev/null +++ b/drivers/hwmon/delta-ahe50dc-fan.c @@ -0,0 +1,265 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Delta AHE-50DC power shelf fan control module driver + * + * Copyright 2021 Zev Weiss <zev@bewilderbeest.net> + */ + +#include <linux/module.h> +#include <linux/hwmon.h> +#include <linux/i2c.h> +#include <linux/regmap.h> + +static const u8 AHE50DC_FAN_TEMP_REGS[] = { 0x8d, 0x8e, 0x8f, 0xd0 }; +static const u8 AHE50DC_FAN_SPEED_REGS[] = { 0x90, 0x91, 0x92, 0x93 }; +static const u8 AHE50DC_FAN_FAN_STATUS_REGS[] = { 0x81, 0x82 }; +#define AHE50DC_FAN_VIN_REG 0x88 +#define AHE50DC_FAN_CHIP_STATUS_REG 0x79 + +static int ahe50dc_fan_get_temp(struct regmap *regmap, int channel, long *val) +{ + int ret; + unsigned int reg; + + if (channel >= ARRAY_SIZE(AHE50DC_FAN_TEMP_REGS)) + return -EINVAL; + + ret = regmap_read(regmap, AHE50DC_FAN_TEMP_REGS[channel], ®); + if (ret < 0) + return ret; + + /* Temp regs report tenths of a degree C; convert to millidegrees */ + *val = reg * 100; + + return 0; +} + +static int ahe50dc_fan_get_fan(struct regmap *regmap, int channel, long *val) +{ + int ret; + unsigned int reg; + + if (channel >= ARRAY_SIZE(AHE50DC_FAN_SPEED_REGS)) + return -EINVAL; + + ret = regmap_read(regmap, AHE50DC_FAN_SPEED_REGS[channel], ®); + if (ret < 0) + return ret; + + *val = reg; + + return 0; +} + +static int ahe50dc_fan_get_fan_status(struct regmap *regmap, int channel, u32 attr, long *val) +{ + int ret; + unsigned int reg, bit; + int regidx = channel / 2; + + if (regidx >= ARRAY_SIZE(AHE50DC_FAN_FAN_STATUS_REGS) || + (attr != hwmon_fan_fault && attr != hwmon_fan_alarm)) + return -EINVAL; + + ret = regmap_read(regmap, AHE50DC_FAN_FAN_STATUS_REGS[regidx], ®); + if (ret < 0) + return ret; + + /* + * Fan status register bits: + * bit 0: fan 1/3 fault + * bit 1: fan 1/3 warn + * bit 8: fan 2/4 fault + * bit 9: fan 2/4 warn + */ + bit = ((channel % 2) * 8) + (attr == hwmon_fan_alarm); + *val = !!(reg & BIT(bit)); + + return 0; +} + +static int ahe50dc_fan_get_vin(struct regmap *regmap, int channel, long *val) +{ + int ret; + unsigned int reg; + + if (channel) + return -EINVAL; + + ret = regmap_read(regmap, AHE50DC_FAN_VIN_REG, ®); + if (ret < 0) + return ret; + + *val = reg; + + return 0; +} + +static int ahe50dc_fan_get_chip_status(struct regmap *regmap, enum hwmon_sensor_types type, + int channel, u32 attr, long *val) +{ + int ret; + unsigned int reg, bit; + + if (type == hwmon_temp && attr == hwmon_temp_alarm && channel == 4) + bit = 2; + else if (type == hwmon_fan && attr == hwmon_fan_alarm && channel == 4) + bit = 11; + else if (type == hwmon_in && attr == hwmon_in_alarm && channel == 1) + bit = 15; + else + return -EINVAL; + + ret = regmap_read(regmap, AHE50DC_FAN_CHIP_STATUS_REG, ®); + if (ret < 0) + return ret; + + *val = !!(reg & BIT(bit)); + + return 0; +} + +static int ahe50dc_fan_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, + int channel, long *val) +{ + struct regmap *regmap = dev_get_drvdata(dev); + + switch (type) { + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: + return ahe50dc_fan_get_temp(regmap, channel, val); + case hwmon_temp_alarm: + return ahe50dc_fan_get_chip_status(regmap, type, channel, attr, val); + default: + return -EOPNOTSUPP; + } + + case hwmon_fan: + switch (attr) { + case hwmon_fan_input: + return ahe50dc_fan_get_fan(regmap, channel, val); + case hwmon_fan_alarm: + case hwmon_fan_fault: + if (channel == 4) + return ahe50dc_fan_get_chip_status(regmap, type, channel, + attr, val); + return ahe50dc_fan_get_fan_status(regmap, channel, attr, val); + default: + return -EOPNOTSUPP; + } + + case hwmon_in: + switch (attr) { + case hwmon_in_input: + return ahe50dc_fan_get_vin(regmap, channel, val); + case hwmon_in_alarm: + return ahe50dc_fan_get_chip_status(regmap, type, channel, attr, val); + default: + return -EOPNOTSUPP; + } + + default: + return -EOPNOTSUPP; + } +} + +static int ahe50dc_fan_read_labels(struct device *dev, enum hwmon_sensor_types type, u32 attr, + int channel, const char **str) +{ + if (attr == hwmon_in_input && channel < 2) { + *str = channel ? "vout" : "vin"; + return 0; + } + + return -EOPNOTSUPP; +} + +static umode_t ahe50dc_fan_is_visible(const void *data, enum hwmon_sensor_types type, + u32 attr, int channel) +{ + return 0444; +} + +static const struct hwmon_channel_info *ahe50dc_fan_info[] = { + HWMON_CHANNEL_INFO(temp, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_INPUT, + HWMON_T_ALARM), + HWMON_CHANNEL_INFO(fan, + HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_ALARM, + HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_ALARM, + HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_ALARM, + HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_ALARM, + HWMON_F_ALARM), + HWMON_CHANNEL_INFO(in, + HWMON_I_INPUT | HWMON_I_LABEL, + HWMON_I_ALARM | HWMON_I_LABEL), + NULL +}; + +static const struct hwmon_ops ahe50dc_fan_ops = { + .is_visible = ahe50dc_fan_is_visible, + .read = ahe50dc_fan_read, + .read_string = ahe50dc_fan_read_labels, +}; + +static const struct hwmon_chip_info ahe50dc_fan_chip_info = { + .ops = &ahe50dc_fan_ops, + .info = ahe50dc_fan_info, +}; + +static const struct regmap_config ahe50dc_fan_regmap_config = { + .reg_bits = 8, + .val_bits = 16, + .val_format_endian = REGMAP_ENDIAN_LITTLE, +}; + +static int ahe50dc_fan_probe(struct i2c_client *client) +{ + struct regmap *regmap; + struct device *hwmon_dev; + struct device *dev = &client->dev; + + regmap = devm_regmap_init_i2c(client, &ahe50dc_fan_regmap_config); + if (IS_ERR(regmap)) { + dev_err(dev, "regmap init failed\n"); + return PTR_ERR(regmap); + } + + i2c_set_clientdata(client, regmap); + + hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, regmap, + &ahe50dc_fan_chip_info, NULL); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static const struct i2c_device_id ahe50dc_fan_id[] = { + { "ahe50dc_fan" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ahe50dc_fan_id); + +const struct of_device_id __maybe_unused ahe50dc_fan_of_match[] = { + { .compatible = "delta,ahe50dc-fan" }, + { } +}; +MODULE_DEVICE_TABLE(of, ahe50dc_fan_of_match); + +static struct i2c_driver ahe50dc_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "ahe50dc_fan", + .of_match_table = of_match_ptr(ahe50dc_fan_of_match), + }, + .probe_new = ahe50dc_fan_probe, + .id_table = ahe50dc_fan_id, +}; +module_i2c_driver(ahe50dc_fan_driver); + +MODULE_AUTHOR("Zev Weiss <zev@bewilderbeest.net>"); +MODULE_DESCRIPTION("Driver for Delta AHE-50DC power shelf fan control module"); +MODULE_LICENSE("GPL"); -- 2.34.1
next prev parent reply other threads:[~2021-12-06 23:02 UTC|newest] Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-12-06 23:01 [PATCH v2 0/2] hwmon: Add driver for Delta AHE-50DC fan control module Zev Weiss 2021-12-06 23:01 ` Zev Weiss 2021-12-06 23:01 ` Zev Weiss [this message] 2021-12-06 23:01 ` [PATCH v2 1/2] hwmon: add Delta AHE-50DC fan control module driver Zev Weiss 2021-12-06 23:01 ` [PATCH v2 2/2] dt-bindings: add Delta AHE-50DC fan control module Zev Weiss 2021-12-06 23:01 ` Zev Weiss
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20211206230153.16891-2-zev@bewilderbeest.net \ --to=zev@bewilderbeest.net \ --cc=jdelvare@suse.com \ --cc=linux-hwmon@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux@roeck-us.net \ --cc=openbmc@lists.ozlabs.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.