aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/mcp3021.c
diff options
context:
space:
mode:
authorSven Schuchmann <schuchmann@schleissheimer.de>2012-09-21 07:04:21 -0400
committerGuenter Roeck <linux@roeck-us.net>2012-09-24 00:08:36 -0400
commit8b662f38e066d8fc1b73a8655da547c348206904 (patch)
tree8b4098e594041bf1df6dbc3e6c34b56cf3cef17d /drivers/hwmon/mcp3021.c
parenta91698135bef4e945b0eee1b676d6ea5085177dc (diff)
hwmon: (mcp3021) Prepare MCP3021 driver to support other chips
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>
Diffstat (limited to 'drivers/hwmon/mcp3021.c')
-rw-r--r--drivers/hwmon/mcp3021.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/drivers/hwmon/mcp3021.c b/drivers/hwmon/mcp3021.c
index 5162bb95bc61..d700b9271174 100644
--- a/drivers/hwmon/mcp3021.c
+++ b/drivers/hwmon/mcp3021.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Copyright (C) 2008-2009, 2012 Freescale Semiconductor, Inc. 4 * Copyright (C) 2008-2009, 2012 Freescale Semiconductor, Inc.
5 * Author: Mingkai Hu <Mingkai.hu@freescale.com> 5 * Author: Mingkai Hu <Mingkai.hu@freescale.com>
6 * Reworked by Sven Schuchmann <schuchmann@schleissheimer.de>
6 * 7 *
7 * This driver export the value of analog input voltage to sysfs, the 8 * This driver export the value of analog input voltage to sysfs, the
8 * voltage unit is mV. Through the sysfs interface, lm-sensors tool 9 * voltage unit is mV. Through the sysfs interface, lm-sensors tool
@@ -34,16 +35,24 @@
34#define MCP3021_OUTPUT_RES 10 /* 10-bit resolution */ 35#define MCP3021_OUTPUT_RES 10 /* 10-bit resolution */
35#define MCP3021_OUTPUT_SCALE 4 36#define MCP3021_OUTPUT_SCALE 4
36 37
38enum chips {
39 mcp3021
40};
37/* 41/*
38 * Client data (each client gets its own) 42 * Client data (each client gets its own)
39 */ 43 */
40struct mcp3021_data { 44struct mcp3021_data {
41 struct device *hwmon_dev; 45 struct device *hwmon_dev;
42 u32 vdd; /* device power supply */ 46 u32 vdd; /* device power supply */
47 u16 sar_shift;
48 u16 sar_mask;
49 u8 output_res;
50 u8 output_scale;
43}; 51};
44 52
45static int mcp3021_read16(struct i2c_client *client) 53static int mcp3021_read16(struct i2c_client *client)
46{ 54{
55 struct mcp3021_data *data = i2c_get_clientdata(client);
47 int ret; 56 int ret;
48 u16 reg; 57 u16 reg;
49 __be16 buf; 58 __be16 buf;
@@ -61,20 +70,20 @@ static int mcp3021_read16(struct i2c_client *client)
61 * The ten-bit output code is composed of the lower 4-bit of the 70 * The ten-bit output code is composed of the lower 4-bit of the
62 * first byte and the upper 6-bit of the second byte. 71 * first byte and the upper 6-bit of the second byte.
63 */ 72 */
64 reg = (reg >> MCP3021_SAR_SHIFT) & MCP3021_SAR_MASK; 73 reg = (reg >> data->sar_shift) & data->sar_mask;
65 74
66 return reg; 75 return reg;
67} 76}
68 77
69static inline u16 volts_from_reg(u16 vdd, u16 val) 78static inline u16 volts_from_reg(struct mcp3021_data *data, u16 val)
70{ 79{
71 if (val == 0) 80 if (val == 0)
72 return 0; 81 return 0;
73 82
74 val = val * MCP3021_OUTPUT_SCALE - MCP3021_OUTPUT_SCALE / 2; 83 val = val * data->output_scale - data->output_scale / 2;
75 84
76 return val * DIV_ROUND_CLOSEST(vdd, 85 return val * DIV_ROUND_CLOSEST(data->vdd,
77 (1 << MCP3021_OUTPUT_RES) * MCP3021_OUTPUT_SCALE); 86 (1 << data->output_res) * data->output_scale);
78} 87}
79 88
80static ssize_t show_in_input(struct device *dev, struct device_attribute *attr, 89static ssize_t show_in_input(struct device *dev, struct device_attribute *attr,
@@ -88,7 +97,8 @@ static ssize_t show_in_input(struct device *dev, struct device_attribute *attr,
88 if (reg < 0) 97 if (reg < 0)
89 return reg; 98 return reg;
90 99
91 in_input = volts_from_reg(data->vdd, reg); 100 in_input = volts_from_reg(data, reg);
101
92 return sprintf(buf, "%d\n", in_input); 102 return sprintf(buf, "%d\n", in_input);
93} 103}
94 104
@@ -110,6 +120,15 @@ static int mcp3021_probe(struct i2c_client *client,
110 120
111 i2c_set_clientdata(client, data); 121 i2c_set_clientdata(client, data);
112 122
123 switch (id->driver_data) {
124 case mcp3021:
125 data->sar_shift = MCP3021_SAR_SHIFT;
126 data->sar_mask = MCP3021_SAR_MASK;
127 data->output_res = MCP3021_OUTPUT_RES;
128 data->output_scale = MCP3021_OUTPUT_SCALE;
129 break;
130 }
131
113 if (client->dev.platform_data) { 132 if (client->dev.platform_data) {
114 data->vdd = *(u32 *)client->dev.platform_data; 133 data->vdd = *(u32 *)client->dev.platform_data;
115 if (data->vdd > MCP3021_VDD_MAX || data->vdd < MCP3021_VDD_MIN) 134 if (data->vdd > MCP3021_VDD_MAX || data->vdd < MCP3021_VDD_MIN)
@@ -145,7 +164,7 @@ static int mcp3021_remove(struct i2c_client *client)
145} 164}
146 165
147static const struct i2c_device_id mcp3021_id[] = { 166static const struct i2c_device_id mcp3021_id[] = {
148 { "mcp3021", 0 }, 167 { "mcp3021", mcp3021 },
149 { } 168 { }
150}; 169};
151MODULE_DEVICE_TABLE(i2c, mcp3021_id); 170MODULE_DEVICE_TABLE(i2c, mcp3021_id);