2019-01-31 23:14:07

by Jeremy Gebben

[permalink] [raw]
Subject: [PATCH v2 0/3] hwmon: (lm85) add LM96000 high freqency pwm support

Hi,

This patch adds support for the PWM frequencies from 22.5 to 30 kHz
available on the LM96000.

It looks like this chip has been supported for a long time, but wasn't
mentioned in the docs (which I have updated).

Also, it has been using the generic 'lm85' prefix, which I have not
changed to avoid breaking userspace or device tree files. AFAICT,
lm85_detect() will only return 'lm85' for LM96000 chips, so it doesn't
look like you can get a bare 'lm85' prefix with any other chips.

I stumbled on to a 10 year old thread discussing a patch which looks
like an early attempt to add support for this chip, which may be of
interest:
https://lm-sensors.lm-sensors.narkive.com/1SIwaMDT/patch-hwmon-lm96000-support

Thanks for reviewing,

Jeremy

Changes since v1:
- replace freq_map_mask with freq_map_size

Jeremy Gebben (3):
hwmon: (lm85) remove freq_map size hardcodes
hwmon: (lm85) Document the LM96000 as supported
hwmon: (lm85) add support for LM96000 high frequencies

Documentation/hwmon/lm85 | 9 ++++++++-
drivers/hwmon/lm85.c | 32 ++++++++++++++++++++++----------
2 files changed, 30 insertions(+), 11 deletions(-)

--
2.17.1



2019-01-31 23:07:26

by Jeremy Gebben

[permalink] [raw]
Subject: [PATCH v2 1/3] hwmon: (lm85) remove freq_map size hardcodes

Allow support for chips that support more than 8 frequencies.

Signed-off-by: Jeremy Gebben <[email protected]>
---
drivers/hwmon/lm85.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index 0a325878e..4b15193d1 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -198,13 +198,13 @@ static int RANGE_TO_REG(long range)
#define RANGE_FROM_REG(val) lm85_range_map[(val) & 0x0f]

/* These are the PWM frequency encodings */
-static const int lm85_freq_map[8] = { /* 1 Hz */
+static const int lm85_freq_map[] = { /* 1 Hz */
10, 15, 23, 30, 38, 47, 61, 94
};
-static const int adm1027_freq_map[8] = { /* 1 Hz */
+
+static const int adm1027_freq_map[] = { /* 1 Hz */
11, 15, 22, 29, 35, 44, 59, 88
};
-#define FREQ_MAP_LEN 8

static int FREQ_TO_REG(const int *map,
unsigned int map_size, unsigned long freq)
@@ -212,9 +212,9 @@ static int FREQ_TO_REG(const int *map,
return find_closest(freq, map, map_size);
}

-static int FREQ_FROM_REG(const int *map, u8 reg)
+static int FREQ_FROM_REG(const int *map, unsigned int map_size, u8 reg)
{
- return map[reg & 0x07];
+ return map[reg % map_size];
}

/*
@@ -296,6 +296,8 @@ struct lm85_data {
struct i2c_client *client;
const struct attribute_group *groups[6];
const int *freq_map;
+ unsigned int freq_map_size;
+
enum chips type;

bool has_vid5; /* true if VID5 is configured for ADT7463 or ADT7468 */
@@ -514,7 +516,7 @@ static struct lm85_data *lm85_update_device(struct device *dev)
data->autofan[i].config =
lm85_read_value(client, LM85_REG_AFAN_CONFIG(i));
val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i));
- data->pwm_freq[i] = val & 0x07;
+ data->pwm_freq[i] = val % data->freq_map_size;
data->zone[i].range = val >> 4;
data->autofan[i].min_pwm =
lm85_read_value(client, LM85_REG_AFAN_MINPWM(i));
@@ -791,7 +793,8 @@ static ssize_t show_pwm_freq(struct device *dev,
if (IS_ADT7468_HFPWM(data))
freq = 22500;
else
- freq = FREQ_FROM_REG(data->freq_map, data->pwm_freq[nr]);
+ freq = FREQ_FROM_REG(data->freq_map, data->freq_map_size,
+ data->pwm_freq[nr]);

return sprintf(buf, "%d\n", freq);
}
@@ -820,7 +823,7 @@ static ssize_t set_pwm_freq(struct device *dev,
lm85_write_value(client, ADT7468_REG_CFG5, data->cfg5);
} else { /* Low freq. mode */
data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map,
- FREQ_MAP_LEN, val);
+ data->freq_map_size, val);
lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
(data->zone[nr].range << 4)
| data->pwm_freq[nr]);
@@ -1196,7 +1199,7 @@ static ssize_t set_temp_auto_temp_min(struct device *dev,
TEMP_FROM_REG(data->zone[nr].limit));
lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
((data->zone[nr].range & 0x0f) << 4)
- | (data->pwm_freq[nr] & 0x07));
+ | data->pwm_freq[nr]);

mutex_unlock(&data->update_lock);
return count;
@@ -1232,7 +1235,7 @@ static ssize_t set_temp_auto_temp_max(struct device *dev,
val - min);
lm85_write_value(client, LM85_REG_AFAN_RANGE(nr),
((data->zone[nr].range & 0x0f) << 4)
- | (data->pwm_freq[nr] & 0x07));
+ | data->pwm_freq[nr]);
mutex_unlock(&data->update_lock);
return count;
}
@@ -1569,9 +1572,11 @@ static int lm85_probe(struct i2c_client *client, const struct i2c_device_id *id)
case emc6d103:
case emc6d103s:
data->freq_map = adm1027_freq_map;
+ data->freq_map_size = ARRAY_SIZE(adm1027_freq_map);
break;
default:
data->freq_map = lm85_freq_map;
+ data->freq_map_size = ARRAY_SIZE(lm85_freq_map);
}

/* Set the VRM version */
--
2.17.1


2019-01-31 23:09:05

by Jeremy Gebben

[permalink] [raw]
Subject: [PATCH v2 3/3] hwmon: (lm85) add support for LM96000 high frequencies

This chip expands the freqency field from 3 to 4 bits, to
add more frequencies in the 22.5 to 30 kHz ranges.

Signed-off-by: Jeremy Gebben <[email protected]>
---
Documentation/hwmon/lm85 | 3 +++
drivers/hwmon/lm85.c | 9 +++++++++
2 files changed, 12 insertions(+)

diff --git a/Documentation/hwmon/lm85 b/Documentation/hwmon/lm85
index 9f3a945d1..264874f09 100644
--- a/Documentation/hwmon/lm85
+++ b/Documentation/hwmon/lm85
@@ -140,6 +140,9 @@ of voltage and temperature channels.
SMSC EMC6D103S is similar to EMC6D103, but does not support pwm#_auto_pwm_minctl
and temp#_auto_temp_off.

+The LM96000 supports additional high frequency PWM modes (22.5 kHz, 24 kHz,
+25.7 kHz, 27.7 kHz and 30 kHz), which can be configured on a per-PWM basis.
+
Hardware Configurations
-----------------------

diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index 4b15193d1..88f08f4bc 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -202,6 +202,11 @@ static const int lm85_freq_map[] = { /* 1 Hz */
10, 15, 23, 30, 38, 47, 61, 94
};

+static const int lm85_high_freq_map[] = { /* 1 Hz */
+ 10, 15, 23, 30, 38, 47, 61, 94,
+ 22500, 24000, 25700, 25700, 27700, 27700, 30000, 30000
+};
+
static const int adm1027_freq_map[] = { /* 1 Hz */
11, 15, 22, 29, 35, 44, 59, 88
};
@@ -1574,6 +1579,10 @@ static int lm85_probe(struct i2c_client *client, const struct i2c_device_id *id)
data->freq_map = adm1027_freq_map;
data->freq_map_size = ARRAY_SIZE(adm1027_freq_map);
break;
+ case lm85:
+ data->freq_map = lm85_high_freq_map;
+ data->freq_map_size = ARRAY_SIZE(lm85_high_freq_map);
+ break;
default:
data->freq_map = lm85_freq_map;
data->freq_map_size = ARRAY_SIZE(lm85_freq_map);
--
2.17.1


2019-01-31 23:11:34

by Jeremy Gebben

[permalink] [raw]
Subject: [PATCH v2 2/3] hwmon: (lm85) Document the LM96000 as supported

It has been supported as a generic lm85 for quite some time.

Signed-off-by: Jeremy Gebben <[email protected]>
---
Documentation/hwmon/lm85 | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/hwmon/lm85 b/Documentation/hwmon/lm85
index 7c49feaa7..9f3a945d1 100644
--- a/Documentation/hwmon/lm85
+++ b/Documentation/hwmon/lm85
@@ -3,9 +3,13 @@ Kernel driver lm85

Supported chips:
* National Semiconductor LM85 (B and C versions)
- Prefix: 'lm85'
+ Prefix: 'lm85b' or 'lm85c'
Addresses scanned: I2C 0x2c, 0x2d, 0x2e
Datasheet: http://www.national.com/pf/LM/LM85.html
+ * Texas Instruments LM96000
+ Prefix: 'lm85'
+ Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+ Datasheet: http://www.ti.com/lit/ds/symlink/lm96000.pdf
* Analog Devices ADM1027
Prefix: 'adm1027'
Addresses scanned: I2C 0x2c, 0x2d, 0x2e
--
2.17.1


2019-02-01 22:38:51

by Guenter Roeck

[permalink] [raw]
Subject: Re: [PATCH v2 3/3] hwmon: (lm85) add support for LM96000 high frequencies

On Thu, Jan 31, 2019 at 03:06:17PM -0700, Jeremy Gebben wrote:
> This chip expands the freqency field from 3 to 4 bits, to
> add more frequencies in the 22.5 to 30 kHz ranges.
>
"This chip" -> LM96000

> Signed-off-by: Jeremy Gebben <[email protected]>
> ---
> Documentation/hwmon/lm85 | 3 +++
> drivers/hwmon/lm85.c | 9 +++++++++
> 2 files changed, 12 insertions(+)
>
> diff --git a/Documentation/hwmon/lm85 b/Documentation/hwmon/lm85
> index 9f3a945d1..264874f09 100644
> --- a/Documentation/hwmon/lm85
> +++ b/Documentation/hwmon/lm85
> @@ -140,6 +140,9 @@ of voltage and temperature channels.
> SMSC EMC6D103S is similar to EMC6D103, but does not support pwm#_auto_pwm_minctl
> and temp#_auto_temp_off.
>
> +The LM96000 supports additional high frequency PWM modes (22.5 kHz, 24 kHz,
> +25.7 kHz, 27.7 kHz and 30 kHz), which can be configured on a per-PWM basis.
> +
> Hardware Configurations
> -----------------------
>
> diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
> index 4b15193d1..88f08f4bc 100644
> --- a/drivers/hwmon/lm85.c
> +++ b/drivers/hwmon/lm85.c
> @@ -202,6 +202,11 @@ static const int lm85_freq_map[] = { /* 1 Hz */
> 10, 15, 23, 30, 38, 47, 61, 94
> };
>
> +static const int lm85_high_freq_map[] = { /* 1 Hz */
> + 10, 15, 23, 30, 38, 47, 61, 94,
> + 22500, 24000, 25700, 25700, 27700, 27700, 30000, 30000
> +};

Should be lm96000_freq_map.

> +
> static const int adm1027_freq_map[] = { /* 1 Hz */
> 11, 15, 22, 29, 35, 44, 59, 88
> };
> @@ -1574,6 +1579,10 @@ static int lm85_probe(struct i2c_client *client, const struct i2c_device_id *id)
> data->freq_map = adm1027_freq_map;
> data->freq_map_size = ARRAY_SIZE(adm1027_freq_map);
> break;
> + case lm85:
> + data->freq_map = lm85_high_freq_map;
> + data->freq_map_size = ARRAY_SIZE(lm85_high_freq_map);
> + break;

This is too generic. You'll have to introduce a 'lm96000' type
and use it. That should be straightforward since the lm96000
is already detected (and for some reason handled as lm85).

> default:
> data->freq_map = lm85_freq_map;
> data->freq_map_size = ARRAY_SIZE(lm85_freq_map);
> --
> 2.17.1
>