Loading arch/arm64/configs/vendor/lahaina_QGKI.config +2 −0 Original line number Diff line number Diff line Loading @@ -258,3 +258,5 @@ CONFIG_SRAM=y CONFIG_CRYPTO_SHA1_ARM64_CE=y CONFIG_PRINT_SUSPEND_EPOCH_QGKI=y CONFIG_SM_DEBUGCC_YUPIK=y CONFIG_MAX31760_FAN_CONTROLLER=y CONFIG_I2C_GPIO=y drivers/thermal/qcom/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -163,3 +163,12 @@ config QTI_DDR_COOLING_DEVICE devices will be used by QTI chipset to place a DDR state request to meet the performance requirement under thermally constrained conditions. config MAX31760_FAN_CONTROLLER tristate "MAX31760 Fan Controller Driver" depends on THERMAL_OF && QTI_THERMAL && I2C_GPIO help This enables the MAX31760 fan controller cooling device. This driver uses i2c bus to control registers for setting different fan speed. Also, this driver initializes the power for the fan controller. drivers/thermal/qcom/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -24,3 +24,4 @@ obj-$(CONFIG_REGULATOR_COOLING_DEVICE) += regulator_cdev.o obj-$(CONFIG_QTI_RPM_SMD_COOLING_DEVICE) += rpm_smd_cooling_device.o obj-$(CONFIG_QTI_LIMITS_ISENSE_CDSP) += msm_isense_cdsp.o obj-$(CONFIG_QTI_DDR_COOLING_DEVICE) += ddr_cdev.o obj-$(CONFIG_MAX31760_FAN_CONTROLLER) += max31760_fan.o drivers/thermal/qcom/max31760_fan.c 0 → 100644 +361 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2021, The Linux Foundation. All rights reserved. */ #include <linux/delay.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/of_gpio.h> #include <linux/regulator/consumer.h> #include <linux/thermal.h> #define MAX31760_CTRL_REG1 0x00 #define MAX31760_CTRL_REG2 0x01 #define MAX31760_CTRL_REG3 0x02 #define MAX31760_DUTY_CYCLE_CTRL_REG 0x50 #define VDD_MAX_UV 3100000 #define VDD_MIN_UV 3000000 #define VDD_LOAD_UA 300000 #define VCCA_MAX_UV 1800000 #define VCCA_MIN_UV 1800000 #define VCCA_LOAD_UA 600000 #define FAN_SPEED_LEVEL0 0 #define FAN_SPEED_LEVEL4 4 #define FAN_SPEED_MAX 5 struct max31760_data { struct device *dev; struct i2c_client *i2c_client; struct thermal_cooling_device *cdev; struct mutex update_lock; struct regulator *vdd_reg; struct regulator *vcca_reg; u32 max31760_en_gpio; unsigned int cur_state; atomic_t in_suspend; }; static int max31760_speed_map[FAN_SPEED_MAX] = {0x00, 0x30, 0x85, 0xCF, 0xFF}; static int max31760_write_byte(struct max31760_data *pdata, u8 reg, u8 val) { int ret = 0; struct i2c_client *client = pdata->i2c_client; ret = i2c_smbus_write_byte_data(client, reg, val); if (ret < 0) { dev_err(pdata->dev, "failed write reg %#x failure, ret:%d\n", reg, ret); return ret; } dev_dbg(pdata->dev, "successfully write reg %#x=%#x\n", reg, val); return 0; } static void max31760_enable_gpio(struct max31760_data *pdata, int on) { gpio_direction_output(pdata->max31760_en_gpio, on); dev_dbg(pdata->dev, "gpio:%d set to %d\n", pdata->max31760_en_gpio, on); usleep_range(20000, 20100); } static void max31760_speed_control(struct max31760_data *pdata, unsigned long level) { max31760_write_byte(pdata, MAX31760_DUTY_CYCLE_CTRL_REG, max31760_speed_map[level]); } static void max31760_set_cur_state_common(struct max31760_data *pdata, unsigned long state) { if (state > FAN_SPEED_LEVEL4) state = FAN_SPEED_LEVEL4; if (state < FAN_SPEED_LEVEL0) state = FAN_SPEED_LEVEL0; if (!atomic_read(&pdata->in_suspend)) max31760_speed_control(pdata, state); pdata->cur_state = state; } static int max31760_get_max_state(struct thermal_cooling_device *cdev, unsigned long *state) { *state = FAN_SPEED_LEVEL4; return 0; } static int max31760_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *state) { struct max31760_data *data = cdev->devdata; mutex_lock(&data->update_lock); *state = data->cur_state; mutex_unlock(&data->update_lock); return 0; } static int max31760_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) { struct max31760_data *data = cdev->devdata; mutex_lock(&data->update_lock); max31760_set_cur_state_common(data, state); mutex_unlock(&data->update_lock); return 0; } static struct thermal_cooling_device_ops max31760_cooling_ops = { .get_max_state = max31760_get_max_state, .get_cur_state = max31760_get_cur_state, .set_cur_state = max31760_set_cur_state, }; static int max31760_register_cdev(struct max31760_data *pdata) { int ret = 0; char cdev_name[THERMAL_NAME_LENGTH] = ""; snprintf(cdev_name, THERMAL_NAME_LENGTH, "fan-max31760"); pdata->cdev = thermal_of_cooling_device_register(pdata->dev->of_node, cdev_name, pdata, &max31760_cooling_ops); if (IS_ERR(pdata->cdev)) { ret = PTR_ERR(pdata->cdev); dev_err(pdata->dev, "Cooling register failed for %s, ret:%d\n", cdev_name, ret); pdata->cdev = NULL; return ret; } dev_dbg(pdata->dev, "Cooling register success for %s\n", cdev_name); return 0; } static void max31760_hw_init(struct max31760_data *pdata) { max31760_write_byte(pdata, MAX31760_CTRL_REG1, 0x19); max31760_write_byte(pdata, MAX31760_CTRL_REG2, 0x11); max31760_write_byte(pdata, MAX31760_CTRL_REG3, 0x31); mutex_lock(&pdata->update_lock); max31760_speed_control(pdata, FAN_SPEED_LEVEL0); pdata->cur_state = FAN_SPEED_LEVEL0; mutex_unlock(&pdata->update_lock); atomic_set(&pdata->in_suspend, 0); } static int max31760_parse_dt(struct max31760_data *pdata) { int ret = 0; struct device_node *node = pdata->dev->of_node; if (!node) { pr_err("device tree info missing\n"); return -EINVAL; } pdata->max31760_en_gpio = of_get_named_gpio(node, "maxim,fan_en_gpio", 0); if (!gpio_is_valid(pdata->max31760_en_gpio)) { dev_err(pdata->dev, "max31760 enable gpio not specified\n"); return -EINVAL; } ret = gpio_request(pdata->max31760_en_gpio, "max31760_en_gpio"); if (ret) { pr_err("max31760 enable gpio request failed, ret:%d\n", ret); goto error; } max31760_enable_gpio(pdata, 1); return ret; error: gpio_free(pdata->max31760_en_gpio); return ret; } static int max31760_enable_vregs(struct max31760_data *pdata) { int ret = 0; pdata->vdd_reg = devm_regulator_get(pdata->dev, "maxim,vdd"); if (IS_ERR(pdata->vdd_reg)) { ret = PTR_ERR(pdata->vdd_reg); dev_err(pdata->dev, "couldn't get vdd_reg regulator, ret:%d\n", ret); pdata->vdd_reg = NULL; return ret; } regulator_set_voltage(pdata->vdd_reg, VDD_MIN_UV, VDD_MAX_UV); regulator_set_load(pdata->vdd_reg, VDD_LOAD_UA); ret = regulator_enable(pdata->vdd_reg); if (ret < 0) { dev_err(pdata->dev, "vdd_reg regulator failed, ret:%d\n", ret); regulator_set_voltage(pdata->vdd_reg, 0, VDD_MAX_UV); regulator_set_load(pdata->vdd_reg, 0); return -EINVAL; } pdata->vcca_reg = devm_regulator_get(pdata->dev, "maxim,vcca"); if (IS_ERR(pdata->vcca_reg)) { ret = PTR_ERR(pdata->vcca_reg); dev_err(pdata->dev, "couldn't get vcca_reg regulator, ret:%d\n", ret); pdata->vcca_reg = NULL; return ret; } regulator_set_voltage(pdata->vcca_reg, VCCA_MIN_UV, VCCA_MAX_UV); regulator_set_load(pdata->vcca_reg, VCCA_LOAD_UA); ret = regulator_enable(pdata->vcca_reg); if (ret < 0) { dev_err(pdata->dev, "vcca_reg regulator failed, ret:%d\n", ret); regulator_set_voltage(pdata->vcca_reg, 0, VCCA_MAX_UV); regulator_set_load(pdata->vcca_reg, 0); return -EINVAL; } return 0; } static int max31760_remove(struct i2c_client *client) { struct max31760_data *pdata = i2c_get_clientdata(client); if (!pdata) return 0; thermal_cooling_device_unregister(pdata->cdev); regulator_disable(pdata->vdd_reg); regulator_disable(pdata->vcca_reg); max31760_enable_gpio(pdata, 0); gpio_free(pdata->max31760_en_gpio); return 0; } static int max31760_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = 0; struct max31760_data *pdata; if (!client || !client->dev.of_node) { pr_err("max31760 invalid input\n"); return -EINVAL; } if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "device doesn't support I2C\n"); return -ENODEV; } pdata = devm_kzalloc(&client->dev, sizeof(struct max31760_data), GFP_KERNEL); if (!pdata) return -ENOMEM; pdata->dev = &client->dev; pdata->i2c_client = client; i2c_set_clientdata(client, pdata); dev_set_drvdata(&client->dev, pdata); mutex_init(&pdata->update_lock); ret = max31760_parse_dt(pdata); if (ret) { dev_err(pdata->dev, "failed to parse device tree, ret:%d\n", ret); goto fail_parse_dt; } ret = max31760_enable_vregs(pdata); if (ret) { dev_err(pdata->dev, "failed to enable regulators, ret:%d\n", ret); goto fail_enable_vregs; } max31760_hw_init(pdata); ret = max31760_register_cdev(pdata); if (ret) { dev_err(pdata->dev, "failed to register cooling device, ret:%d\n", ret); goto fail_register_cdev; } return ret; fail_register_cdev: max31760_remove(client); return ret; fail_enable_vregs: max31760_enable_gpio(pdata, 0); gpio_free(pdata->max31760_en_gpio); fail_parse_dt: i2c_set_clientdata(client, NULL); dev_set_drvdata(&client->dev, NULL); return ret; } static void max31760_shutdown(struct i2c_client *client) { max31760_remove(client); } static int max31760_suspend(struct device *dev, pm_message_t state) { struct max31760_data *pdata = dev_get_drvdata(dev); dev_dbg(dev, "enter suspend now\n"); if (pdata) { atomic_set(&pdata->in_suspend, 1); mutex_lock(&pdata->update_lock); max31760_speed_control(pdata, FAN_SPEED_LEVEL0); mutex_unlock(&pdata->update_lock); } return 0; } static int max31760_resume(struct device *dev) { struct max31760_data *pdata = dev_get_drvdata(dev); dev_dbg(dev, "enter resume now\n"); if (pdata) { atomic_set(&pdata->in_suspend, 0); mutex_lock(&pdata->update_lock); max31760_set_cur_state_common(pdata, pdata->cur_state); mutex_unlock(&pdata->update_lock); } return 0; } static const struct of_device_id max31760_id_table[] = { { .compatible = "maxim,max31760",}, { }, }; static const struct i2c_device_id max31760_i2c_table[] = { { "max31760", 0 }, { }, }; static struct i2c_driver max31760_i2c_driver = { .probe = max31760_probe, .remove = max31760_remove, .shutdown = max31760_shutdown, .driver = { .name = "max31760", .of_match_table = max31760_id_table, .suspend = max31760_suspend, .resume = max31760_resume, }, .id_table = max31760_i2c_table, }; module_i2c_driver(max31760_i2c_driver); MODULE_DEVICE_TABLE(i2c, max31760_i2c_table); MODULE_DESCRIPTION("Maxim 31760 Fan Controller"); MODULE_LICENSE("GPL v2"); Loading
arch/arm64/configs/vendor/lahaina_QGKI.config +2 −0 Original line number Diff line number Diff line Loading @@ -258,3 +258,5 @@ CONFIG_SRAM=y CONFIG_CRYPTO_SHA1_ARM64_CE=y CONFIG_PRINT_SUSPEND_EPOCH_QGKI=y CONFIG_SM_DEBUGCC_YUPIK=y CONFIG_MAX31760_FAN_CONTROLLER=y CONFIG_I2C_GPIO=y
drivers/thermal/qcom/Kconfig +9 −0 Original line number Diff line number Diff line Loading @@ -163,3 +163,12 @@ config QTI_DDR_COOLING_DEVICE devices will be used by QTI chipset to place a DDR state request to meet the performance requirement under thermally constrained conditions. config MAX31760_FAN_CONTROLLER tristate "MAX31760 Fan Controller Driver" depends on THERMAL_OF && QTI_THERMAL && I2C_GPIO help This enables the MAX31760 fan controller cooling device. This driver uses i2c bus to control registers for setting different fan speed. Also, this driver initializes the power for the fan controller.
drivers/thermal/qcom/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -24,3 +24,4 @@ obj-$(CONFIG_REGULATOR_COOLING_DEVICE) += regulator_cdev.o obj-$(CONFIG_QTI_RPM_SMD_COOLING_DEVICE) += rpm_smd_cooling_device.o obj-$(CONFIG_QTI_LIMITS_ISENSE_CDSP) += msm_isense_cdsp.o obj-$(CONFIG_QTI_DDR_COOLING_DEVICE) += ddr_cdev.o obj-$(CONFIG_MAX31760_FAN_CONTROLLER) += max31760_fan.o
drivers/thermal/qcom/max31760_fan.c 0 → 100644 +361 −0 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2021, The Linux Foundation. All rights reserved. */ #include <linux/delay.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/of_gpio.h> #include <linux/regulator/consumer.h> #include <linux/thermal.h> #define MAX31760_CTRL_REG1 0x00 #define MAX31760_CTRL_REG2 0x01 #define MAX31760_CTRL_REG3 0x02 #define MAX31760_DUTY_CYCLE_CTRL_REG 0x50 #define VDD_MAX_UV 3100000 #define VDD_MIN_UV 3000000 #define VDD_LOAD_UA 300000 #define VCCA_MAX_UV 1800000 #define VCCA_MIN_UV 1800000 #define VCCA_LOAD_UA 600000 #define FAN_SPEED_LEVEL0 0 #define FAN_SPEED_LEVEL4 4 #define FAN_SPEED_MAX 5 struct max31760_data { struct device *dev; struct i2c_client *i2c_client; struct thermal_cooling_device *cdev; struct mutex update_lock; struct regulator *vdd_reg; struct regulator *vcca_reg; u32 max31760_en_gpio; unsigned int cur_state; atomic_t in_suspend; }; static int max31760_speed_map[FAN_SPEED_MAX] = {0x00, 0x30, 0x85, 0xCF, 0xFF}; static int max31760_write_byte(struct max31760_data *pdata, u8 reg, u8 val) { int ret = 0; struct i2c_client *client = pdata->i2c_client; ret = i2c_smbus_write_byte_data(client, reg, val); if (ret < 0) { dev_err(pdata->dev, "failed write reg %#x failure, ret:%d\n", reg, ret); return ret; } dev_dbg(pdata->dev, "successfully write reg %#x=%#x\n", reg, val); return 0; } static void max31760_enable_gpio(struct max31760_data *pdata, int on) { gpio_direction_output(pdata->max31760_en_gpio, on); dev_dbg(pdata->dev, "gpio:%d set to %d\n", pdata->max31760_en_gpio, on); usleep_range(20000, 20100); } static void max31760_speed_control(struct max31760_data *pdata, unsigned long level) { max31760_write_byte(pdata, MAX31760_DUTY_CYCLE_CTRL_REG, max31760_speed_map[level]); } static void max31760_set_cur_state_common(struct max31760_data *pdata, unsigned long state) { if (state > FAN_SPEED_LEVEL4) state = FAN_SPEED_LEVEL4; if (state < FAN_SPEED_LEVEL0) state = FAN_SPEED_LEVEL0; if (!atomic_read(&pdata->in_suspend)) max31760_speed_control(pdata, state); pdata->cur_state = state; } static int max31760_get_max_state(struct thermal_cooling_device *cdev, unsigned long *state) { *state = FAN_SPEED_LEVEL4; return 0; } static int max31760_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *state) { struct max31760_data *data = cdev->devdata; mutex_lock(&data->update_lock); *state = data->cur_state; mutex_unlock(&data->update_lock); return 0; } static int max31760_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) { struct max31760_data *data = cdev->devdata; mutex_lock(&data->update_lock); max31760_set_cur_state_common(data, state); mutex_unlock(&data->update_lock); return 0; } static struct thermal_cooling_device_ops max31760_cooling_ops = { .get_max_state = max31760_get_max_state, .get_cur_state = max31760_get_cur_state, .set_cur_state = max31760_set_cur_state, }; static int max31760_register_cdev(struct max31760_data *pdata) { int ret = 0; char cdev_name[THERMAL_NAME_LENGTH] = ""; snprintf(cdev_name, THERMAL_NAME_LENGTH, "fan-max31760"); pdata->cdev = thermal_of_cooling_device_register(pdata->dev->of_node, cdev_name, pdata, &max31760_cooling_ops); if (IS_ERR(pdata->cdev)) { ret = PTR_ERR(pdata->cdev); dev_err(pdata->dev, "Cooling register failed for %s, ret:%d\n", cdev_name, ret); pdata->cdev = NULL; return ret; } dev_dbg(pdata->dev, "Cooling register success for %s\n", cdev_name); return 0; } static void max31760_hw_init(struct max31760_data *pdata) { max31760_write_byte(pdata, MAX31760_CTRL_REG1, 0x19); max31760_write_byte(pdata, MAX31760_CTRL_REG2, 0x11); max31760_write_byte(pdata, MAX31760_CTRL_REG3, 0x31); mutex_lock(&pdata->update_lock); max31760_speed_control(pdata, FAN_SPEED_LEVEL0); pdata->cur_state = FAN_SPEED_LEVEL0; mutex_unlock(&pdata->update_lock); atomic_set(&pdata->in_suspend, 0); } static int max31760_parse_dt(struct max31760_data *pdata) { int ret = 0; struct device_node *node = pdata->dev->of_node; if (!node) { pr_err("device tree info missing\n"); return -EINVAL; } pdata->max31760_en_gpio = of_get_named_gpio(node, "maxim,fan_en_gpio", 0); if (!gpio_is_valid(pdata->max31760_en_gpio)) { dev_err(pdata->dev, "max31760 enable gpio not specified\n"); return -EINVAL; } ret = gpio_request(pdata->max31760_en_gpio, "max31760_en_gpio"); if (ret) { pr_err("max31760 enable gpio request failed, ret:%d\n", ret); goto error; } max31760_enable_gpio(pdata, 1); return ret; error: gpio_free(pdata->max31760_en_gpio); return ret; } static int max31760_enable_vregs(struct max31760_data *pdata) { int ret = 0; pdata->vdd_reg = devm_regulator_get(pdata->dev, "maxim,vdd"); if (IS_ERR(pdata->vdd_reg)) { ret = PTR_ERR(pdata->vdd_reg); dev_err(pdata->dev, "couldn't get vdd_reg regulator, ret:%d\n", ret); pdata->vdd_reg = NULL; return ret; } regulator_set_voltage(pdata->vdd_reg, VDD_MIN_UV, VDD_MAX_UV); regulator_set_load(pdata->vdd_reg, VDD_LOAD_UA); ret = regulator_enable(pdata->vdd_reg); if (ret < 0) { dev_err(pdata->dev, "vdd_reg regulator failed, ret:%d\n", ret); regulator_set_voltage(pdata->vdd_reg, 0, VDD_MAX_UV); regulator_set_load(pdata->vdd_reg, 0); return -EINVAL; } pdata->vcca_reg = devm_regulator_get(pdata->dev, "maxim,vcca"); if (IS_ERR(pdata->vcca_reg)) { ret = PTR_ERR(pdata->vcca_reg); dev_err(pdata->dev, "couldn't get vcca_reg regulator, ret:%d\n", ret); pdata->vcca_reg = NULL; return ret; } regulator_set_voltage(pdata->vcca_reg, VCCA_MIN_UV, VCCA_MAX_UV); regulator_set_load(pdata->vcca_reg, VCCA_LOAD_UA); ret = regulator_enable(pdata->vcca_reg); if (ret < 0) { dev_err(pdata->dev, "vcca_reg regulator failed, ret:%d\n", ret); regulator_set_voltage(pdata->vcca_reg, 0, VCCA_MAX_UV); regulator_set_load(pdata->vcca_reg, 0); return -EINVAL; } return 0; } static int max31760_remove(struct i2c_client *client) { struct max31760_data *pdata = i2c_get_clientdata(client); if (!pdata) return 0; thermal_cooling_device_unregister(pdata->cdev); regulator_disable(pdata->vdd_reg); regulator_disable(pdata->vcca_reg); max31760_enable_gpio(pdata, 0); gpio_free(pdata->max31760_en_gpio); return 0; } static int max31760_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret = 0; struct max31760_data *pdata; if (!client || !client->dev.of_node) { pr_err("max31760 invalid input\n"); return -EINVAL; } if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "device doesn't support I2C\n"); return -ENODEV; } pdata = devm_kzalloc(&client->dev, sizeof(struct max31760_data), GFP_KERNEL); if (!pdata) return -ENOMEM; pdata->dev = &client->dev; pdata->i2c_client = client; i2c_set_clientdata(client, pdata); dev_set_drvdata(&client->dev, pdata); mutex_init(&pdata->update_lock); ret = max31760_parse_dt(pdata); if (ret) { dev_err(pdata->dev, "failed to parse device tree, ret:%d\n", ret); goto fail_parse_dt; } ret = max31760_enable_vregs(pdata); if (ret) { dev_err(pdata->dev, "failed to enable regulators, ret:%d\n", ret); goto fail_enable_vregs; } max31760_hw_init(pdata); ret = max31760_register_cdev(pdata); if (ret) { dev_err(pdata->dev, "failed to register cooling device, ret:%d\n", ret); goto fail_register_cdev; } return ret; fail_register_cdev: max31760_remove(client); return ret; fail_enable_vregs: max31760_enable_gpio(pdata, 0); gpio_free(pdata->max31760_en_gpio); fail_parse_dt: i2c_set_clientdata(client, NULL); dev_set_drvdata(&client->dev, NULL); return ret; } static void max31760_shutdown(struct i2c_client *client) { max31760_remove(client); } static int max31760_suspend(struct device *dev, pm_message_t state) { struct max31760_data *pdata = dev_get_drvdata(dev); dev_dbg(dev, "enter suspend now\n"); if (pdata) { atomic_set(&pdata->in_suspend, 1); mutex_lock(&pdata->update_lock); max31760_speed_control(pdata, FAN_SPEED_LEVEL0); mutex_unlock(&pdata->update_lock); } return 0; } static int max31760_resume(struct device *dev) { struct max31760_data *pdata = dev_get_drvdata(dev); dev_dbg(dev, "enter resume now\n"); if (pdata) { atomic_set(&pdata->in_suspend, 0); mutex_lock(&pdata->update_lock); max31760_set_cur_state_common(pdata, pdata->cur_state); mutex_unlock(&pdata->update_lock); } return 0; } static const struct of_device_id max31760_id_table[] = { { .compatible = "maxim,max31760",}, { }, }; static const struct i2c_device_id max31760_i2c_table[] = { { "max31760", 0 }, { }, }; static struct i2c_driver max31760_i2c_driver = { .probe = max31760_probe, .remove = max31760_remove, .shutdown = max31760_shutdown, .driver = { .name = "max31760", .of_match_table = max31760_id_table, .suspend = max31760_suspend, .resume = max31760_resume, }, .id_table = max31760_i2c_table, }; module_i2c_driver(max31760_i2c_driver); MODULE_DEVICE_TABLE(i2c, max31760_i2c_table); MODULE_DESCRIPTION("Maxim 31760 Fan Controller"); MODULE_LICENSE("GPL v2");