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

📄 dme1737.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
}static int dme1737_create_files(struct device *dev){	struct dme1737_data *data = dev_get_drvdata(dev);	int err, ix;	/* Create a name attribute for ISA devices */	if (!data->client.driver &&	    (err = sysfs_create_file(&dev->kobj, &dev_attr_name.attr))) {		goto exit;	}	/* Create standard sysfs attributes */	if ((err = sysfs_create_group(&dev->kobj, &dme1737_group))) {		goto exit_remove;	}	/* Create fan sysfs attributes */	for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) {		if (data->has_fan & (1 << ix)) {			if ((err = sysfs_create_group(&dev->kobj,						&dme1737_fan_group[ix]))) {				goto exit_remove;			}		}	}	/* Create PWM sysfs attributes */	for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) {		if (data->has_pwm & (1 << ix)) {			if ((err = sysfs_create_group(&dev->kobj,						&dme1737_pwm_group[ix]))) {				goto exit_remove;			}		}	}	/* Inform if the device is locked. Otherwise change the permissions of	 * selected attributes from read-only to read-writeable. */	if (data->config & 0x02) {		dev_info(dev, "Device is locked. Some attributes "			 "will be read-only.\n");	} else {		/* Change permissions of standard attributes */		dme1737_chmod_group(dev, &dme1737_lock_group,				    S_IRUGO | S_IWUSR);		/* Change permissions of PWM attributes */		for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_lock_group); ix++) {			if (data->has_pwm & (1 << ix)) {				dme1737_chmod_group(dev,						&dme1737_pwm_lock_group[ix],						S_IRUGO | S_IWUSR);			}		}		/* Change permissions of pwm[1-3] if in manual mode */		for (ix = 0; ix < 3; ix++) {			if ((data->has_pwm & (1 << ix)) &&			    (PWM_EN_FROM_REG(data->pwm_config[ix]) == 1)) {				dme1737_chmod_file(dev,						dme1737_attr_pwm[ix],						S_IRUGO | S_IWUSR);			}		}	}	return 0;exit_remove:	dme1737_remove_files(dev);exit:	return err;}static int dme1737_init_device(struct device *dev){	struct dme1737_data *data = dev_get_drvdata(dev);	struct i2c_client *client = &data->client;	int ix;	u8 reg;	data->config = dme1737_read(client, DME1737_REG_CONFIG);	/* Inform if part is not monitoring/started */	if (!(data->config & 0x01)) {		if (!force_start) {			dev_err(dev, "Device is not monitoring. "				"Use the force_start load parameter to "				"override.\n");			return -EFAULT;		}		/* Force monitoring */		data->config |= 0x01;		dme1737_write(client, DME1737_REG_CONFIG, data->config);	}	/* Inform if part is not ready */	if (!(data->config & 0x04)) {		dev_err(dev, "Device is not ready.\n");		return -EFAULT;	}	/* Determine which optional fan and pwm features are enabled/present */	if (client->driver) {   /* I2C chip */		data->config2 = dme1737_read(client, DME1737_REG_CONFIG2);		/* Check if optional fan3 input is enabled */		if (data->config2 & 0x04) {			data->has_fan |= (1 << 2);		}		/* Fan4 and pwm3 are only available if the client's I2C address		 * is the default 0x2e. Otherwise the I/Os associated with		 * these functions are used for addr enable/select. */		if (data->client.addr == 0x2e) {			data->has_fan |= (1 << 3);			data->has_pwm |= (1 << 2);		}		/* Determine which of the optional fan[5-6] and pwm[5-6]		 * features are enabled. For this, we need to query the runtime		 * registers through the Super-IO LPC interface. Try both		 * config ports 0x2e and 0x4e. */		if (dme1737_i2c_get_features(0x2e, data) &&		    dme1737_i2c_get_features(0x4e, data)) {			dev_warn(dev, "Failed to query Super-IO for optional "				 "features.\n");		}	} else {   /* ISA chip */		/* Fan3 and pwm3 are always available. Fan[4-5] and pwm[5-6]		 * don't exist in the ISA chip. */		data->has_fan |= (1 << 2);		data->has_pwm |= (1 << 2);	}	/* Fan1, fan2, pwm1, and pwm2 are always present */	data->has_fan |= 0x03;	data->has_pwm |= 0x03;	dev_info(dev, "Optional features: pwm3=%s, pwm5=%s, pwm6=%s, "		 "fan3=%s, fan4=%s, fan5=%s, fan6=%s.\n",		 (data->has_pwm & (1 << 2)) ? "yes" : "no",		 (data->has_pwm & (1 << 4)) ? "yes" : "no",		 (data->has_pwm & (1 << 5)) ? "yes" : "no",		 (data->has_fan & (1 << 2)) ? "yes" : "no",		 (data->has_fan & (1 << 3)) ? "yes" : "no",		 (data->has_fan & (1 << 4)) ? "yes" : "no",		 (data->has_fan & (1 << 5)) ? "yes" : "no");	reg = dme1737_read(client, DME1737_REG_TACH_PWM);	/* Inform if fan-to-pwm mapping differs from the default */	if (client->driver && reg != 0xa4) {   /* I2C chip */		dev_warn(dev, "Non-standard fan to pwm mapping: "			 "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d, "			 "fan4->pwm%d. Please report to the driver "			 "maintainer.\n",			 (reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1,			 ((reg >> 4) & 0x03) + 1, ((reg >> 6) & 0x03) + 1);	} else if (!client->driver && reg != 0x24) {   /* ISA chip */		dev_warn(dev, "Non-standard fan to pwm mapping: "			 "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d. "			 "Please report to the driver maintainer.\n",			 (reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1,			 ((reg >> 4) & 0x03) + 1);	}	/* Switch pwm[1-3] to manual mode if they are currently disabled and	 * set the duty-cycles to 0% (which is identical to the PWMs being	 * disabled). */	if (!(data->config & 0x02)) {		for (ix = 0; ix < 3; ix++) {			data->pwm_config[ix] = dme1737_read(client,						DME1737_REG_PWM_CONFIG(ix));			if ((data->has_pwm & (1 << ix)) &&			    (PWM_EN_FROM_REG(data->pwm_config[ix]) == -1)) {				dev_info(dev, "Switching pwm%d to "					 "manual mode.\n", ix + 1);				data->pwm_config[ix] = PWM_EN_TO_REG(1,							data->pwm_config[ix]);				dme1737_write(client, DME1737_REG_PWM(ix), 0);				dme1737_write(client,					      DME1737_REG_PWM_CONFIG(ix),					      data->pwm_config[ix]);			}		}	}	/* Initialize the default PWM auto channels zone (acz) assignments */	data->pwm_acz[0] = 1;	/* pwm1 -> zone1 */	data->pwm_acz[1] = 2;	/* pwm2 -> zone2 */	data->pwm_acz[2] = 4;	/* pwm3 -> zone3 */	/* Set VRM */	data->vrm = vid_which_vrm();	return 0;}/* --------------------------------------------------------------------- * I2C device detection and registration * --------------------------------------------------------------------- */static struct i2c_driver dme1737_i2c_driver;static int dme1737_i2c_get_features(int sio_cip, struct dme1737_data *data){	int err = 0, reg;	u16 addr;	dme1737_sio_enter(sio_cip);	/* Check device ID	 * The DME1737 can return either 0x78 or 0x77 as its device ID. */	reg = dme1737_sio_inb(sio_cip, 0x20);	if (!(reg == 0x77 || reg == 0x78)) {		err = -ENODEV;		goto exit;	}	/* Select logical device A (runtime registers) */	dme1737_sio_outb(sio_cip, 0x07, 0x0a);	/* Get the base address of the runtime registers */	if (!(addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) |		      dme1737_sio_inb(sio_cip, 0x61))) {		err = -ENODEV;		goto exit;	}	/* Read the runtime registers to determine which optional features	 * are enabled and available. Bits [3:2] of registers 0x43-0x46 are set	 * to '10' if the respective feature is enabled. */	if ((inb(addr + 0x43) & 0x0c) == 0x08) { /* fan6 */		data->has_fan |= (1 << 5);	}	if ((inb(addr + 0x44) & 0x0c) == 0x08) { /* pwm6 */		data->has_pwm |= (1 << 5);	}	if ((inb(addr + 0x45) & 0x0c) == 0x08) { /* fan5 */		data->has_fan |= (1 << 4);	}	if ((inb(addr + 0x46) & 0x0c) == 0x08) { /* pwm5 */		data->has_pwm |= (1 << 4);	}exit:	dme1737_sio_exit(sio_cip);	return err;}static int dme1737_i2c_detect(struct i2c_adapter *adapter, int address,			      int kind){	u8 company, verstep = 0;	struct i2c_client *client;	struct dme1737_data *data;	struct device *dev;	int err = 0;	const char *name;	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {		goto exit;	}	if (!(data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL))) {		err = -ENOMEM;		goto exit;	}	client = &data->client;	i2c_set_clientdata(client, data);	client->addr = address;	client->adapter = adapter;	client->driver = &dme1737_i2c_driver;	dev = &client->dev;	/* A negative kind means that the driver was loaded with no force	 * parameter (default), so we must identify the chip. */	if (kind < 0) {		company = dme1737_read(client, DME1737_REG_COMPANY);		verstep = dme1737_read(client, DME1737_REG_VERSTEP);		if (!((company == DME1737_COMPANY_SMSC) &&		      ((verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP))) {			err = -ENODEV;			goto exit_kfree;		}	}	kind = dme1737;	name = "dme1737";	/* Fill in the remaining client fields and put it into the global	 * list */	strlcpy(client->name, name, I2C_NAME_SIZE);	mutex_init(&data->update_lock);	/* Tell the I2C layer a new client has arrived */	if ((err = i2c_attach_client(client))) {		goto exit_kfree;	}	dev_info(dev, "Found a DME1737 chip at 0x%02x (rev 0x%02x).\n",		 client->addr, verstep);	/* Initialize the DME1737 chip */	if ((err = dme1737_init_device(dev))) {		dev_err(dev, "Failed to initialize device.\n");		goto exit_detach;	}	/* Create sysfs files */	if ((err = dme1737_create_files(dev))) {		dev_err(dev, "Failed to create sysfs files.\n");		goto exit_detach;	}	/* Register device */	data->hwmon_dev = hwmon_device_register(dev);	if (IS_ERR(data->hwmon_dev)) {		dev_err(dev, "Failed to register device.\n");		err = PTR_ERR(data->hwmon_dev);		goto exit_remove;	}	return 0;exit_remove:	dme1737_remove_files(dev);exit_detach:	i2c_detach_client(client);exit_kfree:	kfree(data);exit:	return err;}static int dme1737_i2c_attach_adapter(struct i2c_adapter *adapter){	if (!(adapter->class & I2C_CLASS_HWMON)) {		return 0;	}	return i2c_probe(adapter, &addr_data, dme1737_i2c_detect);}static int dme1737_i2c_detach_client(struct i2c_client *client){	struct dme1737_data *data = i2c_get_clientdata(client);	int err;	hwmon_device_unregister(data->hwmon_dev);	dme1737_remove_files(&client->dev);	if ((err = i2c_detach_client(client))) {		return err;	}	kfree(data);	return 0;}static struct i2c_driver dme1737_i2c_driver = {	.driver = {		.name = "dme1737",	},	.attach_adapter	= dme1737_i2c_attach_adapter,	.detach_client = dme1737_i2c_detach_client,};/* --------------------------------------------------------------------- * ISA device detection and registration * --------------------------------------------------------------------- */static int __init dme1737_isa_detect(int sio_cip, unsigned short *addr){	int err = 0, reg;	unsigned short base_addr;	dme1737_sio_enter(sio_cip);	/* Check device ID	 * We currently know about SCH3112 (0x7c), SCH3114 (0x7d), and	 * SCH3116 (0x7f). */	reg = dme1737_sio_inb(sio_cip, 0x20);	if (!(reg == 0x7c || reg == 0x7d || reg == 0x7f)) {		err = -ENODEV;		goto exit;	}	/* Select logical device A (runtime registers) */	dme1737_sio_outb(sio_cip, 0x07, 0x0a);	/* Get the base address of the runtime registers */	if (!(base_addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) |			   dme1737_sio_inb(sio_cip, 0x61))) {		printk(KERN_ERR "dme1737: Base address not set.\n");		err = -ENODEV;		goto exit;	}	/* Access to the hwmon registers is through an index/data register	 * pair located at offset 0x70/0x71. */	*addr = base_addr + 0x70;exit:	dme1737_sio_exit(sio_cip);	return err;}static int __init dme1737_isa_device_add(unsigned short addr){	struct resource res = {		.start	= addr,		.end	= addr + DME1737_EXTENT - 1,		.name	= "dme1737",		.flags	= IORESOURCE_IO,	};	int err;	if (!(pdev = platform_device_alloc("dme1737", addr))) {		printk(KERN_ERR "dme1737: Failed to allocate device.\n");		err = -ENOMEM;		goto exit;	}	if ((err = platform_device_add_resources(pdev, &res, 1))) {		printk(KERN_ERR "dme1737: Failed to add device resource "		       "(err = %d).\n", err);		goto exit_device_put;	}	if ((err = platform_device_add(pdev))) {		printk(KERN_ERR "dme1737: Failed to add device (err = %d).\n",		       err);		goto exit_device_put;	}	return 0;exit_device_put:	platform_device_put(pdev);	pdev = NULL;exit:	return err;}static int __devinit dme1737_isa_probe(struct platform_device *pdev){	u8 comp

⌨️ 快捷键说明

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