⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dme1737.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	return PWM_RR_FROM_REG(reg, ix) ? 1 : 0;}static inline int PWM_RR_EN_TO_REG(int val, int ix, int reg){	int en = (ix == 1) ? 0x80 : 0x08;	return val ? reg | en : reg & ~en;}/* PWM min/off * The PWM min/off bits are part of the PMW ramp rate register 0 (see above for * the register layout). */static inline int PWM_OFF_FROM_REG(int reg, int ix){	return (reg >> (ix + 5)) & 0x01;}static inline int PWM_OFF_TO_REG(int val, int ix, int reg){	return (reg & ~(1 << (ix + 5))) | ((val & 0x01) << (ix + 5));}/* --------------------------------------------------------------------- * Device I/O access * * ISA access is performed through an index/data register pair and needs to * be protected by a mutex during runtime (not required for initialization). * We use data->update_lock for this and need to ensure that we acquire it * before calling dme1737_read or dme1737_write. * --------------------------------------------------------------------- */static u8 dme1737_read(struct i2c_client *client, u8 reg){	s32 val;	if (client->driver) { /* I2C device */		val = i2c_smbus_read_byte_data(client, reg);		if (val < 0) {			dev_warn(&client->dev, "Read from register "				 "0x%02x failed! Please report to the driver "				 "maintainer.\n", reg);		}	} else { /* ISA device */		outb(reg, client->addr);		val = inb(client->addr + 1);	}	return val;}static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 val){	s32 res = 0;	if (client->driver) { /* I2C device */		res = i2c_smbus_write_byte_data(client, reg, val);		if (res < 0) {			dev_warn(&client->dev, "Write to register "				 "0x%02x failed! Please report to the driver "				 "maintainer.\n", reg);		}	} else { /* ISA device */		outb(reg, client->addr);		outb(val, client->addr + 1);	}	return res;}static struct dme1737_data *dme1737_update_device(struct device *dev){	struct dme1737_data *data = dev_get_drvdata(dev);	struct i2c_client *client = &data->client;	int ix;	u8 lsb[5];	mutex_lock(&data->update_lock);	/* Enable a Vbat monitoring cycle every 10 mins */	if (time_after(jiffies, data->last_vbat + 600 * HZ) || !data->valid) {		dme1737_write(client, DME1737_REG_CONFIG, dme1737_read(client,						DME1737_REG_CONFIG) | 0x10);		data->last_vbat = jiffies;	}	/* Sample register contents every 1 sec */	if (time_after(jiffies, data->last_update + HZ) || !data->valid) {		data->vid = dme1737_read(client, DME1737_REG_VID) & 0x3f;		/* In (voltage) registers */		for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) {			/* Voltage inputs are stored as 16 bit values even			 * though they have only 12 bits resolution. This is			 * to make it consistent with the temp inputs. */			data->in[ix] = dme1737_read(client,					DME1737_REG_IN(ix)) << 8;			data->in_min[ix] = dme1737_read(client,					DME1737_REG_IN_MIN(ix));			data->in_max[ix] = dme1737_read(client,					DME1737_REG_IN_MAX(ix));		}		/* Temp registers */		for (ix = 0; ix < ARRAY_SIZE(data->temp); ix++) {			/* Temp inputs are stored as 16 bit values even			 * though they have only 12 bits resolution. This is			 * to take advantage of implicit conversions between			 * register values (2's complement) and temp values			 * (signed decimal). */			data->temp[ix] = dme1737_read(client,					DME1737_REG_TEMP(ix)) << 8;			data->temp_min[ix] = dme1737_read(client,					DME1737_REG_TEMP_MIN(ix));			data->temp_max[ix] = dme1737_read(client,					DME1737_REG_TEMP_MAX(ix));			data->temp_offset[ix] = dme1737_read(client,					DME1737_REG_TEMP_OFFSET(ix));		}		/* In and temp LSB registers		 * The LSBs are latched when the MSBs are read, so the order in		 * which the registers are read (MSB first, then LSB) is		 * important! */		for (ix = 0; ix < ARRAY_SIZE(lsb); ix++) {			lsb[ix] = dme1737_read(client,					DME1737_REG_IN_TEMP_LSB(ix));		}		for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) {			data->in[ix] |= (lsb[DME1737_REG_IN_LSB[ix]] <<					DME1737_REG_IN_LSB_SHL[ix]) & 0xf0;		}		for (ix = 0; ix < ARRAY_SIZE(data->temp); ix++) {			data->temp[ix] |= (lsb[DME1737_REG_TEMP_LSB[ix]] <<					DME1737_REG_TEMP_LSB_SHL[ix]) & 0xf0;		}		/* Fan registers */		for (ix = 0; ix < ARRAY_SIZE(data->fan); ix++) {			/* Skip reading registers if optional fans are not			 * present */			if (!(data->has_fan & (1 << ix))) {				continue;			}			data->fan[ix] = dme1737_read(client,					DME1737_REG_FAN(ix));			data->fan[ix] |= dme1737_read(client,					DME1737_REG_FAN(ix) + 1) << 8;			data->fan_min[ix] = dme1737_read(client,					DME1737_REG_FAN_MIN(ix));			data->fan_min[ix] |= dme1737_read(client,					DME1737_REG_FAN_MIN(ix) + 1) << 8;			data->fan_opt[ix] = dme1737_read(client,					DME1737_REG_FAN_OPT(ix));			/* fan_max exists only for fan[5-6] */			if (ix > 3) {				data->fan_max[ix - 4] = dme1737_read(client,					DME1737_REG_FAN_MAX(ix));			}		}		/* PWM registers */		for (ix = 0; ix < ARRAY_SIZE(data->pwm); ix++) {			/* Skip reading registers if optional PWMs are not			 * present */			if (!(data->has_pwm & (1 << ix))) {				continue;			}			data->pwm[ix] = dme1737_read(client,					DME1737_REG_PWM(ix));			data->pwm_freq[ix] = dme1737_read(client,					DME1737_REG_PWM_FREQ(ix));			/* pwm_config and pwm_min exist only for pwm[1-3] */			if (ix < 3) {				data->pwm_config[ix] = dme1737_read(client,						DME1737_REG_PWM_CONFIG(ix));				data->pwm_min[ix] = dme1737_read(client,						DME1737_REG_PWM_MIN(ix));			}		}		for (ix = 0; ix < ARRAY_SIZE(data->pwm_rr); ix++) {			data->pwm_rr[ix] = dme1737_read(client,						DME1737_REG_PWM_RR(ix));		}		/* Thermal zone registers */		for (ix = 0; ix < ARRAY_SIZE(data->zone_low); ix++) {			data->zone_low[ix] = dme1737_read(client,					DME1737_REG_ZONE_LOW(ix));			data->zone_abs[ix] = dme1737_read(client,					DME1737_REG_ZONE_ABS(ix));		}		for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) {			data->zone_hyst[ix] = dme1737_read(client,						DME1737_REG_ZONE_HYST(ix));		}		/* Alarm registers */		data->alarms = dme1737_read(client,						DME1737_REG_ALARM1);		/* Bit 7 tells us if the other alarm registers are non-zero and		 * therefore also need to be read */		if (data->alarms & 0x80) {			data->alarms |= dme1737_read(client,						DME1737_REG_ALARM2) << 8;			data->alarms |= dme1737_read(client,						DME1737_REG_ALARM3) << 16;		}		/* The ISA chips require explicit clearing of alarm bits.		 * Don't worry, an alarm will come back if the condition		 * that causes it still exists */		if (!client->driver) {			if (data->alarms & 0xff0000) {				dme1737_write(client, DME1737_REG_ALARM3,					      0xff);			}			if (data->alarms & 0xff00) {				dme1737_write(client, DME1737_REG_ALARM2,					      0xff);			}			if (data->alarms & 0xff) {				dme1737_write(client, DME1737_REG_ALARM1,					      0xff);			}		}		data->last_update = jiffies;		data->valid = 1;	}	mutex_unlock(&data->update_lock);	return data;}/* --------------------------------------------------------------------- * Voltage sysfs attributes * ix = [0-5] * --------------------------------------------------------------------- */#define SYS_IN_INPUT	0#define SYS_IN_MIN	1#define SYS_IN_MAX	2#define SYS_IN_ALARM	3static ssize_t show_in(struct device *dev, struct device_attribute *attr,		       char *buf){	struct dme1737_data *data = dme1737_update_device(dev);	struct sensor_device_attribute_2		*sensor_attr_2 = to_sensor_dev_attr_2(attr);	int ix = sensor_attr_2->index;	int fn = sensor_attr_2->nr;	int res;	switch (fn) {	case SYS_IN_INPUT:		res = IN_FROM_REG(data->in[ix], ix, 16);		break;	case SYS_IN_MIN:		res = IN_FROM_REG(data->in_min[ix], ix, 8);		break;	case SYS_IN_MAX:		res = IN_FROM_REG(data->in_max[ix], ix, 8);		break;	case SYS_IN_ALARM:		res = (data->alarms >> DME1737_BIT_ALARM_IN[ix]) & 0x01;		break;	default:		res = 0;		dev_dbg(dev, "Unknown function %d.\n", fn);	}	return sprintf(buf, "%d\n", res);}static ssize_t set_in(struct device *dev, struct device_attribute *attr,		      const char *buf, size_t count){	struct dme1737_data *data = dev_get_drvdata(dev);	struct i2c_client *client = &data->client;	struct sensor_device_attribute_2		*sensor_attr_2 = to_sensor_dev_attr_2(attr);	int ix = sensor_attr_2->index;	int fn = sensor_attr_2->nr;	long val = simple_strtol(buf, NULL, 10);	mutex_lock(&data->update_lock);	switch (fn) {	case SYS_IN_MIN:		data->in_min[ix] = IN_TO_REG(val, ix);		dme1737_write(client, DME1737_REG_IN_MIN(ix),			      data->in_min[ix]);		break;	case SYS_IN_MAX:		data->in_max[ix] = IN_TO_REG(val, ix);		dme1737_write(client, DME1737_REG_IN_MAX(ix),			      data->in_max[ix]);		break;	default:		dev_dbg(dev, "Unknown function %d.\n", fn);	}	mutex_unlock(&data->update_lock);	return count;}/* --------------------------------------------------------------------- * Temperature sysfs attributes * ix = [0-2] * --------------------------------------------------------------------- */#define SYS_TEMP_INPUT			0#define SYS_TEMP_MIN			1#define SYS_TEMP_MAX			2#define SYS_TEMP_OFFSET			3#define SYS_TEMP_ALARM			4#define SYS_TEMP_FAULT			5static ssize_t show_temp(struct device *dev, struct device_attribute *attr,			 char *buf){	struct dme1737_data *data = dme1737_update_device(dev);	struct sensor_device_attribute_2		*sensor_attr_2 = to_sensor_dev_attr_2(attr);	int ix = sensor_attr_2->index;	int fn = sensor_attr_2->nr;	int res;	switch (fn) {	case SYS_TEMP_INPUT:		res = TEMP_FROM_REG(data->temp[ix], 16);		break;	case SYS_TEMP_MIN:		res = TEMP_FROM_REG(data->temp_min[ix], 8);		break;	case SYS_TEMP_MAX:		res = TEMP_FROM_REG(data->temp_max[ix], 8);		break;	case SYS_TEMP_OFFSET:		res = TEMP_FROM_REG(data->temp_offset[ix], 8);		break;	case SYS_TEMP_ALARM:		res = (data->alarms >> DME1737_BIT_ALARM_TEMP[ix]) & 0x01;		break;	case SYS_TEMP_FAULT:		res = (((u16)data->temp[ix] & 0xff00) == 0x8000);		break;	default:		res = 0;		dev_dbg(dev, "Unknown function %d.\n", fn);	}	return sprintf(buf, "%d\n", res);}static ssize_t set_temp(struct device *dev, struct device_attribute *attr,			const char *buf, size_t count){	struct dme1737_data *data = dev_get_drvdata(dev);	struct i2c_client *client = &data->client;	struct sensor_device_attribute_2		*sensor_attr_2 = to_sensor_dev_attr_2(attr);	int ix = sensor_attr_2->index;	int fn = sensor_attr_2->nr;	long val = simple_strtol(buf, NULL, 10);	mutex_lock(&data->update_lock);	switch (fn) {	case SYS_TEMP_MIN:		data->temp_min[ix] = TEMP_TO_REG(val);		dme1737_write(client, DME1737_REG_TEMP_MIN(ix),			      data->temp_min[ix]);		break;	case SYS_TEMP_MAX:		data->temp_max[ix] = TEMP_TO_REG(val);		dme1737_write(client, DME1737_REG_TEMP_MAX(ix),			      data->temp_max[ix]);		break;	case SYS_TEMP_OFFSET:		data->temp_offset[ix] = TEMP_TO_REG(val);		dme1737_write(client, DME1737_REG_TEMP_OFFSET(ix),			      data->temp_offset[ix]);		break;	default:		dev_dbg(dev, "Unknown function %d.\n", fn);	}	mutex_unlock(&data->update_lock);	return count;}/* --------------------------------------------------------------------- * Zone sysfs attributes * ix = [0-2] * --------------------------------------------------------------------- */#define SYS_ZONE_AUTO_CHANNELS_TEMP	0#define SYS_ZONE_AUTO_POINT1_TEMP_HYST	1#define SYS_ZONE_AUTO_POINT1_TEMP	2#define SYS_ZONE_AUTO_POINT2_TEMP	3#define SYS_ZONE_AUTO_POINT3_TEMP	4static ssize_t show_zone(struct device *dev, struct device_attribute *attr,			 char *buf){	struct dme1737_data *data = dme1737_update_device(dev);	struct sensor_device_attribute_2		*sensor_attr_2 = to_sensor_dev_attr_2(attr);	int ix = sensor_attr_2->index;	int fn = sensor_attr_2->nr;	int res;	switch (fn) {	case SYS_ZONE_AUTO_CHANNELS_TEMP:		/* check config2 for non-standard temp-to-zone mapping */		if ((ix == 1) && (data->config2 & 0x02)) {			res = 4;		} else {			res = 1 << ix;		}		break;	case SYS_ZONE_AUTO_POINT1_TEMP_HYST:		res = TEMP_FROM_REG(data->zone_low[ix], 8) -		      TEMP_HYST_FROM_REG(data->zone_hyst[ix == 2], ix);		break;	case SYS_ZONE_AUTO_POINT1_TEMP:		res = TEMP_FROM_REG(data->zone_low[ix], 8);		break;	case SYS_ZONE_AUTO_POINT2_TEMP:		/* pwm_freq holds the temp range bits in the upper nibble */		res = TEMP_FROM_REG(data->zone_low[ix], 8) +		      TEMP_RANGE_FROM_REG(data->pwm_freq[ix]);		break;	case SYS_ZONE_AUTO_POINT3_TEMP:		res = TEMP_FROM_REG(data->zone_abs[ix], 8);		break;	default:		res = 0;		dev_dbg(dev, "Unknown function %d.\n", fn);	}	return sprintf(buf, "%d\n", res);}static ssize_t set_zone(struct device *dev, struct device_attribute *attr,			const char *buf, size_t count){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -