Skip to content

Commit

Permalink
hwmon: (mcp3021) Prepare MCP3021 driver to support other chips
Browse files Browse the repository at this point in the history
This Patch is to prepare the MCP3021 driver to support
other chips like the MCP3221. The hard defined chip data
is now stored within the data struct of each chip.

Signed-off-by: Sven Schuchmann <schuchmann@schleissheimer.de>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
  • Loading branch information
Sven Schuchmann authored and Guenter Roeck committed Sep 24, 2012
1 parent a916981 commit 8b662f3
Showing 1 changed file with 26 additions and 7 deletions.
33 changes: 26 additions & 7 deletions drivers/hwmon/mcp3021.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*
* Copyright (C) 2008-2009, 2012 Freescale Semiconductor, Inc.
* Author: Mingkai Hu <Mingkai.hu@freescale.com>
* Reworked by Sven Schuchmann <schuchmann@schleissheimer.de>
*
* This driver export the value of analog input voltage to sysfs, the
* voltage unit is mV. Through the sysfs interface, lm-sensors tool
Expand Down Expand Up @@ -34,16 +35,24 @@
#define MCP3021_OUTPUT_RES 10 /* 10-bit resolution */
#define MCP3021_OUTPUT_SCALE 4

enum chips {
mcp3021
};
/*
* Client data (each client gets its own)
*/
struct mcp3021_data {
struct device *hwmon_dev;
u32 vdd; /* device power supply */
u16 sar_shift;
u16 sar_mask;
u8 output_res;
u8 output_scale;
};

static int mcp3021_read16(struct i2c_client *client)
{
struct mcp3021_data *data = i2c_get_clientdata(client);
int ret;
u16 reg;
__be16 buf;
Expand All @@ -61,20 +70,20 @@ static int mcp3021_read16(struct i2c_client *client)
* The ten-bit output code is composed of the lower 4-bit of the
* first byte and the upper 6-bit of the second byte.
*/
reg = (reg >> MCP3021_SAR_SHIFT) & MCP3021_SAR_MASK;
reg = (reg >> data->sar_shift) & data->sar_mask;

return reg;
}

static inline u16 volts_from_reg(u16 vdd, u16 val)
static inline u16 volts_from_reg(struct mcp3021_data *data, u16 val)
{
if (val == 0)
return 0;

val = val * MCP3021_OUTPUT_SCALE - MCP3021_OUTPUT_SCALE / 2;
val = val * data->output_scale - data->output_scale / 2;

return val * DIV_ROUND_CLOSEST(vdd,
(1 << MCP3021_OUTPUT_RES) * MCP3021_OUTPUT_SCALE);
return val * DIV_ROUND_CLOSEST(data->vdd,
(1 << data->output_res) * data->output_scale);
}

static ssize_t show_in_input(struct device *dev, struct device_attribute *attr,
Expand All @@ -88,7 +97,8 @@ static ssize_t show_in_input(struct device *dev, struct device_attribute *attr,
if (reg < 0)
return reg;

in_input = volts_from_reg(data->vdd, reg);
in_input = volts_from_reg(data, reg);

return sprintf(buf, "%d\n", in_input);
}

Expand All @@ -110,6 +120,15 @@ static int mcp3021_probe(struct i2c_client *client,

i2c_set_clientdata(client, data);

switch (id->driver_data) {
case mcp3021:
data->sar_shift = MCP3021_SAR_SHIFT;
data->sar_mask = MCP3021_SAR_MASK;
data->output_res = MCP3021_OUTPUT_RES;
data->output_scale = MCP3021_OUTPUT_SCALE;
break;
}

if (client->dev.platform_data) {
data->vdd = *(u32 *)client->dev.platform_data;
if (data->vdd > MCP3021_VDD_MAX || data->vdd < MCP3021_VDD_MIN)
Expand Down Expand Up @@ -145,7 +164,7 @@ static int mcp3021_remove(struct i2c_client *client)
}

static const struct i2c_device_id mcp3021_id[] = {
{ "mcp3021", 0 },
{ "mcp3021", mcp3021 },
{ }
};
MODULE_DEVICE_TABLE(i2c, mcp3021_id);
Expand Down

0 comments on commit 8b662f3

Please sign in to comment.