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

📄 f71805f.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	&sensor_dev_attr_in1_alarm.dev_attr.attr,	&sensor_dev_attr_in2_alarm.dev_attr.attr,	&sensor_dev_attr_in3_alarm.dev_attr.attr,	&sensor_dev_attr_in5_alarm.dev_attr.attr,	&sensor_dev_attr_in6_alarm.dev_attr.attr,	&sensor_dev_attr_in7_alarm.dev_attr.attr,	&dev_attr_alarms_in.attr,	&sensor_dev_attr_temp1_alarm.dev_attr.attr,	&sensor_dev_attr_temp2_alarm.dev_attr.attr,	&sensor_dev_attr_temp3_alarm.dev_attr.attr,	&dev_attr_alarms_temp.attr,	&dev_attr_alarms_fan.attr,	&dev_attr_name.attr,	NULL};static const struct attribute_group f71805f_group = {	.attrs = f71805f_attributes,};static struct attribute *f71805f_attributes_optin[4][5] = {	{		&sensor_dev_attr_in4_input.dev_attr.attr,		&sensor_dev_attr_in4_max.dev_attr.attr,		&sensor_dev_attr_in4_min.dev_attr.attr,		&sensor_dev_attr_in4_alarm.dev_attr.attr,		NULL	}, {		&sensor_dev_attr_in8_input.dev_attr.attr,		&sensor_dev_attr_in8_max.dev_attr.attr,		&sensor_dev_attr_in8_min.dev_attr.attr,		&sensor_dev_attr_in8_alarm.dev_attr.attr,		NULL	}, {		&sensor_dev_attr_in9_input.dev_attr.attr,		&sensor_dev_attr_in9_max.dev_attr.attr,		&sensor_dev_attr_in9_min.dev_attr.attr,		&sensor_dev_attr_in9_alarm.dev_attr.attr,		NULL	}, {		&sensor_dev_attr_in10_input.dev_attr.attr,		&sensor_dev_attr_in10_max.dev_attr.attr,		&sensor_dev_attr_in10_min.dev_attr.attr,		&sensor_dev_attr_in10_alarm.dev_attr.attr,		NULL	}};static const struct attribute_group f71805f_group_optin[4] = {	{ .attrs = f71805f_attributes_optin[0] },	{ .attrs = f71805f_attributes_optin[1] },	{ .attrs = f71805f_attributes_optin[2] },	{ .attrs = f71805f_attributes_optin[3] },};/* We don't include pwm_freq files in the arrays above, because they must be   created conditionally (only if pwm_mode is 1 == PWM) */static struct attribute *f71805f_attributes_pwm_freq[] = {	&sensor_dev_attr_pwm1_freq.dev_attr.attr,	&sensor_dev_attr_pwm2_freq.dev_attr.attr,	&sensor_dev_attr_pwm3_freq.dev_attr.attr,	NULL};static const struct attribute_group f71805f_group_pwm_freq = {	.attrs = f71805f_attributes_pwm_freq,};/* We also need an indexed access to pwmN files to toggle writability */static struct attribute *f71805f_attr_pwm[] = {	&sensor_dev_attr_pwm1.dev_attr.attr,	&sensor_dev_attr_pwm2.dev_attr.attr,	&sensor_dev_attr_pwm3.dev_attr.attr,};/* * Device registration and initialization */static void __devinit f71805f_init_device(struct f71805f_data *data){	u8 reg;	int i;	reg = f71805f_read8(data, F71805F_REG_START);	if ((reg & 0x41) != 0x01) {		printk(KERN_DEBUG DRVNAME ": Starting monitoring "		       "operations\n");		f71805f_write8(data, F71805F_REG_START, (reg | 0x01) & ~0x40);	}	/* Fan monitoring can be disabled. If it is, we won't be polling	   the register values, and won't create the related sysfs files. */	for (i = 0; i < 3; i++) {		data->fan_ctrl[i] = f71805f_read8(data,						  F71805F_REG_FAN_CTRL(i));		/* Clear latch full bit, else "speed mode" fan speed control		   doesn't work */		if (data->fan_ctrl[i] & FAN_CTRL_LATCH_FULL) {			data->fan_ctrl[i] &= ~FAN_CTRL_LATCH_FULL;			f71805f_write8(data, F71805F_REG_FAN_CTRL(i),				       data->fan_ctrl[i]);		}	}}static int __devinit f71805f_probe(struct platform_device *pdev){	struct f71805f_sio_data *sio_data = pdev->dev.platform_data;	struct f71805f_data *data;	struct resource *res;	int i, err;	static const char *names[] = {		"f71805f",		"f71872f",	};	if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {		err = -ENOMEM;		printk(KERN_ERR DRVNAME ": Out of memory\n");		goto exit;	}	res = platform_get_resource(pdev, IORESOURCE_IO, 0);	if (!request_region(res->start + ADDR_REG_OFFSET, 2, DRVNAME)) {		err = -EBUSY;		dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n",			(unsigned long)(res->start + ADDR_REG_OFFSET),			(unsigned long)(res->start + ADDR_REG_OFFSET + 1));		goto exit_free;	}	data->addr = res->start;	data->name = names[sio_data->kind];	mutex_init(&data->update_lock);	platform_set_drvdata(pdev, data);	/* Some voltage inputs depend on chip model and configuration */	switch (sio_data->kind) {	case f71805f:		data->has_in = 0x1ff;		break;	case f71872f:		data->has_in = 0x6ef;		if (sio_data->fnsel1 & 0x01)			data->has_in |= (1 << 4); /* in4 */		if (sio_data->fnsel1 & 0x02)			data->has_in |= (1 << 8); /* in8 */		break;	}	/* Initialize the F71805F chip */	f71805f_init_device(data);	/* Register sysfs interface files */	if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group)))		goto exit_release_region;	if (data->has_in & (1 << 4)) { /* in4 */		if ((err = sysfs_create_group(&pdev->dev.kobj,					      &f71805f_group_optin[0])))			goto exit_remove_files;	}	if (data->has_in & (1 << 8)) { /* in8 */		if ((err = sysfs_create_group(&pdev->dev.kobj,					      &f71805f_group_optin[1])))			goto exit_remove_files;	}	if (data->has_in & (1 << 9)) { /* in9 (F71872F/FG only) */		if ((err = sysfs_create_group(&pdev->dev.kobj,					      &f71805f_group_optin[2])))			goto exit_remove_files;	}	if (data->has_in & (1 << 10)) { /* in9 (F71872F/FG only) */		if ((err = sysfs_create_group(&pdev->dev.kobj,					      &f71805f_group_optin[3])))			goto exit_remove_files;	}	for (i = 0; i < 3; i++) {		/* If control mode is PWM, create pwm_freq file */		if (!(data->fan_ctrl[i] & FAN_CTRL_DC_MODE)) {			if ((err = sysfs_create_file(&pdev->dev.kobj,					f71805f_attributes_pwm_freq[i])))				goto exit_remove_files;		}		/* If PWM is in manual mode, add write permission */		if (data->fan_ctrl[i] & FAN_CTRL_MODE_MANUAL) {			if ((err = sysfs_chmod_file(&pdev->dev.kobj,						    f71805f_attr_pwm[i],						    S_IRUGO | S_IWUSR))) {				dev_err(&pdev->dev, "chmod +w pwm%d failed\n",					i + 1);				goto exit_remove_files;			}		}	}	data->hwmon_dev = hwmon_device_register(&pdev->dev);	if (IS_ERR(data->hwmon_dev)) {		err = PTR_ERR(data->hwmon_dev);		dev_err(&pdev->dev, "Class registration failed (%d)\n", err);		goto exit_remove_files;	}	return 0;exit_remove_files:	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);	for (i = 0; i < 4; i++)		sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);exit_release_region:	release_region(res->start + ADDR_REG_OFFSET, 2);exit_free:	platform_set_drvdata(pdev, NULL);	kfree(data);exit:	return err;}static int __devexit f71805f_remove(struct platform_device *pdev){	struct f71805f_data *data = platform_get_drvdata(pdev);	struct resource *res;	int i;	hwmon_device_unregister(data->hwmon_dev);	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);	for (i = 0; i < 4; i++)		sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);	platform_set_drvdata(pdev, NULL);	kfree(data);	res = platform_get_resource(pdev, IORESOURCE_IO, 0);	release_region(res->start + ADDR_REG_OFFSET, 2);	return 0;}static struct platform_driver f71805f_driver = {	.driver = {		.owner	= THIS_MODULE,		.name	= DRVNAME,	},	.probe		= f71805f_probe,	.remove		= __devexit_p(f71805f_remove),};static int __init f71805f_device_add(unsigned short address,				     const struct f71805f_sio_data *sio_data){	struct resource res = {		.start	= address,		.end	= address + REGION_LENGTH - 1,		.flags	= IORESOURCE_IO,	};	int err;	pdev = platform_device_alloc(DRVNAME, address);	if (!pdev) {		err = -ENOMEM;		printk(KERN_ERR DRVNAME ": Device allocation failed\n");		goto exit;	}	res.name = pdev->name;	err = platform_device_add_resources(pdev, &res, 1);	if (err) {		printk(KERN_ERR DRVNAME ": Device resource addition failed "		       "(%d)\n", err);		goto exit_device_put;	}	err = platform_device_add_data(pdev, sio_data,				       sizeof(struct f71805f_sio_data));	if (err) {		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");		goto exit_device_put;	}	err = platform_device_add(pdev);	if (err) {		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",		       err);		goto exit_device_put;	}	return 0;exit_device_put:	platform_device_put(pdev);exit:	return err;}static int __init f71805f_find(int sioaddr, unsigned short *address,			       struct f71805f_sio_data *sio_data){	int err = -ENODEV;	u16 devid;	static const char *names[] = {		"F71805F/FG",		"F71872F/FG or F71806F/FG",	};	superio_enter(sioaddr);	devid = superio_inw(sioaddr, SIO_REG_MANID);	if (devid != SIO_FINTEK_ID)		goto exit;	devid = superio_inw(sioaddr, SIO_REG_DEVID);	switch (devid) {	case SIO_F71805F_ID:		sio_data->kind = f71805f;		break;	case SIO_F71872F_ID:		sio_data->kind = f71872f;		sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1);		break;	default:		printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "		       "skipping\n");		goto exit;	}	superio_select(sioaddr, F71805F_LD_HWM);	if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {		printk(KERN_WARNING DRVNAME ": Device not activated, "		       "skipping\n");		goto exit;	}	*address = superio_inw(sioaddr, SIO_REG_ADDR);	if (*address == 0) {		printk(KERN_WARNING DRVNAME ": Base address not set, "		       "skipping\n");		goto exit;	}	*address &= ~(REGION_LENGTH - 1);	/* Ignore 3 LSB */	err = 0;	printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %u\n",	       names[sio_data->kind], *address,	       superio_inb(sioaddr, SIO_REG_DEVREV));exit:	superio_exit(sioaddr);	return err;}static int __init f71805f_init(void){	int err;	unsigned short address;	struct f71805f_sio_data sio_data;	if (f71805f_find(0x2e, &address, &sio_data)	 && f71805f_find(0x4e, &address, &sio_data))		return -ENODEV;	err = platform_driver_register(&f71805f_driver);	if (err)		goto exit;	/* Sets global pdev as a side effect */	err = f71805f_device_add(address, &sio_data);	if (err)		goto exit_driver;	return 0;exit_driver:	platform_driver_unregister(&f71805f_driver);exit:	return err;}static void __exit f71805f_exit(void){	platform_device_unregister(pdev);	platform_driver_unregister(&f71805f_driver);}MODULE_AUTHOR("Jean Delvare <khali@linux-fr>");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("F71805F/F71872F hardware monitoring driver");module_init(f71805f_init);module_exit(f71805f_exit);

⌨️ 快捷键说明

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