Commit 1680a013 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging:
  hwmon: (f71882fg) Add support for the F71889A
  hwmon: (f71882fg) Add support for the F81865F
  hwmon: (f71882fg) Document all supported devices
  hwmon: (f71882fg) Per-chip fan/temperature input count tables
  hwmon: (f71882fg) Secure chip property definition arrays
parents a17d4730 a66c1088
Loading
Loading
Loading
Loading
+19 −0
Original line number Original line Diff line number Diff line
@@ -2,6 +2,10 @@ Kernel driver f71882fg
======================
======================


Supported chips:
Supported chips:
  * Fintek F71808E
    Prefix: 'f71808e'
    Addresses scanned: none, address read from Super I/O config space
    Datasheet: Not public
  * Fintek F71858FG
  * Fintek F71858FG
    Prefix: 'f71858fg'
    Prefix: 'f71858fg'
    Addresses scanned: none, address read from Super I/O config space
    Addresses scanned: none, address read from Super I/O config space
@@ -26,10 +30,25 @@ Supported chips:
    Prefix: 'f71889ed'
    Prefix: 'f71889ed'
    Addresses scanned: none, address read from Super I/O config space
    Addresses scanned: none, address read from Super I/O config space
    Datasheet: Should become available on the Fintek website soon
    Datasheet: Should become available on the Fintek website soon
  * Fintek F71889A
    Prefix: 'f71889a'
    Addresses scanned: none, address read from Super I/O config space
    Datasheet: Should become available on the Fintek website soon
  * Fintek F8000
  * Fintek F8000
    Prefix: 'f8000'
    Prefix: 'f8000'
    Addresses scanned: none, address read from Super I/O config space
    Addresses scanned: none, address read from Super I/O config space
    Datasheet: Not public
    Datasheet: Not public
  * Fintek F81801U
    Prefix: 'f71889fg'
    Addresses scanned: none, address read from Super I/O config space
    Datasheet: Not public
    Note: This is the 64-pin variant of the F71889FG, they have the
	  same device ID and are fully compatible as far as hardware
	  monitoring is concerned.
  * Fintek F81865F
    Prefix: 'f81865f'
    Addresses scanned: none, address read from Super I/O config space
    Datasheet: Available from the Fintek website


Author: Hans de Goede <hdegoede@redhat.com>
Author: Hans de Goede <hdegoede@redhat.com>


+14 −3
Original line number Original line Diff line number Diff line
@@ -315,11 +315,22 @@ config SENSORS_F71805F
	  will be called f71805f.
	  will be called f71805f.


config SENSORS_F71882FG
config SENSORS_F71882FG
	tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000"
	tristate "Fintek F71882FG and compatibles"
	help
	help
	  If you say yes here you get support for hardware monitoring
	  If you say yes here you get support for hardware monitoring
	  features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG,
	  features of many Fintek Super-I/O (LPC) chips. The currently
	  F71889FG and F8000 Super-I/O chips.
	  supported chips are:
	    F71808E
	    F71858FG
	    F71862FG
	    F71863FG
	    F71869F/E
	    F71882FG
	    F71883FG
	    F71889FG/ED/A
	    F8000
	    F81801U
	    F81865F


	  This driver can also be built as a module.  If so, the module
	  This driver can also be built as a module.  If so, the module
	  will be called f71882fg.
	  will be called f71882fg.
+84 −42
Original line number Original line Diff line number Diff line
@@ -54,7 +54,9 @@
#define SIO_F71882_ID		0x0541	/* Chipset ID */
#define SIO_F71882_ID		0x0541	/* Chipset ID */
#define SIO_F71889_ID		0x0723	/* Chipset ID */
#define SIO_F71889_ID		0x0723	/* Chipset ID */
#define SIO_F71889E_ID		0x0909	/* Chipset ID */
#define SIO_F71889E_ID		0x0909	/* Chipset ID */
#define SIO_F71889A_ID		0x1005	/* Chipset ID */
#define SIO_F8000_ID		0x0581	/* Chipset ID */
#define SIO_F8000_ID		0x0581	/* Chipset ID */
#define SIO_F81865_ID		0x0704	/* Chipset ID */


#define REGION_LENGTH		8
#define REGION_LENGTH		8
#define ADDR_REG_OFFSET		5
#define ADDR_REG_OFFSET		5
@@ -106,7 +108,7 @@ module_param(force_id, ushort, 0);
MODULE_PARM_DESC(force_id, "Override the detected device ID");
MODULE_PARM_DESC(force_id, "Override the detected device ID");


enum chips { f71808e, f71858fg, f71862fg, f71869, f71882fg, f71889fg,
enum chips { f71808e, f71858fg, f71862fg, f71869, f71882fg, f71889fg,
	     f71889ed, f8000 };
	     f71889ed, f71889a, f8000, f81865f };


static const char *f71882fg_names[] = {
static const char *f71882fg_names[] = {
	"f71808e",
	"f71808e",
@@ -114,42 +116,76 @@ static const char *f71882fg_names[] = {
	"f71862fg",
	"f71862fg",
	"f71869", /* Both f71869f and f71869e, reg. compatible and same id */
	"f71869", /* Both f71869f and f71869e, reg. compatible and same id */
	"f71882fg",
	"f71882fg",
	"f71889fg",
	"f71889fg", /* f81801u too, same id */
	"f71889ed",
	"f71889ed",
	"f71889a",
	"f8000",
	"f8000",
	"f81865f",
};
};


static const char f71882fg_has_in[8][F71882FG_MAX_INS] = {
static const char f71882fg_has_in[][F71882FG_MAX_INS] = {
	{ 1, 1, 1, 1, 1, 1, 0, 1, 1 }, /* f71808e */
	[f71808e]	= { 1, 1, 1, 1, 1, 1, 0, 1, 1 },
	{ 1, 1, 1, 0, 0, 0, 0, 0, 0 }, /* f71858fg */
	[f71858fg]	= { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71862fg */
	[f71862fg]	= { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71869 */
	[f71869]	= { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71882fg */
	[f71882fg]	= { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71889fg */
	[f71889fg]	= { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71889ed */
	[f71889ed]	= { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	{ 1, 1, 1, 0, 0, 0, 0, 0, 0 }, /* f8000 */
	[f71889a]	= { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
	[f8000]		= { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
	[f81865f]	= { 1, 1, 1, 1, 1, 1, 1, 0, 0 },
};
};


static const char f71882fg_has_in1_alarm[8] = {
static const char f71882fg_has_in1_alarm[] = {
	0, /* f71808e */
	[f71808e]	= 0,
	0, /* f71858fg */
	[f71858fg]	= 0,
	0, /* f71862fg */
	[f71862fg]	= 0,
	0, /* f71869 */
	[f71869]	= 0,
	1, /* f71882fg */
	[f71882fg]	= 1,
	1, /* f71889fg */
	[f71889fg]	= 1,
	1, /* f71889ed */
	[f71889ed]	= 1,
	0, /* f8000 */
	[f71889a]	= 1,
	[f8000]		= 0,
	[f81865f]	= 1,
};
};


static const char f71882fg_has_beep[8] = {
static const char f71882fg_has_beep[] = {
	0, /* f71808e */
	[f71808e]	= 0,
	0, /* f71858fg */
	[f71858fg]	= 0,
	1, /* f71862fg */
	[f71862fg]	= 1,
	1, /* f71869 */
	[f71869]	= 1,
	1, /* f71882fg */
	[f71882fg]	= 1,
	1, /* f71889fg */
	[f71889fg]	= 1,
	1, /* f71889ed */
	[f71889ed]	= 1,
	0, /* f8000 */
	[f71889a]	= 1,
	[f8000]		= 0,
	[f81865f]	= 1,
};

static const char f71882fg_nr_fans[] = {
	[f71808e]	= 3,
	[f71858fg]	= 3,
	[f71862fg]	= 3,
	[f71869]	= 3,
	[f71882fg]	= 4,
	[f71889fg]	= 3,
	[f71889ed]	= 3,
	[f71889a]	= 3,
	[f8000]		= 3,
	[f81865f]	= 2,
};

static const char f71882fg_nr_temps[] = {
	[f71808e]	= 2,
	[f71858fg]	= 3,
	[f71862fg]	= 3,
	[f71869]	= 3,
	[f71882fg]	= 3,
	[f71889fg]	= 3,
	[f71889ed]	= 3,
	[f71889a]	= 3,
	[f8000]		= 3,
	[f81865f]	= 2,
};
};


static struct platform_device *f71882fg_pdev;
static struct platform_device *f71882fg_pdev;
@@ -1071,9 +1107,9 @@ static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr)
static struct f71882fg_data *f71882fg_update_device(struct device *dev)
static struct f71882fg_data *f71882fg_update_device(struct device *dev)
{
{
	struct f71882fg_data *data = dev_get_drvdata(dev);
	struct f71882fg_data *data = dev_get_drvdata(dev);
	int nr_fans = f71882fg_nr_fans[data->type];
	int nr_temps = f71882fg_nr_temps[data->type];
	int nr, reg, point;
	int nr, reg, point;
	int nr_fans = (data->type == f71882fg) ? 4 : 3;
	int nr_temps = (data->type == f71808e) ? 2 : 3;


	mutex_lock(&data->update_lock);
	mutex_lock(&data->update_lock);


@@ -2042,8 +2078,9 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
{
{
	struct f71882fg_data *data;
	struct f71882fg_data *data;
	struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
	struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
	int err, i, nr_fans = (sio_data->type == f71882fg) ? 4 : 3;
	int nr_fans = f71882fg_nr_fans[sio_data->type];
	int nr_temps = (sio_data->type == f71808e) ? 2 : 3;
	int nr_temps = f71882fg_nr_temps[sio_data->type];
	int err, i;
	u8 start_reg, reg;
	u8 start_reg, reg;


	data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL);
	data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL);
@@ -2138,6 +2175,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
			/* Fall through to select correct fan/pwm reg bank! */
			/* Fall through to select correct fan/pwm reg bank! */
		case f71889fg:
		case f71889fg:
		case f71889ed:
		case f71889ed:
		case f71889a:
			reg = f71882fg_read8(data, F71882FG_REG_FAN_FAULT_T);
			reg = f71882fg_read8(data, F71882FG_REG_FAN_FAULT_T);
			if (reg & F71882FG_FAN_NEG_TEMP_EN)
			if (reg & F71882FG_FAN_NEG_TEMP_EN)
				data->auto_point_temp_signed = 1;
				data->auto_point_temp_signed = 1;
@@ -2163,16 +2201,12 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
		case f71862fg:
		case f71862fg:
			err = (data->pwm_enable & 0x15) != 0x15;
			err = (data->pwm_enable & 0x15) != 0x15;
			break;
			break;
		case f71808e:
		case f71869:
		case f71882fg:
		case f71889fg:
		case f71889ed:
			err = 0;
			break;
		case f8000:
		case f8000:
			err = data->pwm_enable & 0x20;
			err = data->pwm_enable & 0x20;
			break;
			break;
		default:
			err = 0;
			break;
		}
		}
		if (err) {
		if (err) {
			dev_err(&pdev->dev,
			dev_err(&pdev->dev,
@@ -2199,6 +2233,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
		case f71869:
		case f71869:
		case f71889fg:
		case f71889fg:
		case f71889ed:
		case f71889ed:
		case f71889a:
			for (i = 0; i < nr_fans; i++) {
			for (i = 0; i < nr_fans; i++) {
				data->pwm_auto_point_mapping[i] =
				data->pwm_auto_point_mapping[i] =
					f71882fg_read8(data,
					f71882fg_read8(data,
@@ -2276,8 +2311,9 @@ exit_free:
static int f71882fg_remove(struct platform_device *pdev)
static int f71882fg_remove(struct platform_device *pdev)
{
{
	struct f71882fg_data *data = platform_get_drvdata(pdev);
	struct f71882fg_data *data = platform_get_drvdata(pdev);
	int i, nr_fans = (data->type == f71882fg) ? 4 : 3;
	int nr_fans = f71882fg_nr_fans[data->type];
	int nr_temps = (data->type == f71808e) ? 2 : 3;
	int nr_temps = f71882fg_nr_temps[data->type];
	int i;
	u8 start_reg = f71882fg_read8(data, F71882FG_REG_START);
	u8 start_reg = f71882fg_read8(data, F71882FG_REG_START);


	if (data->hwmon_dev)
	if (data->hwmon_dev)
@@ -2406,9 +2442,15 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
	case SIO_F71889E_ID:
	case SIO_F71889E_ID:
		sio_data->type = f71889ed;
		sio_data->type = f71889ed;
		break;
		break;
	case SIO_F71889A_ID:
		sio_data->type = f71889a;
		break;
	case SIO_F8000_ID:
	case SIO_F8000_ID:
		sio_data->type = f8000;
		sio_data->type = f8000;
		break;
		break;
	case SIO_F81865_ID:
		sio_data->type = f81865f;
		break;
	default:
	default:
		pr_info("Unsupported Fintek device: %04x\n",
		pr_info("Unsupported Fintek device: %04x\n",
			(unsigned int)devid);
			(unsigned int)devid);