Re: [PATCH 1/6] hwmon: (pc87427) Handle disabled fan inputs properly

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 2010-08-11 at 11:08 -0400, Jean Delvare wrote:
> Most fan input pins of the PC87427 can have alternate functions.
> Update the driver to check the configuration register and only support
> fan inputs which are really used for fan monitoring.
> 
> Signed-off-by: Jean Delvare <khali@xxxxxxxxxxxx>

Acked-by: Guenter Roeck <guenter.roeck@xxxxxxxxxxxx>

> ---
>  drivers/hwmon/pc87427.c |   67 ++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 58 insertions(+), 9 deletions(-)
> 
> --- linux-2.6.32-rc3.orig/drivers/hwmon/pc87427.c	2009-10-02 16:11:15.000000000 +0200
> +++ linux-2.6.32-rc3/drivers/hwmon/pc87427.c	2009-10-11 14:27:30.000000000 +0200
> @@ -1,7 +1,7 @@
>  /*
>   *  pc87427.c - hardware monitoring driver for the
>   *              National Semiconductor PC87427 Super-I/O chip
> - *  Copyright (C) 2006 Jean Delvare <khali@xxxxxxxxxxxx>
> + *  Copyright (C) 2006, 2008  Jean Delvare <khali@xxxxxxxxxxxx>
>   *
2010 ?

>   *  This program is free software; you can redistribute it and/or modify
>   *  it under the terms of the GNU General Public License version 2 as
> @@ -59,12 +59,21 @@ struct pc87427_data {
>  	u8 fan_status[8];		/* register values */
>  };
>  
> +struct pc87427_sio_data {
> +	u8 has_fanin;
> +};
> +
>  /*
>   * Super-I/O registers and operations
>   */
>  
>  #define SIOREG_LDSEL	0x07	/* Logical device select */
>  #define SIOREG_DEVID	0x20	/* Device ID */
> +#define SIOREG_CF2	0x22	/* Configuration 2 */
> +#define SIOREG_CF3	0x23	/* Configuration 3 */
> +#define SIOREG_CF4	0x24	/* Configuration 4 */
> +#define SIOREG_CFB	0x2B	/* Configuration B */
> +#define SIOREG_CFD	0x2D	/* Configuration D */
>  #define SIOREG_ACT	0x30	/* Device activation */
>  #define SIOREG_MAP	0x50	/* I/O or memory mapping */
>  #define SIOREG_IOBASE	0x60	/* I/O base address */
> @@ -393,6 +402,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_n
>  
>  static void __devinit pc87427_init_device(struct device *dev)
>  {
> +	struct pc87427_sio_data *sio_data = dev->platform_data;
>  	struct pc87427_data *data = dev_get_drvdata(dev);
>  	int i;
>  	u8 reg;
> @@ -404,6 +414,8 @@ static void __devinit pc87427_init_devic
>  
>  	/* Check which fans are enabled */
>  	for (i = 0; i < 8; i++) {
> +		if (!(sio_data->has_fanin & (1 << i)))	/* Not wired */
> +			continue;
>  		reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i),
>  					 PC87427_REG_FAN_STATUS);
>  		if (reg & FAN_STATUS_MONEN)
> @@ -411,12 +423,15 @@ static void __devinit pc87427_init_devic
>  	}
>  
>  	if (!data->fan_enabled) {
> -		dev_dbg(dev, "Enabling all fan inputs\n");
> -		for (i = 0; i < 8; i++)
> +		dev_dbg(dev, "Enabling monitoring of all fans\n");
> +		for (i = 0; i < 8; i++) {
> +			if (!(sio_data->has_fanin & (1 << i)))	/* Not wired */
> +				continue;
>  			pc87427_write8_bank(data, LD_FAN, BANK_FM(i),
>  					    PC87427_REG_FAN_STATUS,
>  					    FAN_STATUS_MONEN);
> -		data->fan_enabled = 0xff;
> +		}
> +		data->fan_enabled = sio_data->has_fanin;
>  	}
>  }
>  
> @@ -515,7 +530,8 @@ static struct platform_driver pc87427_dr
>  	.remove		= __devexit_p(pc87427_remove),
>  };
>  
> -static int __init pc87427_device_add(unsigned short address)
> +static int __init pc87427_device_add(unsigned short address,
> +				     const struct pc87427_sio_data *sio_data)
>  {
>  	struct resource res = {
>  		.start	= address,
> @@ -543,6 +559,13 @@ static int __init pc87427_device_add(uns
>  		goto exit_device_put;
>  	}
>  
> +	err = platform_device_add_data(pdev, sio_data,
> +				       sizeof(struct pc87427_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",
> @@ -558,9 +581,11 @@ exit:
>  	return err;
>  }
>  
> -static int __init pc87427_find(int sioaddr, unsigned short *address)
> +static int __init pc87427_find(int sioaddr, unsigned short *address,
> +			       struct pc87427_sio_data *sio_data)
>  {
>  	u16 val;
> +	u8 cfg, cfg_b;
>  	int i, err = 0;
>  
>  	/* Identify device */
> @@ -599,6 +624,29 @@ static int __init pc87427_find(int sioad
>  		address[i] = val;
>  	}
>  
> +	/* Check which fan inputs are wired */
> +	sio_data->has_fanin = (1 << 2) | (1 << 3);	/* FANIN2, FANIN3 */
> +
> +	cfg = superio_inb(sioaddr, SIOREG_CF2);
> +	if (!(cfg & (1 << 3)))
> +		sio_data->has_fanin |= (1 << 0);	/* FANIN0 */
> +	if (!(cfg & (1 << 2)))
> +		sio_data->has_fanin |= (1 << 4);	/* FANIN4 */
> +
> +	cfg = superio_inb(sioaddr, SIOREG_CFD);
> +	if (!(cfg & (1 << 0)))
> +		sio_data->has_fanin |= (1 << 1);	/* FANIN1 */
> +
> +	cfg = superio_inb(sioaddr, SIOREG_CF4);
> +	if (!(cfg & (1 << 0)))
> +		sio_data->has_fanin |= (1 << 7);	/* FANIN7 */
> +	cfg_b = superio_inb(sioaddr, SIOREG_CFB);
> +	if (!(cfg & (1 << 1)) && (cfg_b & (1 << 3)))
> +		sio_data->has_fanin |= (1 << 5);	/* FANIN5 */
> +	cfg = superio_inb(sioaddr, SIOREG_CF3);
> +	if ((cfg & (1 << 3)) && !(cfg_b & (1 << 5)))
> +		sio_data->has_fanin |= (1 << 6);	/* FANIN6 */
> +
>  exit:
>  	superio_exit(sioaddr);
>  	return err;
> @@ -608,9 +656,10 @@ static int __init pc87427_init(void)
>  {
>  	int err;
>  	unsigned short address[2];
> +	struct pc87427_sio_data sio_data;
>  
> -	if (pc87427_find(0x2e, address)
> -	 && pc87427_find(0x4e, address))
> +	if (pc87427_find(0x2e, address, &sio_data)
> +	 && pc87427_find(0x4e, address, &sio_data))
>  		return -ENODEV;
>  
>  	/* For now the driver only handles fans so we only care about the
> @@ -623,7 +672,7 @@ static int __init pc87427_init(void)
>  		goto exit;
>  
>  	/* Sets global pdev as a side effect */
> -	err = pc87427_device_add(address[0]);
> +	err = pc87427_device_add(address[0], &sio_data);
>  	if (err)
>  		goto exit_driver;
>  
> 



_______________________________________________
lm-sensors mailing list
lm-sensors@xxxxxxxxxxxxxx
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors


[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux