📄 adm1026.c
字号:
}static ssize_t show_auto_pwm_min(struct device *dev, char *buf){ struct adm1026_data *data = adm1026_update_device(dev); return sprintf(buf,"%d\n", data->pwm1.auto_pwm_min);}static ssize_t set_auto_pwm_min(struct device *dev, const char *buf, size_t count){ struct i2c_client *client = to_i2c_client(dev); struct adm1026_data *data = i2c_get_clientdata(client); int val; down(&data->update_lock); val = simple_strtol(buf, NULL, 10); data->pwm1.auto_pwm_min = SENSORS_LIMIT(val,0,255); if (data->pwm1.enable == 2) { /* apply immediately */ data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); } up(&data->update_lock); return count;}static ssize_t show_auto_pwm_max(struct device *dev, char *buf){ return sprintf(buf,"%d\n", ADM1026_PWM_MAX);}static ssize_t show_pwm_enable(struct device *dev, char *buf){ struct adm1026_data *data = adm1026_update_device(dev); return sprintf(buf,"%d\n", data->pwm1.enable);}static ssize_t set_pwm_enable(struct device *dev, const char *buf, size_t count){ struct i2c_client *client = to_i2c_client(dev); struct adm1026_data *data = i2c_get_clientdata(client); int val; int old_enable; val = simple_strtol(buf, NULL, 10); if ((val >= 0) && (val < 3)) { down(&data->update_lock); old_enable = data->pwm1.enable; data->pwm1.enable = val; data->config1 = (data->config1 & ~CFG1_PWM_AFC) | ((val == 2) ? CFG1_PWM_AFC : 0); adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1); if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */ data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); } else if (!((old_enable == 1) && (val == 1))) { /* set pwm to safe value */ data->pwm1.pwm = 255; adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); } up(&data->update_lock); } return count;}/* enable PWM fan control */static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); static DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); static DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable);static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable);static DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable, set_pwm_enable);static DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO | S_IWUSR, show_auto_pwm_min, set_auto_pwm_min);static DEVICE_ATTR(temp2_auto_point1_pwm, S_IRUGO | S_IWUSR, show_auto_pwm_min, set_auto_pwm_min);static DEVICE_ATTR(temp3_auto_point1_pwm, S_IRUGO | S_IWUSR, show_auto_pwm_min, set_auto_pwm_min);static DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);static DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);static DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL);int adm1026_detect(struct i2c_adapter *adapter, int address, int kind){ int company, verstep; struct i2c_client *new_client; struct adm1026_data *data; int err = 0; const char *type_name = ""; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { /* We need to be able to do byte I/O */ goto exit; }; /* OK. For now, we presume we have a valid client. We now create the client structure, even though we cannot fill it completely yet. But it allows us to access adm1026_{read,write}_value. */ if (!(data = kmalloc(sizeof(struct adm1026_data), GFP_KERNEL))) { err = -ENOMEM; goto exit; } memset(data, 0, sizeof(struct adm1026_data)); new_client = &data->client; i2c_set_clientdata(new_client, data); new_client->addr = address; new_client->adapter = adapter; new_client->driver = &adm1026_driver; new_client->flags = 0; /* Now, we do the remaining detection. */ company = adm1026_read_value(new_client, ADM1026_REG_COMPANY); verstep = adm1026_read_value(new_client, ADM1026_REG_VERSTEP); dev_dbg(&new_client->dev, "Detecting device at %d,0x%02x with" " COMPANY: 0x%02x and VERSTEP: 0x%02x\n", i2c_adapter_id(new_client->adapter), new_client->addr, company, verstep); /* If auto-detecting, Determine the chip type. */ if (kind <= 0) { dev_dbg(&new_client->dev, "Autodetecting device at %d,0x%02x " "...\n", i2c_adapter_id(adapter), address); if (company == ADM1026_COMPANY_ANALOG_DEV && verstep == ADM1026_VERSTEP_ADM1026) { kind = adm1026; } else if (company == ADM1026_COMPANY_ANALOG_DEV && (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) { dev_err(&adapter->dev, ": Unrecognized stepping " "0x%02x. Defaulting to ADM1026.\n", verstep); kind = adm1026; } else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) { dev_err(&adapter->dev, ": Found version/stepping " "0x%02x. Assuming generic ADM1026.\n", verstep); kind = any_chip; } else { dev_dbg(&new_client->dev, ": Autodetection " "failed\n"); /* Not an ADM1026 ... */ if (kind == 0) { /* User used force=x,y */ dev_err(&adapter->dev, "Generic ADM1026 not " "found at %d,0x%02x. Try " "force_adm1026.\n", i2c_adapter_id(adapter), address); } err = 0; goto exitfree; } } /* Fill in the chip specific driver values */ switch (kind) { case any_chip : type_name = "adm1026"; break; case adm1026 : type_name = "adm1026"; break; default : dev_err(&adapter->dev, ": Internal error, invalid " "kind (%d)!", kind); err = -EFAULT; goto exitfree; } strlcpy(new_client->name, type_name, I2C_NAME_SIZE); /* Fill in the remaining client fields */ new_client->id = adm1026_id++; data->type = kind; data->valid = 0; init_MUTEX(&data->update_lock); dev_dbg(&new_client->dev, "(%d): Assigning ID %d to %s at %d,0x%02x\n", new_client->id, new_client->id, new_client->name, i2c_adapter_id(new_client->adapter), new_client->addr); /* Tell the I2C layer a new client has arrived */ if ((err = i2c_attach_client(new_client))) goto exitfree; /* Set the VRM version */ data->vrm = i2c_which_vrm(); /* Initialize the ADM1026 chip */ adm1026_init_client(new_client); /* Register sysfs hooks */ device_create_file(&new_client->dev, &dev_attr_in0_input); device_create_file(&new_client->dev, &dev_attr_in0_max); device_create_file(&new_client->dev, &dev_attr_in0_min); device_create_file(&new_client->dev, &dev_attr_in1_input); device_create_file(&new_client->dev, &dev_attr_in1_max); device_create_file(&new_client->dev, &dev_attr_in1_min); device_create_file(&new_client->dev, &dev_attr_in2_input); device_create_file(&new_client->dev, &dev_attr_in2_max); device_create_file(&new_client->dev, &dev_attr_in2_min); device_create_file(&new_client->dev, &dev_attr_in3_input); device_create_file(&new_client->dev, &dev_attr_in3_max); device_create_file(&new_client->dev, &dev_attr_in3_min); device_create_file(&new_client->dev, &dev_attr_in4_input); device_create_file(&new_client->dev, &dev_attr_in4_max); device_create_file(&new_client->dev, &dev_attr_in4_min); device_create_file(&new_client->dev, &dev_attr_in5_input); device_create_file(&new_client->dev, &dev_attr_in5_max); device_create_file(&new_client->dev, &dev_attr_in5_min); device_create_file(&new_client->dev, &dev_attr_in6_input); device_create_file(&new_client->dev, &dev_attr_in6_max); device_create_file(&new_client->dev, &dev_attr_in6_min); device_create_file(&new_client->dev, &dev_attr_in7_input); device_create_file(&new_client->dev, &dev_attr_in7_max); device_create_file(&new_client->dev, &dev_attr_in7_min); device_create_file(&new_client->dev, &dev_attr_in8_input); device_create_file(&new_client->dev, &dev_attr_in8_max); device_create_file(&new_client->dev, &dev_attr_in8_min); device_create_file(&new_client->dev, &dev_attr_in9_input); device_create_file(&new_client->dev, &dev_attr_in9_max); device_create_file(&new_client->dev, &dev_attr_in9_min); device_create_file(&new_client->dev, &dev_attr_in10_input); device_create_file(&new_client->dev, &dev_attr_in10_max); device_create_file(&new_client->dev, &dev_attr_in10_min); device_create_file(&new_client->dev, &dev_attr_in11_input); device_create_file(&new_client->dev, &dev_attr_in11_max); device_create_file(&new_client->dev, &dev_attr_in11_min); device_create_file(&new_client->dev, &dev_attr_in12_input); device_create_file(&new_client->dev, &dev_attr_in12_max); device_create_file(&new_client->dev, &dev_attr_in12_min); device_create_file(&new_client->dev, &dev_attr_in13_input); device_create_file(&new_client->dev, &dev_attr_in13_max); device_create_file(&new_client->dev, &dev_attr_in13_min); device_create_file(&new_client->dev, &dev_attr_in14_input); device_create_file(&new_client->dev, &dev_attr_in14_max); device_create_file(&new_client->dev, &dev_attr_in14_min); device_create_file(&new_client->dev, &dev_attr_in15_input); device_create_file(&new_client->dev, &dev_attr_in15_max); device_create_file(&new_client->dev, &dev_attr_in15_min); device_create_file(&new_client->dev, &dev_attr_in16_input); device_create_file(&new_client->dev, &dev_attr_in16_max); device_create_file(&new_client->dev, &dev_attr_in16_min); device_create_file(&new_client->dev, &dev_attr_fan1_input); device_create_file(&new_client->dev, &dev_attr_fan1_div); device_create_file(&new_client->dev, &dev_attr_fan1_min); device_create_file(&new_client->dev, &dev_attr_fan2_input); device_create_file(&new_client->dev, &dev_attr_fan2_div); device_create_file(&new_client->dev, &dev_attr_fan2_min); device_create_file(&new_client->dev, &dev_attr_fan3_input); device_create_file(&new_client->dev, &dev_attr_fan3_div); device_create_file(&new_client->dev, &dev_attr_fan3_min); device_create_file(&new_client->dev, &dev_attr_fan4_input); device_create_file(&new_client->dev, &dev_attr_fan4_div); device_create_file(&new_client->dev, &dev_attr_fan4_min); device_create_file(&new_client->dev, &dev_attr_fan5_input); device_create_file(&new_client->dev, &dev_attr_fan5_div); device_create_file(&new_client->dev, &dev_attr_fan5_min); device_create_file(&new_client->dev, &dev_attr_fan6_input); device_create_file(&new_client->dev, &dev_attr_fan6_div); device_create_file(&new_client->dev, &dev_attr_fan6_min); device_create_file(&new_client->dev, &dev_attr_fan7_input); device_create_file(&new_client->dev, &dev_attr_fan7_div); device_create_file(&new_client->dev, &dev_attr_fan7_min); device_create_file(&new_client->dev, &dev_attr_fan8_input); device_create_file(&new_client->dev, &dev_attr_fan8_div); device_create_file(&new_client->dev, &dev_attr_fan8_min); device_create_file(&new_client->dev, &dev_attr_temp1_input); device_create_file(&new_client->dev, &dev_attr_temp1_max); device_create_file(&new_client->dev, &dev_attr_temp1_min); device_create_file(&new_client->dev, &dev_attr_temp2_input); device_create_file(&new_client->dev, &dev_attr_temp2_max); device_create_file(&new_client->dev, &dev_attr_temp2_min); device_create_file(&new_client->dev, &dev_attr_temp3_input); device_create_file(&new_client->dev, &dev_attr_temp3_max); device_create_file(&new_client->dev, &dev_attr_temp3_min); device_create_file(&new_client->dev, &dev_attr_temp1_offset); device_create_file(&new_client->dev, &dev_attr_temp2_offset); device_create_file(&new_client->dev, &dev_attr_temp3_offset); device_create_file(&new_client->dev, &dev_attr_temp1_auto_point1_temp); device_create_file(&new_client->dev, &dev_attr_temp2_auto_point1_temp); device_create_file(&new_client->dev, &dev_attr_temp3_auto_point1_temp); device_create_file(&new_client->dev, &dev_attr_temp1_auto_point1_temp_hyst); device_create_file(&new_client->dev, &dev_attr_temp2_auto_point1_temp_hyst); device_create_file(&new_client->dev, &dev_attr_temp3_auto_point1_temp_hyst); device_create_file(&new_client->dev, &dev_attr_temp1_auto_point2_temp); device_create_file(&new_client->dev, &dev_attr_temp2_auto_point2_temp); device_create_file(&new_client->dev, &dev_attr_temp3_auto_point2_temp); device_create_file(&new_client->dev, &dev_attr_temp1_crit); device_create_file(&new_client->dev, &dev_attr_temp2_crit); device_create_file(&new_client->dev, &dev_attr_temp3_crit); device_create_file(&new_client->dev, &dev_attr_temp1_crit_enable); device_create_file(&new_client->dev, &dev_attr_temp2_crit_enable); device_create_file(&new_client->dev, &dev_attr_temp3_crit_enable); device_create_file(&new_client->dev, &dev_attr_vid); device_create_file(&new_client->dev, &dev_attr_vrm); device_create_file(&new_client->dev, &dev_attr_alarms); device_create_file(&new_client->dev, &dev_attr_alarm_mask); device_create_file(&new_client->dev, &dev_attr_gpio); device_create_file(&new_client->dev, &dev_attr_gpio_mask); device_create_file(&new_client->dev, &dev_attr_pwm1); device_create_file(&new_client->dev, &dev_attr_pwm2); device_create_file(&new_client->dev, &dev_attr_pwm3); device_create_file(&new_client->dev, &dev_attr_pwm1_enable); device_create_file(&new_client->dev, &dev_attr_pwm2_enable); device_create_file(&new_client->dev, &dev_attr_pwm3_enable); device_create_file(&new_client->dev, &dev_attr_temp1_auto_point1_pwm); device_create_file(&new_client->dev, &dev_attr_temp2_auto_point1_pwm); device_create_file(&new_client->dev, &dev_attr_temp3_auto_point1_pwm); device_create_file(&new_client->dev, &dev_attr_temp1_auto_point2_pwm); device_create_file(&new_client->dev, &dev_attr_temp2_auto_point2_pwm); device_create_file(&new_client->dev, &dev_attr_temp3_auto_point2_pwm); device_create_file(&new_client->dev, &dev_attr_analog_out); return 0; /* Error out and cleanup code */exitfree: kfree(new_client);exit: return err;}static int __init sm_adm1026_init(void){ return i2c_add_driver(&adm1026_driver);}static void __exit sm_adm1026_exit(void){ i2c_del_driver(&adm1026_driver);}MODULE_LICENSE("GPL");MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, " "Justin Thiessen <jthiessen@penguincomputing.com>");MODULE_DESCRIPTION("ADM1026 driver");module_init(sm_adm1026_init);module_exit(sm_adm1026_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -