Skip to content

Commit

Permalink
hwmon: emc2305: fixups for driver submitted to mailing lists
Browse files Browse the repository at this point in the history
The driver had a number of issues, checkpatch warnings/errors,
and other limitations, so fix these up to make it usable.

Signed-off-by: Phil Elwell <[email protected]>
Signed-off-by: Dave Stevenson <[email protected]>
  • Loading branch information
pelwell committed Oct 20, 2022
1 parent ab116bf commit 727fb29
Showing 1 changed file with 72 additions and 8 deletions.
80 changes: 72 additions & 8 deletions drivers/hwmon/emc2305.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
static const unsigned short
emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d, I2C_CLIENT_END };

#define EMC2305_REG_FAN_STATUS 0x24
#define EMC2305_REG_FAN_STALL_STATUS 0x25
#define EMC2305_REG_DRIVE_FAIL_STATUS 0x27
#define EMC2305_REG_DEVICE 0xfd
#define EMC2305_REG_VENDOR 0xfe
#define EMC2305_FAN_MAX 0xff
#define EMC2305_FAN_MIN 0x00
#define EMC2305_FAN_MAX_STATE 10
#define EMC2305_DEVICE 0x34
#define EMC2305_VENDOR 0x5d
#define EMC2305_REG_PRODUCT_ID 0xfd
#define EMC2305_TACH_REGS_UNUSE_BITS 3
Expand All @@ -40,6 +40,7 @@ emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d, I2C_CLIENT_EN
#define EMC2305_RPM_FACTOR 3932160

#define EMC2305_REG_FAN_DRIVE(n) (0x30 + 0x10 * (n))
#define EMC2305_REG_FAN_CFG(n) (0x32 + 0x10 * (n))
#define EMC2305_REG_FAN_MIN_DRIVE(n) (0x38 + 0x10 * (n))
#define EMC2305_REG_FAN_TACH(n) (0x3e + 0x10 * (n))

Expand All @@ -59,6 +60,15 @@ static const struct i2c_device_id emc2305_ids[] = {
};
MODULE_DEVICE_TABLE(i2c, emc2305_ids);

static const struct of_device_id emc2305_dt_ids[] = {
{ .compatible = "microchip,emc2305" },
{ .compatible = "microchip,emc2303" },
{ .compatible = "microchip,emc2302" },
{ .compatible = "microchip,emc2301" },
{ }
};
MODULE_DEVICE_TABLE(of, emc2305_dt_ids);

/**
* @cdev: cooling device;
* @curr_state: cooling current state;
Expand Down Expand Up @@ -102,6 +112,7 @@ struct emc2305_data {
u8 pwm_num;
bool pwm_separate;
u8 pwm_min[EMC2305_PWM_MAX];
u8 pwm_max;
struct emc2305_cdev_data cdev_data[EMC2305_PWM_MAX];
};

Expand Down Expand Up @@ -263,7 +274,7 @@ static int emc2305_set_pwm(struct device *dev, long val, int channel)
struct i2c_client *client = data->client;
int ret;

if (val < data->pwm_min[channel] || val > EMC2305_FAN_MAX)
if (val < data->pwm_min[channel] || val > data->pwm_max)
return -EINVAL;

ret = i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_DRIVE(channel), val);
Expand All @@ -274,6 +285,49 @@ static int emc2305_set_pwm(struct device *dev, long val, int channel)
return 0;
}

static int emc2305_get_tz_of(struct device *dev)
{
struct device_node *np = dev->of_node;
struct emc2305_data *data = dev_get_drvdata(dev);
int ret = 0;
u32 val;
int i;

/* OF parameters are optional - overwrite default setting
* if some of them are provided.
*/

ret = of_property_read_u32(np, "emc2305,cooling-levels", &val);
if (!ret)
data->max_state = (u8)val;
else if (ret != -EINVAL)
return ret;

ret = of_property_read_u32(np, "emc2305,pwm-max", &val);
if (!ret)
data->pwm_max = (u8)val;
else if (ret != -EINVAL)
return ret;

ret = of_property_read_u32(np, "emc2305,pwm-min", &val);
if (!ret)
for (i = 0; i < EMC2305_PWM_MAX; i++)
data->pwm_min[i] = (u8)val;
else if (ret != -EINVAL)
return ret;

/* Not defined or 0 means one thermal zone over all cooling devices.
* Otherwise - separated thermal zones for each PWM channel.
*/
ret = of_property_read_u32(np, "emc2305,pwm-channel", &val);
if (!ret)
data->pwm_separate = (val != 0);
else if (ret != -EINVAL)
return ret;

return 0;
}

static int emc2305_set_single_tz(struct device *dev, int idx)
{
struct emc2305_data *data = dev_get_drvdata(dev);
Expand Down Expand Up @@ -524,7 +578,7 @@ static int emc2305_probe(struct i2c_client *client, const struct i2c_device_id *
struct device *dev = &client->dev;
struct emc2305_data *data;
struct emc2305_platform_data *pdata;
int vendor, device;
int vendor;
int ret;
int i;

Expand All @@ -535,10 +589,6 @@ static int emc2305_probe(struct i2c_client *client, const struct i2c_device_id *
if (vendor != EMC2305_VENDOR)
return -ENODEV;

device = i2c_smbus_read_byte_data(client, EMC2305_REG_DEVICE);
if (device != EMC2305_DEVICE)
return -ENODEV;

data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
Expand Down Expand Up @@ -566,11 +616,18 @@ static int emc2305_probe(struct i2c_client *client, const struct i2c_device_id *
data->pwm_separate = pdata->pwm_separate;
for (i = 0; i < EMC2305_PWM_MAX; i++)
data->pwm_min[i] = pdata->pwm_min[i];
data->pwm_max = EMC2305_FAN_MAX;
} else {
data->max_state = EMC2305_FAN_MAX_STATE;
data->pwm_separate = false;
for (i = 0; i < EMC2305_PWM_MAX; i++)
data->pwm_min[i] = EMC2305_FAN_MIN;
data->pwm_max = EMC2305_FAN_MAX;
if (dev->of_node) {
ret = emc2305_get_tz_of(dev);
if (ret < 0)
return ret;
}
}

data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "emc2305", data,
Expand All @@ -591,6 +648,12 @@ static int emc2305_probe(struct i2c_client *client, const struct i2c_device_id *
return ret;
}

/* Acknowledge any existing faults. Stops the device responding on the
* SMBus alert address.
*/
i2c_smbus_read_byte_data(client, EMC2305_REG_FAN_STALL_STATUS);
i2c_smbus_read_byte_data(client, EMC2305_REG_FAN_STATUS);

return 0;
}

Expand All @@ -606,6 +669,7 @@ static struct i2c_driver emc2305_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "emc2305",
.of_match_table = emc2305_dt_ids,
},
.probe = emc2305_probe,
.remove = emc2305_remove,
Expand Down

0 comments on commit 727fb29

Please sign in to comment.