hwmon updates for v4.12
Removed twl4030-madc driver Various minor improvements and fixes in several drivers -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJZBlqUAAoJEMsfJm/On5mBHigP/jlJ9DNCADg/oK2lqyHugfDH TPk37lBCGYKVVuE4uScpojU9Q/T9aSWtsQPRVJa8FzdVCuPpSfdq5zSOUdv19auR Q/45726UM7scjY+DFxt5Guj+ZR60qL/B9khCq2dCKfDe2eL3plWEyMWsYSyTt1ml EG+w1BbmmsYLLmUIRqy+otn9RqtMZPr0ZwvsBG4y8NCNJYOXDvevhzzp6nkXkupg Gx9SL7XgY9FViKTOubLX+/DANeILDhm5DV7vOL+E28fDHNZPSwQ6pWSIcxUpYFse WPaZAbpMbx39hownGSwt7jTU1m9MjjsTZ4TTVuw+jBymEQiuG8Q9d22kyc3rpiju eb9NR75Qidl5gEaPWhps9iWlabtPN+r90mtIwL4YgjrPeY+nDRRPPvaw3zIZI+iz hx2bMXAvscHQparAQ5NOhaBcsQ12ZL/FNOvTr+rkcqVoGk/psmxJOJOHMZfHk97e B78RdO/e0seJQYpniWPGG+xzbddT6xqMih+xBOaPRlxeAOcvG0M+gz9WhDNq3Dyp MDw+xM0YYhq0OKrZfCU6hi7ZII5TERioPWDkihrZ7/+5/m151oO3YbqpJStqSq04 Q29ASUn2HjI0xxI7XFg8+MlMbhWI2rCNe/p33/OsUlgYYsCFLqnBXjCmuJ45w+0P USEpljqFei6xwjX2B6br =sbJB -----END PGP SIGNATURE----- Merge tag 'hwmon-for-linus-v4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging Pull hwmon updates from Guenter Roeck: - removed twl4030-madc driver - added ASPEED PWM/fan driver - various minor improvements and fixes in several drivers * tag 'hwmon-for-linus-v4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (36 commits) hwmon: (twl4030-madc) drop driver hwmon: (tmp103) Use SIMPLE_DEV_PM_OPS helper macro hwmon: (adt7475) set start bit in probe hwmon: (ina209) Handled signed registers hwmon: (lm87) Add OF device ID table hwmon: (lm87) Remove unused I2C devices driver_data drivers: hwmon: Support for ASPEED PWM/Fan tach Documentation: dt-bindings: Document bindings for ASPEED AST2400/AST2500 PWM and Fan tach controller device driver hwmon: (lm87) Allow channel data to be set from dts file Documentation: dtb: lm87: Add hwmon binding documentation hwmon: (ads7828) Accept optional parameters from device tree hwmon: (dell-smm) Add Dell XPS 15 9560 into DMI list hwmon: Constify str parameter of hwmon_ops->read_string dt: Add vendor prefix for Sensirion hwmon: (tmp421) Add OF device ID table hwmon: (tmp103) Add OF device ID table hwmon: (tmp102) Add OF device ID table hwmon: (stts751) Add OF device ID table hwmon: (ucd9200) Add OF device ID table hwmon: (ucd9000) Add OF device ID table ...
This commit is contained in:
commit
cdbfbba98c
|
@ -0,0 +1,25 @@
|
|||
ads7828 properties
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be one of
|
||||
ti,ads7828
|
||||
ti,ads7830
|
||||
- reg: I2C address
|
||||
|
||||
Optional properties:
|
||||
|
||||
- ti,differential-input
|
||||
Set to use the device in differential mode.
|
||||
- vref-supply
|
||||
The external reference on the device is set to this regulators output. If it
|
||||
does not exists the internal reference will be used and output by the ads78xx
|
||||
on the "external vref" pin.
|
||||
|
||||
Example ADS7828 node:
|
||||
|
||||
ads7828: ads@48 {
|
||||
comatible = "ti,ads7828";
|
||||
reg = <0x48>;
|
||||
vref-supply = <&vref>;
|
||||
ti,differential-input;
|
||||
};
|
|
@ -0,0 +1,68 @@
|
|||
ASPEED AST2400/AST2500 PWM and Fan Tacho controller device driver
|
||||
|
||||
The ASPEED PWM controller can support upto 8 PWM outputs. The ASPEED Fan Tacho
|
||||
controller can support upto 16 Fan tachometer inputs.
|
||||
|
||||
There can be upto 8 fans supported. Each fan can have one PWM output and
|
||||
one/two Fan tach inputs.
|
||||
|
||||
Required properties for pwm-tacho node:
|
||||
- #address-cells : should be 1.
|
||||
|
||||
- #size-cells : should be 1.
|
||||
|
||||
- reg : address and length of the register set for the device.
|
||||
|
||||
- pinctrl-names : a pinctrl state named "default" must be defined.
|
||||
|
||||
- pinctrl-0 : phandle referencing pin configuration of the PWM ports.
|
||||
|
||||
- compatible : should be "aspeed,ast2400-pwm-tacho" for AST2400 and
|
||||
"aspeed,ast2500-pwm-tacho" for AST2500.
|
||||
|
||||
- clocks : a fixed clock providing input clock frequency(PWM
|
||||
and Fan Tach clock)
|
||||
|
||||
fan subnode format:
|
||||
===================
|
||||
Under fan subnode there can upto 8 child nodes, with each child node
|
||||
representing a fan. If there are 8 fans each fan can have one PWM port and
|
||||
one/two Fan tach inputs.
|
||||
|
||||
Required properties for each child node:
|
||||
- reg : should specify PWM source port.
|
||||
integer value in the range 0 to 7 with 0 indicating PWM port A and
|
||||
7 indicating PWM port H.
|
||||
|
||||
- aspeed,fan-tach-ch : should specify the Fan tach input channel.
|
||||
integer value in the range 0 through 15, with 0 indicating
|
||||
Fan tach channel 0 and 15 indicating Fan tach channel 15.
|
||||
Atleast one Fan tach input channel is required.
|
||||
|
||||
Examples:
|
||||
|
||||
pwm_tacho_fixed_clk: fixedclk {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <24000000>;
|
||||
};
|
||||
|
||||
pwm_tacho: pwmtachocontroller@1e786000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
reg = <0x1E786000 0x1000>;
|
||||
compatible = "aspeed,ast2500-pwm-tacho";
|
||||
clocks = <&pwm_tacho_fixed_clk>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default>;
|
||||
|
||||
fan@0 {
|
||||
reg = <0x00>;
|
||||
aspeed,fan-tach-ch = /bits/ 8 <0x00>;
|
||||
};
|
||||
|
||||
fan@1 {
|
||||
reg = <0x01>;
|
||||
aspeed,fan-tach-ch = /bits/ 8 <0x01 0x02>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,30 @@
|
|||
*LM87 hwmon sensor.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be
|
||||
"ti,lm87"
|
||||
|
||||
- reg: I2C address
|
||||
|
||||
optional properties:
|
||||
- has-temp3: This configures pins 18 and 19 to be used as a second
|
||||
remote temperature sensing channel. By default the pins
|
||||
are configured as voltage input pins in0 and in5.
|
||||
|
||||
- has-in6: When set, pin 5 is configured to be used as voltage input
|
||||
in6. Otherwise the pin is set as FAN1 input.
|
||||
|
||||
- has-in7: When set, pin 6 is configured to be used as voltage input
|
||||
in7. Otherwise the pin is set as FAN2 input.
|
||||
|
||||
- vcc-supply: a Phandle for the regulator supplying power, can be
|
||||
cofigured to measure 5.0V power supply. Default is 3.3V.
|
||||
|
||||
Example:
|
||||
|
||||
lm87@2e {
|
||||
compatible = "ti,lm87";
|
||||
reg = <0x2e>;
|
||||
has-temp3;
|
||||
vcc-supply = <®_5v0>;
|
||||
};
|
|
@ -265,6 +265,7 @@ sbs Smart Battery System
|
|||
schindler Schindler
|
||||
seagate Seagate Technology PLC
|
||||
semtech Semtech Corporation
|
||||
sensirion Sensirion AG
|
||||
sgx SGX Sensortech
|
||||
sharp Sharp Corporation
|
||||
si-en Si-En Technology Ltd.
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
Kernel driver aspeed-pwm-tacho
|
||||
==============================
|
||||
|
||||
Supported chips:
|
||||
ASPEED AST2400/2500
|
||||
|
||||
Authors:
|
||||
<jaghu@google.com>
|
||||
|
||||
Description:
|
||||
------------
|
||||
This driver implements support for ASPEED AST2400/2500 PWM and Fan Tacho
|
||||
controller. The PWM controller supports upto 8 PWM outputs. The Fan tacho
|
||||
controller supports up to 16 tachometer inputs.
|
||||
|
||||
The driver provides the following sensor accesses in sysfs:
|
||||
|
||||
fanX_input ro provide current fan rotation value in RPM as reported
|
||||
by the fan to the device.
|
||||
|
||||
pwmX rw get or set PWM fan control value. This is an integer
|
||||
value between 0(off) and 255(full speed).
|
|
@ -2,7 +2,7 @@ Kernel driver tc654
|
|||
===================
|
||||
|
||||
Supported chips:
|
||||
* Microship TC654 and TC655
|
||||
* Microchip TC654 and TC655
|
||||
Prefix: 'tc654'
|
||||
Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/20001734C.pdf
|
||||
|
||||
|
|
|
@ -341,6 +341,15 @@ config SENSORS_ASB100
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called asb100.
|
||||
|
||||
config SENSORS_ASPEED
|
||||
tristate "ASPEED AST2400/AST2500 PWM and Fan tach driver"
|
||||
help
|
||||
This driver provides support for ASPEED AST2400/AST2500 PWM
|
||||
and Fan Tacho controllers.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called aspeed_pwm_tacho.
|
||||
|
||||
config SENSORS_ATXP1
|
||||
tristate "Attansic ATXP1 VID controller"
|
||||
depends on I2C
|
||||
|
@ -1643,16 +1652,6 @@ config SENSORS_TMP421
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called tmp421.
|
||||
|
||||
config SENSORS_TWL4030_MADC
|
||||
tristate "Texas Instruments TWL4030 MADC Hwmon"
|
||||
depends on TWL4030_MADC
|
||||
help
|
||||
If you say yes here you get hwmon support for triton
|
||||
TWL4030-MADC.
|
||||
|
||||
This driver can also be built as a module. If so it will be called
|
||||
twl4030-madc-hwmon.
|
||||
|
||||
config SENSORS_VEXPRESS
|
||||
tristate "Versatile Express"
|
||||
depends on VEXPRESS_CONFIG
|
||||
|
|
|
@ -46,6 +46,7 @@ obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o
|
|||
obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
|
||||
obj-$(CONFIG_SENSORS_ARM_SCPI) += scpi-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
|
||||
obj-$(CONFIG_SENSORS_ASPEED) += aspeed-pwm-tacho.o
|
||||
obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
|
||||
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
|
||||
obj-$(CONFIG_SENSORS_DA9052_ADC)+= da9052-hwmon.o
|
||||
|
@ -157,7 +158,6 @@ obj-$(CONFIG_SENSORS_TMP103) += tmp103.o
|
|||
obj-$(CONFIG_SENSORS_TMP108) += tmp108.o
|
||||
obj-$(CONFIG_SENSORS_TMP401) += tmp401.o
|
||||
obj-$(CONFIG_SENSORS_TMP421) += tmp421.o
|
||||
obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_VEXPRESS) += vexpress-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
|
||||
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
|
||||
|
|
|
@ -217,9 +217,16 @@ static const struct i2c_device_id ad7414_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ad7414_id);
|
||||
|
||||
static const struct of_device_id ad7414_of_match[] = {
|
||||
{ .compatible = "ad,ad7414" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ad7414_of_match);
|
||||
|
||||
static struct i2c_driver ad7414_driver = {
|
||||
.driver = {
|
||||
.name = "ad7414",
|
||||
.of_match_table = of_match_ptr(ad7414_of_match),
|
||||
},
|
||||
.probe = ad7414_probe,
|
||||
.id_table = ad7414_id,
|
||||
|
|
|
@ -546,10 +546,17 @@ static const struct i2c_device_id adc128_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adc128_id);
|
||||
|
||||
static const struct of_device_id adc128_of_match[] = {
|
||||
{ .compatible = "ti,adc128d818" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, adc128_of_match);
|
||||
|
||||
static struct i2c_driver adc128_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "adc128d818",
|
||||
.of_match_table = of_match_ptr(adc128_of_match),
|
||||
},
|
||||
.probe = adc128_probe,
|
||||
.remove = adc128_remove,
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/i2c/ads1015.h>
|
||||
|
@ -268,7 +269,12 @@ static int ads1015_probe(struct i2c_client *client,
|
|||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
data->id = id->driver_data;
|
||||
|
||||
if (client->dev.of_node)
|
||||
data->id = (enum ads1015_chips)
|
||||
of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->id = id->driver_data;
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
|
@ -303,9 +309,23 @@ static const struct i2c_device_id ads1015_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ads1015_id);
|
||||
|
||||
static const struct of_device_id ads1015_of_match[] = {
|
||||
{
|
||||
.compatible = "ti,ads1015",
|
||||
.data = (void *)ads1015
|
||||
},
|
||||
{
|
||||
.compatible = "ti,ads1115",
|
||||
.data = (void *)ads1115
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ads1015_of_match);
|
||||
|
||||
static struct i2c_driver ads1015_driver = {
|
||||
.driver = {
|
||||
.name = "ads1015",
|
||||
.of_match_table = of_match_ptr(ads1015_of_match),
|
||||
},
|
||||
.probe = ads1015_probe,
|
||||
.remove = ads1015_remove,
|
||||
|
|
|
@ -31,9 +31,11 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_data/ads7828.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
/* The ADS7828 registers */
|
||||
#define ADS7828_CMD_SD_SE 0x80 /* Single ended inputs */
|
||||
|
@ -118,9 +120,12 @@ static int ads7828_probe(struct i2c_client *client,
|
|||
struct ads7828_data *data;
|
||||
struct device *hwmon_dev;
|
||||
unsigned int vref_mv = ADS7828_INT_VREF_MV;
|
||||
unsigned int vref_uv;
|
||||
bool diff_input = false;
|
||||
bool ext_vref = false;
|
||||
unsigned int regval;
|
||||
enum ads7828_chips chip;
|
||||
struct regulator *reg;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL);
|
||||
if (!data)
|
||||
|
@ -131,14 +136,32 @@ static int ads7828_probe(struct i2c_client *client,
|
|||
ext_vref = pdata->ext_vref;
|
||||
if (ext_vref && pdata->vref_mv)
|
||||
vref_mv = pdata->vref_mv;
|
||||
} else if (dev->of_node) {
|
||||
diff_input = of_property_read_bool(dev->of_node,
|
||||
"ti,differential-input");
|
||||
reg = devm_regulator_get_optional(dev, "vref");
|
||||
if (!IS_ERR(reg)) {
|
||||
vref_uv = regulator_get_voltage(reg);
|
||||
vref_mv = DIV_ROUND_CLOSEST(vref_uv, 1000);
|
||||
if (vref_mv < ADS7828_EXT_VREF_MV_MIN ||
|
||||
vref_mv > ADS7828_EXT_VREF_MV_MAX)
|
||||
return -EINVAL;
|
||||
ext_vref = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (client->dev.of_node)
|
||||
chip = (enum ads7828_chips)
|
||||
of_device_get_match_data(&client->dev);
|
||||
else
|
||||
chip = id->driver_data;
|
||||
|
||||
/* Bound Vref with min/max values */
|
||||
vref_mv = clamp_val(vref_mv, ADS7828_EXT_VREF_MV_MIN,
|
||||
ADS7828_EXT_VREF_MV_MAX);
|
||||
|
||||
/* ADS7828 uses 12-bit samples, while ADS7830 is 8-bit */
|
||||
if (id->driver_data == ads7828) {
|
||||
if (chip == ads7828) {
|
||||
data->lsb_resol = DIV_ROUND_CLOSEST(vref_mv * 1000, 4096);
|
||||
data->regmap = devm_regmap_init_i2c(client,
|
||||
&ads2828_regmap_config);
|
||||
|
@ -177,9 +200,23 @@ static const struct i2c_device_id ads7828_device_ids[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ads7828_device_ids);
|
||||
|
||||
static const struct of_device_id ads7828_of_match[] = {
|
||||
{
|
||||
.compatible = "ti,ads7828",
|
||||
.data = (void *)ads7828
|
||||
},
|
||||
{
|
||||
.compatible = "ti,ads7830",
|
||||
.data = (void *)ads7830
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ads7828_of_match);
|
||||
|
||||
static struct i2c_driver ads7828_driver = {
|
||||
.driver = {
|
||||
.name = "ads7828",
|
||||
.of_match_table = of_match_ptr(ads7828_of_match),
|
||||
},
|
||||
|
||||
.id_table = ads7828_device_ids,
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
|
@ -58,6 +59,8 @@
|
|||
#define REG_VENDID 0x3E
|
||||
#define REG_DEVID2 0x3F
|
||||
|
||||
#define REG_CONFIG1 0x40
|
||||
|
||||
#define REG_STATUS1 0x41
|
||||
#define REG_STATUS2 0x42
|
||||
|
||||
|
@ -161,6 +164,27 @@ static const struct i2c_device_id adt7475_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, adt7475_id);
|
||||
|
||||
static const struct of_device_id adt7475_of_match[] = {
|
||||
{
|
||||
.compatible = "adi,adt7473",
|
||||
.data = (void *)adt7473
|
||||
},
|
||||
{
|
||||
.compatible = "adi,adt7475",
|
||||
.data = (void *)adt7475
|
||||
},
|
||||
{
|
||||
.compatible = "adi,adt7476",
|
||||
.data = (void *)adt7476
|
||||
},
|
||||
{
|
||||
.compatible = "adi,adt7490",
|
||||
.data = (void *)adt7490
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, adt7475_of_match);
|
||||
|
||||
struct adt7475_data {
|
||||
struct device *hwmon_dev;
|
||||
struct mutex lock;
|
||||
|
@ -1250,6 +1274,7 @@ static void adt7475_remove_files(struct i2c_client *client,
|
|||
static int adt7475_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
enum chips chip;
|
||||
static const char * const names[] = {
|
||||
[adt7473] = "ADT7473",
|
||||
[adt7475] = "ADT7475",
|
||||
|
@ -1268,8 +1293,13 @@ static int adt7475_probe(struct i2c_client *client,
|
|||
mutex_init(&data->lock);
|
||||
i2c_set_clientdata(client, data);
|
||||
|
||||
if (client->dev.of_node)
|
||||
chip = (enum chips)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
chip = id->driver_data;
|
||||
|
||||
/* Initialize device-specific values */
|
||||
switch (id->driver_data) {
|
||||
switch (chip) {
|
||||
case adt7476:
|
||||
data->has_voltage = 0x0e; /* in1 to in3 */
|
||||
revision = adt7475_read(REG_DEVID2) & 0x07;
|
||||
|
@ -1343,6 +1373,17 @@ static int adt7475_probe(struct i2c_client *client,
|
|||
for (i = 0; i < ADT7475_PWM_COUNT; i++)
|
||||
adt7475_read_pwm(client, i);
|
||||
|
||||
/* Start monitoring */
|
||||
switch (chip) {
|
||||
case adt7475:
|
||||
case adt7476:
|
||||
i2c_smbus_write_byte_data(client, REG_CONFIG1,
|
||||
adt7475_read(REG_CONFIG1) | 0x01);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(&client->dev.kobj, &adt7475_attr_group);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -1428,6 +1469,7 @@ static struct i2c_driver adt7475_driver = {
|
|||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "adt7475",
|
||||
.of_match_table = of_match_ptr(adt7475_of_match),
|
||||
},
|
||||
.probe = adt7475_probe,
|
||||
.remove = adt7475_remove,
|
||||
|
|
|
@ -0,0 +1,835 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Google, Inc
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 or later as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/* ASPEED PWM & FAN Tach Register Definition */
|
||||
#define ASPEED_PTCR_CTRL 0x00
|
||||
#define ASPEED_PTCR_CLK_CTRL 0x04
|
||||
#define ASPEED_PTCR_DUTY0_CTRL 0x08
|
||||
#define ASPEED_PTCR_DUTY1_CTRL 0x0c
|
||||
#define ASPEED_PTCR_TYPEM_CTRL 0x10
|
||||
#define ASPEED_PTCR_TYPEM_CTRL1 0x14
|
||||
#define ASPEED_PTCR_TYPEN_CTRL 0x18
|
||||
#define ASPEED_PTCR_TYPEN_CTRL1 0x1c
|
||||
#define ASPEED_PTCR_TACH_SOURCE 0x20
|
||||
#define ASPEED_PTCR_TRIGGER 0x28
|
||||
#define ASPEED_PTCR_RESULT 0x2c
|
||||
#define ASPEED_PTCR_INTR_CTRL 0x30
|
||||
#define ASPEED_PTCR_INTR_STS 0x34
|
||||
#define ASPEED_PTCR_TYPEM_LIMIT 0x38
|
||||
#define ASPEED_PTCR_TYPEN_LIMIT 0x3C
|
||||
#define ASPEED_PTCR_CTRL_EXT 0x40
|
||||
#define ASPEED_PTCR_CLK_CTRL_EXT 0x44
|
||||
#define ASPEED_PTCR_DUTY2_CTRL 0x48
|
||||
#define ASPEED_PTCR_DUTY3_CTRL 0x4c
|
||||
#define ASPEED_PTCR_TYPEO_CTRL 0x50
|
||||
#define ASPEED_PTCR_TYPEO_CTRL1 0x54
|
||||
#define ASPEED_PTCR_TACH_SOURCE_EXT 0x60
|
||||
#define ASPEED_PTCR_TYPEO_LIMIT 0x78
|
||||
|
||||
/* ASPEED_PTCR_CTRL : 0x00 - General Control Register */
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART1 15
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART2 6
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMD_TYPE_MASK (BIT(7) | BIT(15))
|
||||
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART1 14
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART2 5
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMC_TYPE_MASK (BIT(6) | BIT(14))
|
||||
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART1 13
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART2 4
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMB_TYPE_MASK (BIT(5) | BIT(13))
|
||||
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART1 12
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART2 3
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMA_TYPE_MASK (BIT(4) | BIT(12))
|
||||
|
||||
#define ASPEED_PTCR_CTRL_FAN_NUM_EN(x) BIT(16 + (x))
|
||||
|
||||
#define ASPEED_PTCR_CTRL_PWMD_EN BIT(11)
|
||||
#define ASPEED_PTCR_CTRL_PWMC_EN BIT(10)
|
||||
#define ASPEED_PTCR_CTRL_PWMB_EN BIT(9)
|
||||
#define ASPEED_PTCR_CTRL_PWMA_EN BIT(8)
|
||||
|
||||
#define ASPEED_PTCR_CTRL_CLK_SRC BIT(1)
|
||||
#define ASPEED_PTCR_CTRL_CLK_EN BIT(0)
|
||||
|
||||
/* ASPEED_PTCR_CLK_CTRL : 0x04 - Clock Control Register */
|
||||
/* TYPE N */
|
||||
#define ASPEED_PTCR_CLK_CTRL_TYPEN_MASK GENMASK(31, 16)
|
||||
#define ASPEED_PTCR_CLK_CTRL_TYPEN_UNIT 24
|
||||
#define ASPEED_PTCR_CLK_CTRL_TYPEN_H 20
|
||||
#define ASPEED_PTCR_CLK_CTRL_TYPEN_L 16
|
||||
/* TYPE M */
|
||||
#define ASPEED_PTCR_CLK_CTRL_TYPEM_MASK GENMASK(15, 0)
|
||||
#define ASPEED_PTCR_CLK_CTRL_TYPEM_UNIT 8
|
||||
#define ASPEED_PTCR_CLK_CTRL_TYPEM_H 4
|
||||
#define ASPEED_PTCR_CLK_CTRL_TYPEM_L 0
|
||||
|
||||
/*
|
||||
* ASPEED_PTCR_DUTY_CTRL/1/2/3 : 0x08/0x0C/0x48/0x4C - PWM-FAN duty control
|
||||
* 0/1/2/3 register
|
||||
*/
|
||||
#define DUTY_CTRL_PWM2_FALL_POINT 24
|
||||
#define DUTY_CTRL_PWM2_RISE_POINT 16
|
||||
#define DUTY_CTRL_PWM2_RISE_FALL_MASK GENMASK(31, 16)
|
||||
#define DUTY_CTRL_PWM1_FALL_POINT 8
|
||||
#define DUTY_CTRL_PWM1_RISE_POINT 0
|
||||
#define DUTY_CTRL_PWM1_RISE_FALL_MASK GENMASK(15, 0)
|
||||
|
||||
/* ASPEED_PTCR_TYPEM_CTRL : 0x10/0x18/0x50 - Type M/N/O Ctrl 0 Register */
|
||||
#define TYPE_CTRL_FAN_MASK (GENMASK(5, 1) | GENMASK(31, 16))
|
||||
#define TYPE_CTRL_FAN1_MASK GENMASK(31, 0)
|
||||
#define TYPE_CTRL_FAN_PERIOD 16
|
||||
#define TYPE_CTRL_FAN_MODE 4
|
||||
#define TYPE_CTRL_FAN_DIVISION 1
|
||||
#define TYPE_CTRL_FAN_TYPE_EN 1
|
||||
|
||||
/* ASPEED_PTCR_TACH_SOURCE : 0x20/0x60 - Tach Source Register */
|
||||
/* bit [0,1] at 0x20, bit [2] at 0x60 */
|
||||
#define TACH_PWM_SOURCE_BIT01(x) ((x) * 2)
|
||||
#define TACH_PWM_SOURCE_BIT2(x) ((x) * 2)
|
||||
#define TACH_PWM_SOURCE_MASK_BIT01(x) (0x3 << ((x) * 2))
|
||||
#define TACH_PWM_SOURCE_MASK_BIT2(x) BIT((x) * 2)
|
||||
|
||||
/* ASPEED_PTCR_RESULT : 0x2c - Result Register */
|
||||
#define RESULT_STATUS_MASK BIT(31)
|
||||
#define RESULT_VALUE_MASK 0xfffff
|
||||
|
||||
/* ASPEED_PTCR_CTRL_EXT : 0x40 - General Control Extension #1 Register */
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART1 15
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART2 6
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMH_TYPE_MASK (BIT(7) | BIT(15))
|
||||
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART1 14
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART2 5
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMG_TYPE_MASK (BIT(6) | BIT(14))
|
||||
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART1 13
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART2 4
|
||||
#define ASPEED_PTCR_CTRL_SET_PWMF_TYPE_MASK (BIT(5) | BIT(13))
|
||||
|
||||
#define ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART1 12
|
||||
#define ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART2 3
|
||||
#define ASPEED_PTCR_CTRL_SET_PWME_TYPE_MASK (BIT(4) | BIT(12))
|
||||
|
||||
#define ASPEED_PTCR_CTRL_PWMH_EN BIT(11)
|
||||
#define ASPEED_PTCR_CTRL_PWMG_EN BIT(10)
|
||||
#define ASPEED_PTCR_CTRL_PWMF_EN BIT(9)
|
||||
#define ASPEED_PTCR_CTRL_PWME_EN BIT(8)
|
||||
|
||||
/* ASPEED_PTCR_CLK_EXT_CTRL : 0x44 - Clock Control Extension #1 Register */
|
||||
/* TYPE O */
|
||||
#define ASPEED_PTCR_CLK_CTRL_TYPEO_MASK GENMASK(15, 0)
|
||||
#define ASPEED_PTCR_CLK_CTRL_TYPEO_UNIT 8
|
||||
#define ASPEED_PTCR_CLK_CTRL_TYPEO_H 4
|
||||
#define ASPEED_PTCR_CLK_CTRL_TYPEO_L 0
|
||||
|
||||
#define PWM_MAX 255
|
||||
|
||||
#define M_PWM_DIV_H 0x00
|
||||
#define M_PWM_DIV_L 0x05
|
||||
#define M_PWM_PERIOD 0x5F
|
||||
#define M_TACH_CLK_DIV 0x00
|
||||
#define M_TACH_MODE 0x00
|
||||
#define M_TACH_UNIT 0x1000
|
||||
#define INIT_FAN_CTRL 0xFF
|
||||
|
||||
struct aspeed_pwm_tacho_data {
|
||||
struct regmap *regmap;
|
||||
unsigned long clk_freq;
|
||||
bool pwm_present[8];
|
||||
bool fan_tach_present[16];
|
||||
u8 type_pwm_clock_unit[3];
|
||||
u8 type_pwm_clock_division_h[3];
|
||||
u8 type_pwm_clock_division_l[3];
|
||||
u8 type_fan_tach_clock_division[3];
|
||||
u16 type_fan_tach_unit[3];
|
||||
u8 pwm_port_type[8];
|
||||
u8 pwm_port_fan_ctrl[8];
|
||||
u8 fan_tach_ch_source[16];
|
||||
const struct attribute_group *groups[3];
|
||||
};
|
||||
|
||||
enum type { TYPEM, TYPEN, TYPEO };
|
||||
|
||||
struct type_params {
|
||||
u32 l_value;
|
||||
u32 h_value;
|
||||
u32 unit_value;
|
||||
u32 clk_ctrl_mask;
|
||||
u32 clk_ctrl_reg;
|
||||
u32 ctrl_reg;
|
||||
u32 ctrl_reg1;
|
||||
};
|
||||
|
||||
static const struct type_params type_params[] = {
|
||||
[TYPEM] = {
|
||||
.l_value = ASPEED_PTCR_CLK_CTRL_TYPEM_L,
|
||||
.h_value = ASPEED_PTCR_CLK_CTRL_TYPEM_H,
|
||||
.unit_value = ASPEED_PTCR_CLK_CTRL_TYPEM_UNIT,
|
||||
.clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEM_MASK,
|
||||
.clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL,
|
||||
.ctrl_reg = ASPEED_PTCR_TYPEM_CTRL,
|
||||
.ctrl_reg1 = ASPEED_PTCR_TYPEM_CTRL1,
|
||||
},
|
||||
[TYPEN] = {
|
||||
.l_value = ASPEED_PTCR_CLK_CTRL_TYPEN_L,
|
||||
.h_value = ASPEED_PTCR_CLK_CTRL_TYPEN_H,
|
||||
.unit_value = ASPEED_PTCR_CLK_CTRL_TYPEN_UNIT,
|
||||
.clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEN_MASK,
|
||||
.clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL,
|
||||
.ctrl_reg = ASPEED_PTCR_TYPEN_CTRL,
|
||||
.ctrl_reg1 = ASPEED_PTCR_TYPEN_CTRL1,
|
||||
},
|
||||
[TYPEO] = {
|
||||
.l_value = ASPEED_PTCR_CLK_CTRL_TYPEO_L,
|
||||
.h_value = ASPEED_PTCR_CLK_CTRL_TYPEO_H,
|
||||
.unit_value = ASPEED_PTCR_CLK_CTRL_TYPEO_UNIT,
|
||||
.clk_ctrl_mask = ASPEED_PTCR_CLK_CTRL_TYPEO_MASK,
|
||||
.clk_ctrl_reg = ASPEED_PTCR_CLK_CTRL_EXT,
|
||||
.ctrl_reg = ASPEED_PTCR_TYPEO_CTRL,
|
||||
.ctrl_reg1 = ASPEED_PTCR_TYPEO_CTRL1,
|
||||
}
|
||||
};
|
||||
|
||||
enum pwm_port { PWMA, PWMB, PWMC, PWMD, PWME, PWMF, PWMG, PWMH };
|
||||
|
||||
struct pwm_port_params {
|
||||
u32 pwm_en;
|
||||
u32 ctrl_reg;
|
||||
u32 type_part1;
|
||||
u32 type_part2;
|
||||
u32 type_mask;
|
||||
u32 duty_ctrl_rise_point;
|
||||
u32 duty_ctrl_fall_point;
|
||||
u32 duty_ctrl_reg;
|
||||
u32 duty_ctrl_rise_fall_mask;
|
||||
};
|
||||
|
||||
static const struct pwm_port_params pwm_port_params[] = {
|
||||
[PWMA] = {
|
||||
.pwm_en = ASPEED_PTCR_CTRL_PWMA_EN,
|
||||
.ctrl_reg = ASPEED_PTCR_CTRL,
|
||||
.type_part1 = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART1,
|
||||
.type_part2 = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_PART2,
|
||||
.type_mask = ASPEED_PTCR_CTRL_SET_PWMA_TYPE_MASK,
|
||||
.duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT,
|
||||
.duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT,
|
||||
.duty_ctrl_reg = ASPEED_PTCR_DUTY0_CTRL,
|
||||
.duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK,
|
||||
},
|
||||
[PWMB] = {
|
||||
.pwm_en = ASPEED_PTCR_CTRL_PWMB_EN,
|
||||
.ctrl_reg = ASPEED_PTCR_CTRL,
|
||||
.type_part1 = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART1,
|
||||
.type_part2 = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_PART2,
|
||||
.type_mask = ASPEED_PTCR_CTRL_SET_PWMB_TYPE_MASK,
|
||||
.duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT,
|
||||
.duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT,
|
||||
.duty_ctrl_reg = ASPEED_PTCR_DUTY0_CTRL,
|
||||
.duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK,
|
||||
},
|
||||
[PWMC] = {
|
||||
.pwm_en = ASPEED_PTCR_CTRL_PWMC_EN,
|
||||
.ctrl_reg = ASPEED_PTCR_CTRL,
|
||||
.type_part1 = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART1,
|
||||
.type_part2 = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_PART2,
|
||||
.type_mask = ASPEED_PTCR_CTRL_SET_PWMC_TYPE_MASK,
|
||||
.duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT,
|
||||
.duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT,
|
||||
.duty_ctrl_reg = ASPEED_PTCR_DUTY1_CTRL,
|
||||
.duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK,
|
||||
},
|
||||
[PWMD] = {
|
||||
.pwm_en = ASPEED_PTCR_CTRL_PWMD_EN,
|
||||
.ctrl_reg = ASPEED_PTCR_CTRL,
|
||||
.type_part1 = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART1,
|
||||
.type_part2 = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_PART2,
|
||||
.type_mask = ASPEED_PTCR_CTRL_SET_PWMD_TYPE_MASK,
|
||||
.duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT,
|
||||
.duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT,
|
||||
.duty_ctrl_reg = ASPEED_PTCR_DUTY1_CTRL,
|
||||
.duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK,
|
||||
},
|
||||
[PWME] = {
|
||||
.pwm_en = ASPEED_PTCR_CTRL_PWME_EN,
|
||||
.ctrl_reg = ASPEED_PTCR_CTRL_EXT,
|
||||
.type_part1 = ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART1,
|
||||
.type_part2 = ASPEED_PTCR_CTRL_SET_PWME_TYPE_PART2,
|
||||
.type_mask = ASPEED_PTCR_CTRL_SET_PWME_TYPE_MASK,
|
||||
.duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT,
|
||||
.duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT,
|
||||
.duty_ctrl_reg = ASPEED_PTCR_DUTY2_CTRL,
|
||||
.duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK,
|
||||
},
|
||||
[PWMF] = {
|
||||
.pwm_en = ASPEED_PTCR_CTRL_PWMF_EN,
|
||||
.ctrl_reg = ASPEED_PTCR_CTRL_EXT,
|
||||
.type_part1 = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART1,
|
||||
.type_part2 = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_PART2,
|
||||
.type_mask = ASPEED_PTCR_CTRL_SET_PWMF_TYPE_MASK,
|
||||
.duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT,
|
||||
.duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT,
|
||||
.duty_ctrl_reg = ASPEED_PTCR_DUTY2_CTRL,
|
||||
.duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK,
|
||||
},
|
||||
[PWMG] = {
|
||||
.pwm_en = ASPEED_PTCR_CTRL_PWMG_EN,
|
||||
.ctrl_reg = ASPEED_PTCR_CTRL_EXT,
|
||||
.type_part1 = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART1,
|
||||
.type_part2 = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_PART2,
|
||||
.type_mask = ASPEED_PTCR_CTRL_SET_PWMG_TYPE_MASK,
|
||||
.duty_ctrl_rise_point = DUTY_CTRL_PWM1_RISE_POINT,
|
||||
.duty_ctrl_fall_point = DUTY_CTRL_PWM1_FALL_POINT,
|
||||
.duty_ctrl_reg = ASPEED_PTCR_DUTY3_CTRL,
|
||||
.duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM1_RISE_FALL_MASK,
|
||||
},
|
||||
[PWMH] = {
|
||||
.pwm_en = ASPEED_PTCR_CTRL_PWMH_EN,
|
||||
.ctrl_reg = ASPEED_PTCR_CTRL_EXT,
|
||||
.type_part1 = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART1,
|
||||
.type_part2 = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_PART2,
|
||||
.type_mask = ASPEED_PTCR_CTRL_SET_PWMH_TYPE_MASK,
|
||||
.duty_ctrl_rise_point = DUTY_CTRL_PWM2_RISE_POINT,
|
||||
.duty_ctrl_fall_point = DUTY_CTRL_PWM2_FALL_POINT,
|
||||
.duty_ctrl_reg = ASPEED_PTCR_DUTY3_CTRL,
|
||||
.duty_ctrl_rise_fall_mask = DUTY_CTRL_PWM2_RISE_FALL_MASK,
|
||||
}
|
||||
};
|
||||
|
||||
static int regmap_aspeed_pwm_tacho_reg_write(void *context, unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
void __iomem *regs = (void __iomem *)context;
|
||||
|
||||
writel(val, regs + reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int regmap_aspeed_pwm_tacho_reg_read(void *context, unsigned int reg,
|
||||
unsigned int *val)
|
||||
{
|
||||
void __iomem *regs = (void __iomem *)context;
|
||||
|
||||
*val = readl(regs + reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct regmap_config aspeed_pwm_tacho_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.max_register = ASPEED_PTCR_TYPEO_LIMIT,
|
||||
.reg_write = regmap_aspeed_pwm_tacho_reg_write,
|
||||
.reg_read = regmap_aspeed_pwm_tacho_reg_read,
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
static void aspeed_set_clock_enable(struct regmap *regmap, bool val)
|
||||
{
|
||||
regmap_update_bits(regmap, ASPEED_PTCR_CTRL,
|
||||
ASPEED_PTCR_CTRL_CLK_EN,
|
||||
val ? ASPEED_PTCR_CTRL_CLK_EN : 0);
|
||||
}
|
||||
|
||||
static void aspeed_set_clock_source(struct regmap *regmap, int val)
|
||||
{
|
||||
regmap_update_bits(regmap, ASPEED_PTCR_CTRL,
|
||||
ASPEED_PTCR_CTRL_CLK_SRC,
|
||||
val ? ASPEED_PTCR_CTRL_CLK_SRC : 0);
|
||||
}
|
||||
|
||||
static void aspeed_set_pwm_clock_values(struct regmap *regmap, u8 type,
|
||||
u8 div_high, u8 div_low, u8 unit)
|
||||
{
|
||||
u32 reg_value = ((div_high << type_params[type].h_value) |
|
||||
(div_low << type_params[type].l_value) |
|
||||
(unit << type_params[type].unit_value));
|
||||
|
||||
regmap_update_bits(regmap, type_params[type].clk_ctrl_reg,
|
||||
type_params[type].clk_ctrl_mask, reg_value);
|
||||
}
|
||||
|
||||
static void aspeed_set_pwm_port_enable(struct regmap *regmap, u8 pwm_port,
|
||||
bool enable)
|
||||
{
|
||||
regmap_update_bits(regmap, pwm_port_params[pwm_port].ctrl_reg,
|
||||
pwm_port_params[pwm_port].pwm_en,
|
||||
enable ? pwm_port_params[pwm_port].pwm_en : 0);
|
||||
}
|
||||
|
||||
static void aspeed_set_pwm_port_type(struct regmap *regmap,
|
||||
u8 pwm_port, u8 type)
|
||||
{
|
||||
u32 reg_value = (type & 0x1) << pwm_port_params[pwm_port].type_part1;
|
||||
|
||||
reg_value |= (type & 0x2) << pwm_port_params[pwm_port].type_part2;
|
||||
|
||||
regmap_update_bits(regmap, pwm_port_params[pwm_port].ctrl_reg,
|
||||
pwm_port_params[pwm_port].type_mask, reg_value);
|
||||
}
|
||||
|
||||
static void aspeed_set_pwm_port_duty_rising_falling(struct regmap *regmap,
|
||||
u8 pwm_port, u8 rising,
|
||||
u8 falling)
|
||||
{
|
||||
u32 reg_value = (rising <<
|
||||
pwm_port_params[pwm_port].duty_ctrl_rise_point);
|
||||
reg_value |= (falling <<
|
||||
pwm_port_params[pwm_port].duty_ctrl_fall_point);
|
||||
|
||||
regmap_update_bits(regmap, pwm_port_params[pwm_port].duty_ctrl_reg,
|
||||
pwm_port_params[pwm_port].duty_ctrl_rise_fall_mask,
|
||||
reg_value);
|
||||
}
|
||||
|
||||
static void aspeed_set_tacho_type_enable(struct regmap *regmap, u8 type,
|
||||
bool enable)
|
||||
{
|
||||
regmap_update_bits(regmap, type_params[type].ctrl_reg,
|
||||
TYPE_CTRL_FAN_TYPE_EN,
|
||||
enable ? TYPE_CTRL_FAN_TYPE_EN : 0);
|
||||
}
|
||||
|
||||
static void aspeed_set_tacho_type_values(struct regmap *regmap, u8 type,
|
||||
u8 mode, u16 unit, u8 division)
|
||||
{
|
||||
u32 reg_value = ((mode << TYPE_CTRL_FAN_MODE) |
|
||||
(unit << TYPE_CTRL_FAN_PERIOD) |
|
||||
(division << TYPE_CTRL_FAN_DIVISION));
|
||||
|
||||
regmap_update_bits(regmap, type_params[type].ctrl_reg,
|
||||
TYPE_CTRL_FAN_MASK, reg_value);
|
||||
regmap_update_bits(regmap, type_params[type].ctrl_reg1,
|
||||
TYPE_CTRL_FAN1_MASK, unit << 16);
|
||||
}
|
||||
|
||||
static void aspeed_set_fan_tach_ch_enable(struct regmap *regmap, u8 fan_tach_ch,
|
||||
bool enable)
|
||||
{
|
||||
regmap_update_bits(regmap, ASPEED_PTCR_CTRL,
|
||||
ASPEED_PTCR_CTRL_FAN_NUM_EN(fan_tach_ch),
|
||||
enable ?
|
||||
ASPEED_PTCR_CTRL_FAN_NUM_EN(fan_tach_ch) : 0);
|
||||
}
|
||||
|
||||
static void aspeed_set_fan_tach_ch_source(struct regmap *regmap, u8 fan_tach_ch,
|
||||
u8 fan_tach_ch_source)
|
||||
{
|
||||
u32 reg_value1 = ((fan_tach_ch_source & 0x3) <<
|
||||
TACH_PWM_SOURCE_BIT01(fan_tach_ch));
|
||||
u32 reg_value2 = (((fan_tach_ch_source & 0x4) >> 2) <<
|
||||
TACH_PWM_SOURCE_BIT2(fan_tach_ch));
|
||||
|
||||
regmap_update_bits(regmap, ASPEED_PTCR_TACH_SOURCE,
|
||||
TACH_PWM_SOURCE_MASK_BIT01(fan_tach_ch),
|
||||
reg_value1);
|
||||
|
||||
regmap_update_bits(regmap, ASPEED_PTCR_TACH_SOURCE_EXT,
|
||||
TACH_PWM_SOURCE_MASK_BIT2(fan_tach_ch),
|
||||
reg_value2);
|
||||
}
|
||||
|
||||
static void aspeed_set_pwm_port_fan_ctrl(struct aspeed_pwm_tacho_data *priv,
|
||||
u8 index, u8 fan_ctrl)
|
||||
{
|
||||
u16 period, dc_time_on;
|
||||
|
||||
period = priv->type_pwm_clock_unit[priv->pwm_port_type[index]];
|
||||
period += 1;
|
||||
dc_time_on = (fan_ctrl * period) / PWM_MAX;
|
||||
|
||||
if (dc_time_on == 0) {
|
||||
aspeed_set_pwm_port_enable(priv->regmap, index, false);
|
||||
} else {
|
||||
if (dc_time_on == period)
|
||||
dc_time_on = 0;
|
||||
|
||||
aspeed_set_pwm_port_duty_rising_falling(priv->regmap, index, 0,
|
||||
dc_time_on);
|
||||
aspeed_set_pwm_port_enable(priv->regmap, index, true);
|
||||
}
|
||||
}
|
||||
|
||||
static u32 aspeed_get_fan_tach_ch_measure_period(struct aspeed_pwm_tacho_data
|
||||
*priv, u8 type)
|
||||
{
|
||||
u32 clk;
|
||||
u16 tacho_unit;
|
||||
u8 clk_unit, div_h, div_l, tacho_div;
|
||||
|
||||
clk = priv->clk_freq;
|
||||
clk_unit = priv->type_pwm_clock_unit[type];
|
||||
div_h = priv->type_pwm_clock_division_h[type];
|
||||
div_h = 0x1 << div_h;
|
||||
div_l = priv->type_pwm_clock_division_l[type];
|
||||
if (div_l == 0)
|
||||
div_l = 1;
|
||||
else
|
||||
div_l = div_l * 2;
|
||||
|
||||
tacho_unit = priv->type_fan_tach_unit[type];
|
||||
tacho_div = priv->type_fan_tach_clock_division[type];
|
||||
|
||||
tacho_div = 0x4 << (tacho_div * 2);
|
||||
return clk / (clk_unit * div_h * div_l * tacho_div * tacho_unit);
|
||||
}
|
||||
|
||||
static u32 aspeed_get_fan_tach_ch_rpm(struct aspeed_pwm_tacho_data *priv,
|
||||
u8 fan_tach_ch)
|
||||
{
|
||||
u32 raw_data, tach_div, clk_source, sec, val;
|
||||
u8 fan_tach_ch_source, type;
|
||||
|
||||
regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0);
|
||||
regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch);
|
||||
|
||||
fan_tach_ch_source = priv->fan_tach_ch_source[fan_tach_ch];
|
||||
type = priv->pwm_port_type[fan_tach_ch_source];
|
||||
|
||||
sec = (1000 / aspeed_get_fan_tach_ch_measure_period(priv, type));
|
||||
msleep(sec);
|
||||
|
||||
regmap_read(priv->regmap, ASPEED_PTCR_RESULT, &val);
|
||||
raw_data = val & RESULT_VALUE_MASK;
|
||||
tach_div = priv->type_fan_tach_clock_division[type];
|
||||
tach_div = 0x4 << (tach_div * 2);
|
||||
clk_source = priv->clk_freq;
|
||||
|
||||
if (raw_data == 0)
|
||||
return 0;
|
||||
|
||||
return (clk_source * 60) / (2 * raw_data * tach_div);
|
||||
}
|
||||
|
||||
static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
|
||||
int index = sensor_attr->index;
|
||||
int ret;
|
||||
struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
|
||||
long fan_ctrl;
|
||||
|
||||
ret = kstrtol(buf, 10, &fan_ctrl);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (fan_ctrl < 0 || fan_ctrl > PWM_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (priv->pwm_port_fan_ctrl[index] == fan_ctrl)
|
||||
return count;
|
||||
|
||||
priv->pwm_port_fan_ctrl[index] = fan_ctrl;
|
||||
aspeed_set_pwm_port_fan_ctrl(priv, index, fan_ctrl);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
|
||||
int index = sensor_attr->index;
|
||||
struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
|
||||
|
||||
return sprintf(buf, "%u\n", priv->pwm_port_fan_ctrl[index]);
|
||||
}
|
||||
|
||||
static ssize_t show_rpm(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
|
||||
int index = sensor_attr->index;
|
||||
u32 rpm;
|
||||
struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
|
||||
|
||||
rpm = aspeed_get_fan_tach_ch_rpm(priv, index);
|
||||
|
||||
return sprintf(buf, "%u\n", rpm);
|
||||
}
|
||||
|
||||
static umode_t pwm_is_visible(struct kobject *kobj,
|
||||
struct attribute *a, int index)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
|
||||
|
||||
if (!priv->pwm_present[index])
|
||||
return 0;
|
||||
return a->mode;
|
||||
}
|
||||
|
||||
static umode_t fan_dev_is_visible(struct kobject *kobj,
|
||||
struct attribute *a, int index)
|
||||
{
|
||||
struct device *dev = container_of(kobj, struct device, kobj);
|
||||
struct aspeed_pwm_tacho_data *priv = dev_get_drvdata(dev);
|
||||
|
||||
if (!priv->fan_tach_present[index])
|
||||
return 0;
|
||||
return a->mode;
|
||||
}
|
||||
|
||||
static SENSOR_DEVICE_ATTR(pwm0, 0644,
|
||||
show_pwm, set_pwm, 0);
|
||||
static SENSOR_DEVICE_ATTR(pwm1, 0644,
|
||||
show_pwm, set_pwm, 1);
|
||||
static SENSOR_DEVICE_ATTR(pwm2, 0644,
|
||||
show_pwm, set_pwm, 2);
|
||||
static SENSOR_DEVICE_ATTR(pwm3, 0644,
|
||||
show_pwm, set_pwm, 3);
|
||||
static SENSOR_DEVICE_ATTR(pwm4, 0644,
|
||||
show_pwm, set_pwm, 4);
|
||||
static SENSOR_DEVICE_ATTR(pwm5, 0644,
|
||||
show_pwm, set_pwm, 5);
|
||||
static SENSOR_DEVICE_ATTR(pwm6, 0644,
|
||||
show_pwm, set_pwm, 6);
|
||||
static SENSOR_DEVICE_ATTR(pwm7, 0644,
|
||||
show_pwm, set_pwm, 7);
|
||||
static struct attribute *pwm_dev_attrs[] = {
|
||||
&sensor_dev_attr_pwm0.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm1.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm2.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm3.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm4.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm5.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm6.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm7.dev_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group pwm_dev_group = {
|
||||
.attrs = pwm_dev_attrs,
|
||||
.is_visible = pwm_is_visible,
|
||||
};
|
||||
|
||||
static SENSOR_DEVICE_ATTR(fan0_input, 0444,
|
||||
show_rpm, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(fan1_input, 0444,
|
||||
show_rpm, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(fan2_input, 0444,
|
||||
show_rpm, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(fan3_input, 0444,
|
||||
show_rpm, NULL, 3);
|
||||
static SENSOR_DEVICE_ATTR(fan4_input, 0444,
|
||||
show_rpm, NULL, 4);
|
||||
static SENSOR_DEVICE_ATTR(fan5_input, 0444,
|
||||
show_rpm, NULL, 5);
|
||||
static SENSOR_DEVICE_ATTR(fan6_input, 0444,
|
||||
show_rpm, NULL, 6);
|
||||
static SENSOR_DEVICE_ATTR(fan7_input, 0444,
|
||||
show_rpm, NULL, 7);
|
||||
static SENSOR_DEVICE_ATTR(fan8_input, 0444,
|
||||
show_rpm, NULL, 8);
|
||||
static SENSOR_DEVICE_ATTR(fan9_input, 0444,
|
||||
show_rpm, NULL, 9);
|
||||
static SENSOR_DEVICE_ATTR(fan10_input, 0444,
|
||||
show_rpm, NULL, 10);
|
||||
static SENSOR_DEVICE_ATTR(fan11_input, 0444,
|
||||
show_rpm, NULL, 11);
|
||||
static SENSOR_DEVICE_ATTR(fan12_input, 0444,
|
||||
show_rpm, NULL, 12);
|
||||
static SENSOR_DEVICE_ATTR(fan13_input, 0444,
|
||||
show_rpm, NULL, 13);
|
||||
static SENSOR_DEVICE_ATTR(fan14_input, 0444,
|
||||
show_rpm, NULL, 14);
|
||||
static SENSOR_DEVICE_ATTR(fan15_input, 0444,
|
||||
show_rpm, NULL, 15);
|
||||
static struct attribute *fan_dev_attrs[] = {
|
||||
&sensor_dev_attr_fan0_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan4_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan6_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan7_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan8_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan9_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan10_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan11_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan12_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan13_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan14_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan15_input.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group fan_dev_group = {
|
||||
.attrs = fan_dev_attrs,
|
||||
.is_visible = fan_dev_is_visible,
|
||||
};
|
||||
|
||||
/*
|
||||
* The clock type is type M :
|
||||
* The PWM frequency = 24MHz / (type M clock division L bit *
|
||||
* type M clock division H bit * (type M PWM period bit + 1))
|
||||
*/
|
||||
static void aspeed_create_type(struct aspeed_pwm_tacho_data *priv)
|
||||
{
|
||||
priv->type_pwm_clock_division_h[TYPEM] = M_PWM_DIV_H;
|
||||
priv->type_pwm_clock_division_l[TYPEM] = M_PWM_DIV_L;
|
||||
priv->type_pwm_clock_unit[TYPEM] = M_PWM_PERIOD;
|
||||
aspeed_set_pwm_clock_values(priv->regmap, TYPEM, M_PWM_DIV_H,
|
||||
M_PWM_DIV_L, M_PWM_PERIOD);
|
||||
aspeed_set_tacho_type_enable(priv->regmap, TYPEM, true);
|
||||
priv->type_fan_tach_clock_division[TYPEM] = M_TACH_CLK_DIV;
|
||||
priv->type_fan_tach_unit[TYPEM] = M_TACH_UNIT;
|
||||
aspeed_set_tacho_type_values(priv->regmap, TYPEM, M_TACH_MODE,
|
||||
M_TACH_UNIT, M_TACH_CLK_DIV);
|
||||
}
|
||||
|
||||
static void aspeed_create_pwm_port(struct aspeed_pwm_tacho_data *priv,
|
||||
u8 pwm_port)
|
||||
{
|
||||
aspeed_set_pwm_port_enable(priv->regmap, pwm_port, true);
|
||||
priv->pwm_present[pwm_port] = true;
|
||||
|
||||
priv->pwm_port_type[pwm_port] = TYPEM;
|
||||
aspeed_set_pwm_port_type(priv->regmap, pwm_port, TYPEM);
|
||||
|
||||
priv->pwm_port_fan_ctrl[pwm_port] = INIT_FAN_CTRL;
|
||||
aspeed_set_pwm_port_fan_ctrl(priv, pwm_port, INIT_FAN_CTRL);
|
||||
}
|
||||
|
||||
static void aspeed_create_fan_tach_channel(struct aspeed_pwm_tacho_data *priv,
|
||||
u8 *fan_tach_ch,
|
||||
int count,
|
||||
u8 pwm_source)
|
||||
{
|
||||
u8 val, index;
|
||||
|
||||
for (val = 0; val < count; val++) {
|
||||
index = fan_tach_ch[val];
|
||||
aspeed_set_fan_tach_ch_enable(priv->regmap, index, true);
|
||||
priv->fan_tach_present[index] = true;
|
||||
priv->fan_tach_ch_source[index] = pwm_source;
|
||||
aspeed_set_fan_tach_ch_source(priv->regmap, index, pwm_source);
|
||||
}
|
||||
}
|
||||
|
||||
static int aspeed_create_fan(struct device *dev,
|
||||
struct device_node *child,
|
||||
struct aspeed_pwm_tacho_data *priv)
|
||||
{
|
||||
u8 *fan_tach_ch;
|
||||
u32 pwm_port;
|
||||
int ret, count;
|
||||
|
||||
ret = of_property_read_u32(child, "reg", &pwm_port);
|
||||
if (ret)
|
||||
return ret;
|
||||
aspeed_create_pwm_port(priv, (u8)pwm_port);
|
||||
|
||||
count = of_property_count_u8_elems(child, "aspeed,fan-tach-ch");
|
||||
if (count < 1)
|
||||
return -EINVAL;
|
||||
fan_tach_ch = devm_kzalloc(dev, sizeof(*fan_tach_ch) * count,
|
||||
GFP_KERNEL);
|
||||
if (!fan_tach_ch)
|
||||
return -ENOMEM;
|
||||
ret = of_property_read_u8_array(child, "aspeed,fan-tach-ch",
|
||||
fan_tach_ch, count);
|
||||
if (ret)
|
||||
return ret;
|
||||
aspeed_create_fan_tach_channel(priv, fan_tach_ch, count, pwm_port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aspeed_pwm_tacho_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np, *child;
|
||||
struct aspeed_pwm_tacho_data *priv;
|
||||
void __iomem *regs;
|
||||
struct resource *res;
|
||||
struct device *hwmon;
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
|
||||
np = dev->of_node;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -ENOENT;
|
||||
regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(regs))
|
||||
return PTR_ERR(regs);
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs,
|
||||
&aspeed_pwm_tacho_regmap_config);
|
||||
if (IS_ERR(priv->regmap))
|
||||
return PTR_ERR(priv->regmap);
|
||||
regmap_write(priv->regmap, ASPEED_PTCR_TACH_SOURCE, 0);
|
||||
regmap_write(priv->regmap, ASPEED_PTCR_TACH_SOURCE_EXT, 0);
|
||||
|
||||
clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(clk))
|
||||
return -ENODEV;
|
||||
priv->clk_freq = clk_get_rate(clk);
|
||||
aspeed_set_clock_enable(priv->regmap, true);
|
||||
aspeed_set_clock_source(priv->regmap, 0);
|
||||
|
||||
aspeed_create_type(priv);
|
||||
|
||||
for_each_child_of_node(np, child) {
|
||||
ret = aspeed_create_fan(dev, child, priv);
|
||||
of_node_put(child);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
of_node_put(np);
|
||||
|
||||
priv->groups[0] = &pwm_dev_group;
|
||||
priv->groups[1] = &fan_dev_group;
|
||||
priv->groups[2] = NULL;
|
||||
hwmon = devm_hwmon_device_register_with_groups(dev,
|
||||
"aspeed_pwm_tacho",
|
||||
priv, priv->groups);
|
||||
return PTR_ERR_OR_ZERO(hwmon);
|
||||
}
|
||||
|
||||
static const struct of_device_id of_pwm_tacho_match_table[] = {
|
||||
{ .compatible = "aspeed,ast2400-pwm-tacho", },
|
||||
{ .compatible = "aspeed,ast2500-pwm-tacho", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_pwm_tacho_match_table);
|
||||
|
||||
static struct platform_driver aspeed_pwm_tacho_driver = {
|
||||
.probe = aspeed_pwm_tacho_probe,
|
||||
.driver = {
|
||||
.name = "aspeed_pwm_tacho",
|
||||
.of_match_table = of_pwm_tacho_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(aspeed_pwm_tacho_driver);
|
||||
|
||||
MODULE_AUTHOR("Jaghathiswari Rankappagounder Natarajan <jaghu@google.com>");
|
||||
MODULE_DESCRIPTION("ASPEED PWM and Fan Tacho device driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -995,6 +995,13 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
|
|||
},
|
||||
.driver_data = (void *)&i8k_config_data[DELL_XPS],
|
||||
},
|
||||
{
|
||||
.ident = "Dell XPS 15 9560",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "XPS 15 9560"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ static ssize_t hwmon_attr_show_string(struct device *dev,
|
|||
char *buf)
|
||||
{
|
||||
struct hwmon_device_attribute *hattr = to_hwmon_attr(devattr);
|
||||
char *s;
|
||||
const char *s;
|
||||
int ret;
|
||||
|
||||
ret = hattr->ops->read_string(dev, hattr->type, hattr->attr,
|
||||
|
|
|
@ -117,7 +117,7 @@ static long ina209_from_reg(const u8 reg, const u16 val)
|
|||
case INA209_SHUNT_VOLTAGE_POS_WARN:
|
||||
case INA209_SHUNT_VOLTAGE_NEG_WARN:
|
||||
/* LSB=10 uV. Convert to mV. */
|
||||
return DIV_ROUND_CLOSEST(val, 100);
|
||||
return DIV_ROUND_CLOSEST((s16)val, 100);
|
||||
|
||||
case INA209_BUS_VOLTAGE:
|
||||
case INA209_BUS_VOLTAGE_MAX_PEAK:
|
||||
|
@ -146,7 +146,7 @@ static long ina209_from_reg(const u8 reg, const u16 val)
|
|||
|
||||
case INA209_CURRENT:
|
||||
/* LSB=1 mA (selected). Is in mA */
|
||||
return val;
|
||||
return (s16)val;
|
||||
}
|
||||
|
||||
/* programmer goofed */
|
||||
|
@ -608,11 +608,18 @@ static const struct i2c_device_id ina209_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ina209_id);
|
||||
|
||||
static const struct of_device_id ina209_of_match[] = {
|
||||
{ .compatible = "ti,ina209" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ina209_of_match);
|
||||
|
||||
/* This is the driver that will be inserted */
|
||||
static struct i2c_driver ina209_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "ina209",
|
||||
.of_match_table = of_match_ptr(ina209_of_match),
|
||||
},
|
||||
.probe = ina209_probe,
|
||||
.remove = ina209_remove,
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/util_macros.h>
|
||||
|
@ -424,13 +425,19 @@ static int ina2xx_probe(struct i2c_client *client,
|
|||
struct device *hwmon_dev;
|
||||
u32 val;
|
||||
int ret, group = 0;
|
||||
enum ina2xx_ids chip;
|
||||
|
||||
if (client->dev.of_node)
|
||||
chip = (enum ina2xx_ids)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
chip = id->driver_data;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
/* set the device type */
|
||||
data->config = &ina2xx_config[id->driver_data];
|
||||
data->config = &ina2xx_config[chip];
|
||||
|
||||
if (of_property_read_u32(dev->of_node, "shunt-resistor", &val) < 0) {
|
||||
struct ina2xx_platform_data *pdata = dev_get_platdata(dev);
|
||||
|
@ -487,9 +494,35 @@ static const struct i2c_device_id ina2xx_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ina2xx_id);
|
||||
|
||||
static const struct of_device_id ina2xx_of_match[] = {
|
||||
{
|
||||
.compatible = "ti,ina219",
|
||||
.data = (void *)ina219
|
||||
},
|
||||
{
|
||||
.compatible = "ti,ina220",
|
||||
.data = (void *)ina219
|
||||
},
|
||||
{
|
||||
.compatible = "ti,ina226",
|
||||
.data = (void *)ina226
|
||||
},
|
||||
{
|
||||
.compatible = "ti,ina230",
|
||||
.data = (void *)ina226
|
||||
},
|
||||
{
|
||||
.compatible = "ti,ina231",
|
||||
.data = (void *)ina226
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ina2xx_of_match);
|
||||
|
||||
static struct i2c_driver ina2xx_driver = {
|
||||
.driver = {
|
||||
.name = "ina2xx",
|
||||
.of_match_table = of_match_ptr(ina2xx_of_match),
|
||||
},
|
||||
.probe = ina2xx_probe,
|
||||
.id_table = ina2xx_id,
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
@ -1115,6 +1116,10 @@ static int lm63_probe(struct i2c_client *client,
|
|||
mutex_init(&data->update_lock);
|
||||
|
||||
/* Set the device type */
|
||||
if (client->dev.of_node)
|
||||
data->kind = (enum chips)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->kind = id->driver_data;
|
||||
data->kind = id->driver_data;
|
||||
if (data->kind == lm64)
|
||||
data->temp2_offset = 16000;
|
||||
|
@ -1149,10 +1154,28 @@ static const struct i2c_device_id lm63_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lm63_id);
|
||||
|
||||
static const struct of_device_id lm63_of_match[] = {
|
||||
{
|
||||
.compatible = "national,lm63",
|
||||
.data = (void *)lm63
|
||||
},
|
||||
{
|
||||
.compatible = "national,lm64",
|
||||
.data = (void *)lm64
|
||||
},
|
||||
{
|
||||
.compatible = "national,lm96163",
|
||||
.data = (void *)lm96163
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lm63_of_match);
|
||||
|
||||
static struct i2c_driver lm63_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "lm63",
|
||||
.of_match_table = of_match_ptr(lm63_of_match),
|
||||
},
|
||||
.probe = lm63_probe,
|
||||
.id_table = lm63_id,
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include "lm75.h"
|
||||
|
@ -273,7 +274,12 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
int status, err;
|
||||
u8 set_mask, clr_mask;
|
||||
int new;
|
||||
enum lm75_type kind = id->driver_data;
|
||||
enum lm75_type kind;
|
||||
|
||||
if (client->dev.of_node)
|
||||
kind = (enum lm75_type)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
kind = id->driver_data;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
|
||||
|
@ -424,6 +430,95 @@ static const struct i2c_device_id lm75_ids[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lm75_ids);
|
||||
|
||||
static const struct of_device_id lm75_of_match[] = {
|
||||
{
|
||||
.compatible = "adi,adt75",
|
||||
.data = (void *)adt75
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,ds1775",
|
||||
.data = (void *)ds1775
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,ds75",
|
||||
.data = (void *)ds75
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,ds7505",
|
||||
.data = (void *)ds7505
|
||||
},
|
||||
{
|
||||
.compatible = "gmt,g751",
|
||||
.data = (void *)g751
|
||||
},
|
||||
{
|
||||
.compatible = "national,lm75",
|
||||
.data = (void *)lm75
|
||||
},
|
||||
{
|
||||
.compatible = "national,lm75a",
|
||||
.data = (void *)lm75a
|
||||
},
|
||||
{
|
||||
.compatible = "national,lm75b",
|
||||
.data = (void *)lm75b
|
||||
},
|
||||
{
|
||||
.compatible = "maxim,max6625",
|
||||
.data = (void *)max6625
|
||||
},
|
||||
{
|
||||
.compatible = "maxim,max6626",
|
||||
.data = (void *)max6626
|
||||
},
|
||||
{
|
||||
.compatible = "maxim,mcp980x",
|
||||
.data = (void *)mcp980x
|
||||
},
|
||||
{
|
||||
.compatible = "st,stds75",
|
||||
.data = (void *)stds75
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,tcn75",
|
||||
.data = (void *)tcn75
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp100",
|
||||
.data = (void *)tmp100
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp101",
|
||||
.data = (void *)tmp101
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp105",
|
||||
.data = (void *)tmp105
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp112",
|
||||
.data = (void *)tmp112
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp175",
|
||||
.data = (void *)tmp175
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp275",
|
||||
.data = (void *)tmp275
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp75",
|
||||
.data = (void *)tmp75
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp75c",
|
||||
.data = (void *)tmp75c
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lm75_of_match);
|
||||
|
||||
#define LM75A_ID 0xA1
|
||||
|
||||
/* Return 0 if detection is successful, -ENODEV otherwise */
|
||||
|
@ -560,6 +655,7 @@ static struct i2c_driver lm75_driver = {
|
|||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "lm75",
|
||||
.of_match_table = of_match_ptr(lm75_of_match),
|
||||
.pm = LM75_DEV_PM_OPS,
|
||||
},
|
||||
.probe = lm75_probe,
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
|
@ -1552,7 +1553,10 @@ static int lm85_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
return -ENOMEM;
|
||||
|
||||
data->client = client;
|
||||
data->type = id->driver_data;
|
||||
if (client->dev.of_node)
|
||||
data->type = (enum chips)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->type = id->driver_data;
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
/* Fill in the chip specific driver values */
|
||||
|
@ -1623,10 +1627,60 @@ static const struct i2c_device_id lm85_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lm85_id);
|
||||
|
||||
static const struct of_device_id lm85_of_match[] = {
|
||||
{
|
||||
.compatible = "adi,adm1027",
|
||||
.data = (void *)adm1027
|
||||
},
|
||||
{
|
||||
.compatible = "adi,adt7463",
|
||||
.data = (void *)adt7463
|
||||
},
|
||||
{
|
||||
.compatible = "adi,adt7468",
|
||||
.data = (void *)adt7468
|
||||
},
|
||||
{
|
||||
.compatible = "national,lm85",
|
||||
.data = (void *)lm85
|
||||
},
|
||||
{
|
||||
.compatible = "national,lm85b",
|
||||
.data = (void *)lm85
|
||||
},
|
||||
{
|
||||
.compatible = "national,lm85c",
|
||||
.data = (void *)lm85
|
||||
},
|
||||
{
|
||||
.compatible = "smsc,emc6d100",
|
||||
.data = (void *)emc6d100
|
||||
},
|
||||
{
|
||||
.compatible = "smsc,emc6d101",
|
||||
.data = (void *)emc6d100
|
||||
},
|
||||
{
|
||||
.compatible = "smsc,emc6d102",
|
||||
.data = (void *)emc6d102
|
||||
},
|
||||
{
|
||||
.compatible = "smsc,emc6d103",
|
||||
.data = (void *)emc6d103
|
||||
},
|
||||
{
|
||||
.compatible = "smsc,emc6d103s",
|
||||
.data = (void *)emc6d103s
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lm85_of_match);
|
||||
|
||||
static struct i2c_driver lm85_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "lm85",
|
||||
.of_match_table = of_match_ptr(lm85_of_match),
|
||||
},
|
||||
.probe = lm85_probe,
|
||||
.id_table = lm85_id,
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#include <linux/hwmon-vid.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
/*
|
||||
* Addresses to scan
|
||||
|
@ -74,8 +75,6 @@
|
|||
|
||||
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
|
||||
|
||||
enum chips { lm87, adm1024 };
|
||||
|
||||
/*
|
||||
* The LM87 registers
|
||||
*/
|
||||
|
@ -855,8 +854,26 @@ static int lm87_init_client(struct i2c_client *client)
|
|||
{
|
||||
struct lm87_data *data = i2c_get_clientdata(client);
|
||||
int rc;
|
||||
struct device_node *of_node = client->dev.of_node;
|
||||
u8 val = 0;
|
||||
struct regulator *vcc = NULL;
|
||||
|
||||
if (dev_get_platdata(&client->dev)) {
|
||||
if (of_node) {
|
||||
if (of_property_read_bool(of_node, "has-temp3"))
|
||||
val |= CHAN_TEMP3;
|
||||
if (of_property_read_bool(of_node, "has-in6"))
|
||||
val |= CHAN_NO_FAN(0);
|
||||
if (of_property_read_bool(of_node, "has-in7"))
|
||||
val |= CHAN_NO_FAN(1);
|
||||
vcc = devm_regulator_get_optional(&client->dev, "vcc");
|
||||
if (!IS_ERR(vcc)) {
|
||||
if (regulator_get_voltage(vcc) == 5000000)
|
||||
val |= CHAN_VCC_5V;
|
||||
}
|
||||
data->channel = val;
|
||||
lm87_write_value(client,
|
||||
LM87_REG_CHANNEL_MODE, data->channel);
|
||||
} else if (dev_get_platdata(&client->dev)) {
|
||||
data->channel = *(u8 *)dev_get_platdata(&client->dev);
|
||||
lm87_write_value(client,
|
||||
LM87_REG_CHANNEL_MODE, data->channel);
|
||||
|
@ -962,16 +979,24 @@ static int lm87_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
*/
|
||||
|
||||
static const struct i2c_device_id lm87_id[] = {
|
||||
{ "lm87", lm87 },
|
||||
{ "adm1024", adm1024 },
|
||||
{ "lm87", 0 },
|
||||
{ "adm1024", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lm87_id);
|
||||
|
||||
static const struct of_device_id lm87_of_match[] = {
|
||||
{ .compatible = "ti,lm87" },
|
||||
{ .compatible = "adi,adm1024" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lm87_of_match);
|
||||
|
||||
static struct i2c_driver lm87_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "lm87",
|
||||
.of_match_table = lm87_of_match,
|
||||
},
|
||||
.probe = lm87_probe,
|
||||
.id_table = lm87_id,
|
||||
|
|
|
@ -92,6 +92,7 @@
|
|||
#include <linux/hwmon.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
@ -235,6 +236,99 @@ static const struct i2c_device_id lm90_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lm90_id);
|
||||
|
||||
static const struct of_device_id lm90_of_match[] = {
|
||||
{
|
||||
.compatible = "adi,adm1032",
|
||||
.data = (void *)adm1032
|
||||
},
|
||||
{
|
||||
.compatible = "adi,adt7461",
|
||||
.data = (void *)adt7461
|
||||
},
|
||||
{
|
||||
.compatible = "adi,adt7461a",
|
||||
.data = (void *)adt7461
|
||||
},
|
||||
{
|
||||
.compatible = "gmt,g781",
|
||||
.data = (void *)g781
|
||||
},
|
||||
{
|
||||
.compatible = "national,lm90",
|
||||
.data = (void *)lm90
|
||||
},
|
||||
{
|
||||
.compatible = "national,lm86",
|
||||
.data = (void *)lm86
|
||||
},
|
||||
{
|
||||
.compatible = "national,lm89",
|
||||
.data = (void *)lm86
|
||||
},
|
||||
{
|
||||
.compatible = "national,lm99",
|
||||
.data = (void *)lm99
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,max6646",
|
||||
.data = (void *)max6646
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,max6647",
|
||||
.data = (void *)max6646
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,max6649",
|
||||
.data = (void *)max6646
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,max6657",
|
||||
.data = (void *)max6657
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,max6658",
|
||||
.data = (void *)max6657
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,max6659",
|
||||
.data = (void *)max6659
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,max6680",
|
||||
.data = (void *)max6680
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,max6681",
|
||||
.data = (void *)max6680
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,max6695",
|
||||
.data = (void *)max6696
|
||||
},
|
||||
{
|
||||
.compatible = "dallas,max6696",
|
||||
.data = (void *)max6696
|
||||
},
|
||||
{
|
||||
.compatible = "onnn,nct1008",
|
||||
.data = (void *)adt7461
|
||||
},
|
||||
{
|
||||
.compatible = "winbond,w83l771",
|
||||
.data = (void *)w83l771
|
||||
},
|
||||
{
|
||||
.compatible = "nxp,sa56004",
|
||||
.data = (void *)sa56004
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp451",
|
||||
.data = (void *)tmp451
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lm90_of_match);
|
||||
|
||||
/*
|
||||
* chip type specific parameters
|
||||
*/
|
||||
|
@ -1677,7 +1771,10 @@ static int lm90_probe(struct i2c_client *client,
|
|||
mutex_init(&data->update_lock);
|
||||
|
||||
/* Set the device type */
|
||||
data->kind = id->driver_data;
|
||||
if (client->dev.of_node)
|
||||
data->kind = (enum chips)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->kind = id->driver_data;
|
||||
if (data->kind == adm1032) {
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
|
||||
client->flags &= ~I2C_CLIENT_PEC;
|
||||
|
@ -1816,6 +1913,7 @@ static struct i2c_driver lm90_driver = {
|
|||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "lm90",
|
||||
.of_match_table = of_match_ptr(lm90_of_match),
|
||||
},
|
||||
.probe = lm90_probe,
|
||||
.alert = lm90_alert,
|
||||
|
|
|
@ -622,10 +622,18 @@ static const struct i2c_device_id lm95245_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, lm95245_id);
|
||||
|
||||
static const struct of_device_id lm95245_of_match[] = {
|
||||
{ .compatible = "national,lm95235" },
|
||||
{ .compatible = "national,lm95245" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lm95245_of_match);
|
||||
|
||||
static struct i2c_driver lm95245_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "lm95245",
|
||||
.of_match_table = of_match_ptr(lm95245_of_match),
|
||||
},
|
||||
.probe = lm95245_probe,
|
||||
.id_table = lm95245_id,
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <linux/platform_data/max6697.h>
|
||||
|
@ -632,7 +633,10 @@ static int max6697_probe(struct i2c_client *client,
|
|||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->type = id->driver_data;
|
||||
if (client->dev.of_node)
|
||||
data->type = (enum chips)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->type = id->driver_data;
|
||||
data->chip = &max6697_chip_data[data->type];
|
||||
data->client = client;
|
||||
mutex_init(&data->update_lock);
|
||||
|
@ -662,10 +666,56 @@ static const struct i2c_device_id max6697_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, max6697_id);
|
||||
|
||||
static const struct of_device_id max6697_of_match[] = {
|
||||
{
|
||||
.compatible = "maxim,max6581",
|
||||
.data = (void *)max6581
|
||||
},
|
||||
{
|
||||
.compatible = "maxim,max6602",
|
||||
.data = (void *)max6602
|
||||
},
|
||||
{
|
||||
.compatible = "maxim,max6622",
|
||||
.data = (void *)max6622
|
||||
},
|
||||
{
|
||||
.compatible = "maxim,max6636",
|
||||
.data = (void *)max6636
|
||||
},
|
||||
{
|
||||
.compatible = "maxim,max6689",
|
||||
.data = (void *)max6689
|
||||
},
|
||||
{
|
||||
.compatible = "maxim,max6693",
|
||||
.data = (void *)max6693
|
||||
},
|
||||
{
|
||||
.compatible = "maxim,max6694",
|
||||
.data = (void *)max6694
|
||||
},
|
||||
{
|
||||
.compatible = "maxim,max6697",
|
||||
.data = (void *)max6697
|
||||
},
|
||||
{
|
||||
.compatible = "maxim,max6698",
|
||||
.data = (void *)max6698
|
||||
},
|
||||
{
|
||||
.compatible = "maxim,max6699",
|
||||
.data = (void *)max6699
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, max6697_of_match);
|
||||
|
||||
static struct i2c_driver max6697_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "max6697",
|
||||
.of_match_table = of_match_ptr(max6697_of_match),
|
||||
},
|
||||
.probe = max6697_probe,
|
||||
.id_table = max6697_id,
|
||||
|
|
|
@ -101,8 +101,8 @@ static const struct coefficients adm1075_coefficients[] = {
|
|||
[0] = { 27169, 0, -1 }, /* voltage */
|
||||
[1] = { 806, 20475, -1 }, /* current, irange25 */
|
||||
[2] = { 404, 20475, -1 }, /* current, irange50 */
|
||||
[3] = { 0, -1, 8549 }, /* power, irange25 */
|
||||
[4] = { 0, -1, 4279 }, /* power, irange50 */
|
||||
[3] = { 8549, 0, -1 }, /* power, irange25 */
|
||||
[4] = { 4279, 0, -1 }, /* power, irange50 */
|
||||
};
|
||||
|
||||
static const struct coefficients adm1275_coefficients[] = {
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -119,6 +120,35 @@ static const struct i2c_device_id ucd9000_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ucd9000_id);
|
||||
|
||||
static const struct of_device_id ucd9000_of_match[] = {
|
||||
{
|
||||
.compatible = "ti,ucd9000",
|
||||
.data = (void *)ucd9000
|
||||
},
|
||||
{
|
||||
.compatible = "ti,ucd90120",
|
||||
.data = (void *)ucd90120
|
||||
},
|
||||
{
|
||||
.compatible = "ti,ucd90124",
|
||||
.data = (void *)ucd90124
|
||||
},
|
||||
{
|
||||
.compatible = "ti,ucd90160",
|
||||
.data = (void *)ucd90160
|
||||
},
|
||||
{
|
||||
.compatible = "ti,ucd9090",
|
||||
.data = (void *)ucd9090
|
||||
},
|
||||
{
|
||||
.compatible = "ti,ucd90910",
|
||||
.data = (void *)ucd90910
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ucd9000_of_match);
|
||||
|
||||
static int ucd9000_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -126,6 +156,7 @@ static int ucd9000_probe(struct i2c_client *client,
|
|||
struct ucd9000_data *data;
|
||||
struct pmbus_driver_info *info;
|
||||
const struct i2c_device_id *mid;
|
||||
enum chips chip;
|
||||
int i, ret;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
|
@ -151,7 +182,12 @@ static int ucd9000_probe(struct i2c_client *client,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (id->driver_data != ucd9000 && id->driver_data != mid->driver_data)
|
||||
if (client->dev.of_node)
|
||||
chip = (enum chips)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
chip = id->driver_data;
|
||||
|
||||
if (chip != ucd9000 && chip != mid->driver_data)
|
||||
dev_notice(&client->dev,
|
||||
"Device mismatch: Configured %s, detected %s\n",
|
||||
id->name, mid->name);
|
||||
|
@ -234,6 +270,7 @@ static int ucd9000_probe(struct i2c_client *client,
|
|||
static struct i2c_driver ucd9000_driver = {
|
||||
.driver = {
|
||||
.name = "ucd9000",
|
||||
.of_match_table = of_match_ptr(ucd9000_of_match),
|
||||
},
|
||||
.probe = ucd9000_probe,
|
||||
.remove = pmbus_do_remove,
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -46,12 +47,50 @@ static const struct i2c_device_id ucd9200_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ucd9200_id);
|
||||
|
||||
static const struct of_device_id ucd9200_of_match[] = {
|
||||
{
|
||||
.compatible = "ti,cd9200",
|
||||
.data = (void *)ucd9200
|
||||
},
|
||||
{
|
||||
.compatible = "ti,cd9220",
|
||||
.data = (void *)ucd9220
|
||||
},
|
||||
{
|
||||
.compatible = "ti,cd9222",
|
||||
.data = (void *)ucd9222
|
||||
},
|
||||
{
|
||||
.compatible = "ti,cd9224",
|
||||
.data = (void *)ucd9224
|
||||
},
|
||||
{
|
||||
.compatible = "ti,cd9240",
|
||||
.data = (void *)ucd9240
|
||||
},
|
||||
{
|
||||
.compatible = "ti,cd9244",
|
||||
.data = (void *)ucd9244
|
||||
},
|
||||
{
|
||||
.compatible = "ti,cd9246",
|
||||
.data = (void *)ucd9246
|
||||
},
|
||||
{
|
||||
.compatible = "ti,cd9248",
|
||||
.data = (void *)ucd9248
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ucd9200_of_match);
|
||||
|
||||
static int ucd9200_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
|
||||
struct pmbus_driver_info *info;
|
||||
const struct i2c_device_id *mid;
|
||||
enum chips chip;
|
||||
int i, j, ret;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
|
@ -76,7 +115,13 @@ static int ucd9200_probe(struct i2c_client *client,
|
|||
dev_err(&client->dev, "Unsupported device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (id->driver_data != ucd9200 && id->driver_data != mid->driver_data)
|
||||
|
||||
if (client->dev.of_node)
|
||||
chip = (enum chips)of_device_get_match_data(&client->dev);
|
||||
else
|
||||
chip = id->driver_data;
|
||||
|
||||
if (chip != ucd9200 && chip != mid->driver_data)
|
||||
dev_notice(&client->dev,
|
||||
"Device mismatch: Configured %s, detected %s\n",
|
||||
id->name, mid->name);
|
||||
|
@ -167,6 +212,7 @@ static int ucd9200_probe(struct i2c_client *client,
|
|||
static struct i2c_driver ucd9200_driver = {
|
||||
.driver = {
|
||||
.name = "ucd9200",
|
||||
.of_match_table = of_match_ptr(ucd9200_of_match),
|
||||
},
|
||||
.probe = ucd9200_probe,
|
||||
.remove = pmbus_do_remove,
|
||||
|
|
|
@ -85,6 +85,12 @@ static const struct i2c_device_id stts751_id[] = {
|
|||
{ }
|
||||
};
|
||||
|
||||
static const struct of_device_id stts751_of_match[] = {
|
||||
{ .compatible = "stts751" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, stts751_of_match);
|
||||
|
||||
struct stts751_priv {
|
||||
struct device *dev;
|
||||
struct i2c_client *client;
|
||||
|
@ -819,6 +825,7 @@ static struct i2c_driver stts751_driver = {
|
|||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = DEVNAME,
|
||||
.of_match_table = of_match_ptr(stts751_of_match),
|
||||
},
|
||||
.probe = stts751_probe,
|
||||
.id_table = stts751_id,
|
||||
|
|
|
@ -323,8 +323,15 @@ static const struct i2c_device_id tmp102_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tmp102_id);
|
||||
|
||||
static const struct of_device_id tmp102_of_match[] = {
|
||||
{ .compatible = "ti,tmp102" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tmp102_of_match);
|
||||
|
||||
static struct i2c_driver tmp102_driver = {
|
||||
.driver.name = DRIVER_NAME,
|
||||
.driver.of_match_table = of_match_ptr(tmp102_of_match),
|
||||
.driver.pm = &tmp102_dev_pm_ops,
|
||||
.probe = tmp102_probe,
|
||||
.id_table = tmp102_id,
|
||||
|
|
|
@ -150,8 +150,7 @@ static int tmp103_probe(struct i2c_client *client,
|
|||
return PTR_ERR_OR_ZERO(hwmon_dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int tmp103_suspend(struct device *dev)
|
||||
static int __maybe_unused tmp103_suspend(struct device *dev)
|
||||
{
|
||||
struct regmap *regmap = dev_get_drvdata(dev);
|
||||
|
||||
|
@ -159,7 +158,7 @@ static int tmp103_suspend(struct device *dev)
|
|||
TMP103_CONF_SD_MASK, 0);
|
||||
}
|
||||
|
||||
static int tmp103_resume(struct device *dev)
|
||||
static int __maybe_unused tmp103_resume(struct device *dev)
|
||||
{
|
||||
struct regmap *regmap = dev_get_drvdata(dev);
|
||||
|
||||
|
@ -167,15 +166,7 @@ static int tmp103_resume(struct device *dev)
|
|||
TMP103_CONF_SD_MASK, TMP103_CONF_SD);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops tmp103_dev_pm_ops = {
|
||||
.suspend = tmp103_suspend,
|
||||
.resume = tmp103_resume,
|
||||
};
|
||||
|
||||
#define TMP103_DEV_PM_OPS (&tmp103_dev_pm_ops)
|
||||
#else
|
||||
#define TMP103_DEV_PM_OPS NULL
|
||||
#endif /* CONFIG_PM */
|
||||
static SIMPLE_DEV_PM_OPS(tmp103_dev_pm_ops, tmp103_suspend, tmp103_resume);
|
||||
|
||||
static const struct i2c_device_id tmp103_id[] = {
|
||||
{ "tmp103", 0 },
|
||||
|
@ -183,10 +174,17 @@ static const struct i2c_device_id tmp103_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tmp103_id);
|
||||
|
||||
static const struct of_device_id tmp103_of_match[] = {
|
||||
{ .compatible = "ti,tmp103" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tmp103_of_match);
|
||||
|
||||
static struct i2c_driver tmp103_driver = {
|
||||
.driver = {
|
||||
.name = "tmp103",
|
||||
.pm = TMP103_DEV_PM_OPS,
|
||||
.of_match_table = of_match_ptr(tmp103_of_match),
|
||||
.pm = &tmp103_dev_pm_ops,
|
||||
},
|
||||
.probe = tmp103_probe,
|
||||
.id_table = tmp103_id,
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
/* Addresses to scan */
|
||||
|
@ -69,6 +70,31 @@ static const struct i2c_device_id tmp421_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tmp421_id);
|
||||
|
||||
static const struct of_device_id tmp421_of_match[] = {
|
||||
{
|
||||
.compatible = "ti,tmp421",
|
||||
.data = (void *)2
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp422",
|
||||
.data = (void *)3
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp423",
|
||||
.data = (void *)4
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp441",
|
||||
.data = (void *)2
|
||||
},
|
||||
{
|
||||
.compatible = "ti,tmp422",
|
||||
.data = (void *)3
|
||||
},
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tmp421_of_match);
|
||||
|
||||
struct tmp421_data {
|
||||
struct i2c_client *client;
|
||||
struct mutex update_lock;
|
||||
|
@ -78,7 +104,7 @@ struct tmp421_data {
|
|||
struct hwmon_chip_info chip;
|
||||
char valid;
|
||||
unsigned long last_updated;
|
||||
int channels;
|
||||
unsigned long channels;
|
||||
u8 config;
|
||||
s16 temp[4];
|
||||
};
|
||||
|
@ -272,7 +298,11 @@ static int tmp421_probe(struct i2c_client *client,
|
|||
return -ENOMEM;
|
||||
|
||||
mutex_init(&data->update_lock);
|
||||
data->channels = id->driver_data;
|
||||
if (client->dev.of_node)
|
||||
data->channels = (unsigned long)
|
||||
of_device_get_match_data(&client->dev);
|
||||
else
|
||||
data->channels = id->driver_data;
|
||||
data->client = client;
|
||||
|
||||
err = tmp421_init_client(client);
|
||||
|
@ -301,6 +331,7 @@ static struct i2c_driver tmp421_driver = {
|
|||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "tmp421",
|
||||
.of_match_table = of_match_ptr(tmp421_of_match),
|
||||
},
|
||||
.probe = tmp421_probe,
|
||||
.id_table = tmp421_id,
|
||||
|
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* TWL4030 MADC Hwmon driver-This driver monitors the real time
|
||||
* conversion of analog signals like battery temperature,
|
||||
* battery type, battery level etc. User can ask for the conversion on a
|
||||
* particular channel using the sysfs nodes.
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* J Keerthy <j-keerthy@ti.com>
|
||||
*
|
||||
* 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 published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c/twl4030-madc.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* sysfs hook function
|
||||
*/
|
||||
static ssize_t madc_read(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct twl4030_madc_request req = {
|
||||
.channels = 1 << attr->index,
|
||||
.method = TWL4030_MADC_SW2,
|
||||
.type = TWL4030_MADC_WAIT,
|
||||
};
|
||||
long val;
|
||||
|
||||
val = twl4030_madc_conversion(&req);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
return sprintf(buf, "%d\n", req.rbuf[attr->index]);
|
||||
}
|
||||
|
||||
/* sysfs nodes to read individual channels from user side */
|
||||
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, madc_read, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, madc_read, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, madc_read, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, madc_read, NULL, 3);
|
||||
static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, madc_read, NULL, 4);
|
||||
static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, madc_read, NULL, 5);
|
||||
static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, madc_read, NULL, 6);
|
||||
static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, madc_read, NULL, 7);
|
||||
static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, madc_read, NULL, 8);
|
||||
static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, madc_read, NULL, 9);
|
||||
static SENSOR_DEVICE_ATTR(curr10_input, S_IRUGO, madc_read, NULL, 10);
|
||||
static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, madc_read, NULL, 11);
|
||||
static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, madc_read, NULL, 12);
|
||||
static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, madc_read, NULL, 15);
|
||||
|
||||
static struct attribute *twl4030_madc_attrs[] = {
|
||||
&sensor_dev_attr_in0_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in6_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in7_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in8_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in9_input.dev_attr.attr,
|
||||
&sensor_dev_attr_curr10_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in11_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in12_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in15_input.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(twl4030_madc);
|
||||
|
||||
static int twl4030_madc_hwmon_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *hwmon;
|
||||
|
||||
hwmon = devm_hwmon_device_register_with_groups(&pdev->dev,
|
||||
"twl4030_madc", NULL,
|
||||
twl4030_madc_groups);
|
||||
return PTR_ERR_OR_ZERO(hwmon);
|
||||
}
|
||||
|
||||
static struct platform_driver twl4030_madc_hwmon_driver = {
|
||||
.probe = twl4030_madc_hwmon_probe,
|
||||
.driver = {
|
||||
.name = "twl4030_madc_hwmon",
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(twl4030_madc_hwmon_driver);
|
||||
|
||||
MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("J Keerthy");
|
||||
MODULE_ALIAS("platform:twl4030_madc_hwmon");
|
|
@ -135,11 +135,16 @@ superio_select(int ioreg, int ld)
|
|||
outb(ld, ioreg + 1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline int
|
||||
superio_enter(int ioreg)
|
||||
{
|
||||
if (!request_muxed_region(ioreg, 2, DRVNAME))
|
||||
return -EBUSY;
|
||||
|
||||
outb(0x87, ioreg);
|
||||
outb(0x87, ioreg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -148,6 +153,7 @@ superio_exit(int ioreg)
|
|||
outb(0xaa, ioreg);
|
||||
outb(0x02, ioreg);
|
||||
outb(0x02, ioreg + 1);
|
||||
release_region(ioreg, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1970,8 +1976,6 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
|
|||
return;
|
||||
}
|
||||
|
||||
superio_enter(sio_data->sioreg);
|
||||
|
||||
/* fan4 and fan5 share some pins with the GPIO and serial flash */
|
||||
if (sio_data->kind == nct6775) {
|
||||
/* On NCT6775, fan4 shares pins with the fdc interface */
|
||||
|
@ -2013,8 +2017,6 @@ w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data,
|
|||
fan4min = fan4pin;
|
||||
}
|
||||
|
||||
superio_exit(sio_data->sioreg);
|
||||
|
||||
data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
|
||||
data->has_fan |= (fan3pin << 2);
|
||||
data->has_fan_min |= (fan3pin << 2);
|
||||
|
@ -2352,7 +2354,11 @@ static int w83627ehf_probe(struct platform_device *pdev)
|
|||
w83627ehf_init_device(data, sio_data->kind);
|
||||
|
||||
data->vrm = vid_which_vrm();
|
||||
superio_enter(sio_data->sioreg);
|
||||
|
||||
err = superio_enter(sio_data->sioreg);
|
||||
if (err)
|
||||
goto exit_release;
|
||||
|
||||
/* Read VID value */
|
||||
if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b ||
|
||||
sio_data->kind == nct6775 || sio_data->kind == nct6776) {
|
||||
|
@ -2364,8 +2370,10 @@ static int w83627ehf_probe(struct platform_device *pdev)
|
|||
superio_select(sio_data->sioreg, W83667HG_LD_VID);
|
||||
data->vid = superio_inb(sio_data->sioreg, 0xe3);
|
||||
err = device_create_file(dev, &dev_attr_cpu0_vid);
|
||||
if (err)
|
||||
if (err) {
|
||||
superio_exit(sio_data->sioreg);
|
||||
goto exit_release;
|
||||
}
|
||||
} else if (sio_data->kind != w83627uhg) {
|
||||
superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
|
||||
if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) {
|
||||
|
@ -2401,8 +2409,10 @@ static int w83627ehf_probe(struct platform_device *pdev)
|
|||
data->vid &= 0x3f;
|
||||
|
||||
err = device_create_file(dev, &dev_attr_cpu0_vid);
|
||||
if (err)
|
||||
if (err) {
|
||||
superio_exit(sio_data->sioreg);
|
||||
goto exit_release;
|
||||
}
|
||||
} else {
|
||||
dev_info(dev,
|
||||
"VID pins in output mode, CPU VID not available\n");
|
||||
|
@ -2424,10 +2434,10 @@ static int w83627ehf_probe(struct platform_device *pdev)
|
|||
pr_info("Enabled fan debounce for chip %s\n", data->name);
|
||||
}
|
||||
|
||||
superio_exit(sio_data->sioreg);
|
||||
|
||||
w83627ehf_check_fan_inputs(sio_data, data);
|
||||
|
||||
superio_exit(sio_data->sioreg);
|
||||
|
||||
/* Read fan clock dividers immediately */
|
||||
w83627ehf_update_fan_div_common(dev, data);
|
||||
|
||||
|
@ -2712,8 +2722,11 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
|
|||
|
||||
u16 val;
|
||||
const char *sio_name;
|
||||
int err;
|
||||
|
||||
superio_enter(sioaddr);
|
||||
err = superio_enter(sioaddr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (force_id)
|
||||
val = force_id;
|
||||
|
|
|
@ -337,7 +337,7 @@ struct hwmon_ops {
|
|||
int (*read)(struct device *dev, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, long *val);
|
||||
int (*read_string)(struct device *dev, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, char **str);
|
||||
u32 attr, int channel, const char **str);
|
||||
int (*write)(struct device *dev, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, long val);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue