diff options
author | Guenter Roeck <guenter.roeck@ericsson.com> | 2011-01-26 23:15:27 -0500 |
---|---|---|
committer | Guenter Roeck <guenter.roeck@ericsson.com> | 2011-03-15 01:39:07 -0400 |
commit | a3eeb453539d7ad9c0d8cced1e0883a6a8ed18f3 (patch) | |
tree | fad179f16a410ef12f694c146a2a3db1d26ffed9 /drivers/hwmon/max34440.c | |
parent | dcb7d0668b178deec81db128b9fbab29190063c4 (diff) |
hwmon: (pmbus) Add support for Maxim MAX34440/MAX34441
Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
Acked-by: Jonathan Cameron <jic23@cam.ac.uk>
Diffstat (limited to 'drivers/hwmon/max34440.c')
-rw-r--r-- | drivers/hwmon/max34440.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/drivers/hwmon/max34440.c b/drivers/hwmon/max34440.c new file mode 100644 index 000000000000..992b701b4c5e --- /dev/null +++ b/drivers/hwmon/max34440.c | |||
@@ -0,0 +1,199 @@ | |||
1 | /* | ||
2 | * Hardware monitoring driver for Maxim MAX34440/MAX34441 | ||
3 | * | ||
4 | * Copyright (c) 2011 Ericsson AB. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/i2c.h> | ||
26 | #include "pmbus.h" | ||
27 | |||
28 | enum chips { max34440, max34441 }; | ||
29 | |||
30 | #define MAX34440_STATUS_OC_WARN (1 << 0) | ||
31 | #define MAX34440_STATUS_OC_FAULT (1 << 1) | ||
32 | #define MAX34440_STATUS_OT_FAULT (1 << 5) | ||
33 | #define MAX34440_STATUS_OT_WARN (1 << 6) | ||
34 | |||
35 | static int max34440_get_status(struct i2c_client *client, int page, int reg) | ||
36 | { | ||
37 | int ret; | ||
38 | int mfg_status; | ||
39 | |||
40 | ret = pmbus_set_page(client, page); | ||
41 | if (ret < 0) | ||
42 | return ret; | ||
43 | |||
44 | switch (reg) { | ||
45 | case PMBUS_STATUS_IOUT: | ||
46 | mfg_status = pmbus_read_word_data(client, 0, | ||
47 | PMBUS_STATUS_MFR_SPECIFIC); | ||
48 | if (mfg_status < 0) | ||
49 | return mfg_status; | ||
50 | if (mfg_status & MAX34440_STATUS_OC_WARN) | ||
51 | ret |= PB_IOUT_OC_WARNING; | ||
52 | if (mfg_status & MAX34440_STATUS_OC_FAULT) | ||
53 | ret |= PB_IOUT_OC_FAULT; | ||
54 | break; | ||
55 | case PMBUS_STATUS_TEMPERATURE: | ||
56 | mfg_status = pmbus_read_word_data(client, 0, | ||
57 | PMBUS_STATUS_MFR_SPECIFIC); | ||
58 | if (mfg_status < 0) | ||
59 | return mfg_status; | ||
60 | if (mfg_status & MAX34440_STATUS_OT_WARN) | ||
61 | ret |= PB_TEMP_OT_WARNING; | ||
62 | if (mfg_status & MAX34440_STATUS_OT_FAULT) | ||
63 | ret |= PB_TEMP_OT_FAULT; | ||
64 | break; | ||
65 | default: | ||
66 | ret = -ENODATA; | ||
67 | break; | ||
68 | } | ||
69 | return ret; | ||
70 | } | ||
71 | |||
72 | static struct pmbus_driver_info max34440_info[] = { | ||
73 | [max34440] = { | ||
74 | .pages = 14, | ||
75 | .direct[PSC_VOLTAGE_IN] = true, | ||
76 | .direct[PSC_VOLTAGE_OUT] = true, | ||
77 | .direct[PSC_TEMPERATURE] = true, | ||
78 | .direct[PSC_CURRENT_OUT] = true, | ||
79 | .m[PSC_VOLTAGE_IN] = 1, | ||
80 | .b[PSC_VOLTAGE_IN] = 0, | ||
81 | .R[PSC_VOLTAGE_IN] = 3, /* R = 0 in datasheet reflects mV */ | ||
82 | .m[PSC_VOLTAGE_OUT] = 1, | ||
83 | .b[PSC_VOLTAGE_OUT] = 0, | ||
84 | .R[PSC_VOLTAGE_OUT] = 3, /* R = 0 in datasheet reflects mV */ | ||
85 | .m[PSC_CURRENT_OUT] = 1, | ||
86 | .b[PSC_CURRENT_OUT] = 0, | ||
87 | .R[PSC_CURRENT_OUT] = 3, /* R = 0 in datasheet reflects mA */ | ||
88 | .m[PSC_TEMPERATURE] = 1, | ||
89 | .b[PSC_TEMPERATURE] = 0, | ||
90 | .R[PSC_TEMPERATURE] = 2, | ||
91 | .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
92 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, | ||
93 | .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
94 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, | ||
95 | .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
96 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, | ||
97 | .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
98 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, | ||
99 | .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
100 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, | ||
101 | .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
102 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, | ||
103 | .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
104 | .func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
105 | .func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
106 | .func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
107 | .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
108 | .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
109 | .func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
110 | .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
111 | .get_status = max34440_get_status, | ||
112 | }, | ||
113 | [max34441] = { | ||
114 | .pages = 12, | ||
115 | .direct[PSC_VOLTAGE_IN] = true, | ||
116 | .direct[PSC_VOLTAGE_OUT] = true, | ||
117 | .direct[PSC_TEMPERATURE] = true, | ||
118 | .direct[PSC_CURRENT_OUT] = true, | ||
119 | .direct[PSC_FAN] = true, | ||
120 | .m[PSC_VOLTAGE_IN] = 1, | ||
121 | .b[PSC_VOLTAGE_IN] = 0, | ||
122 | .R[PSC_VOLTAGE_IN] = 3, | ||
123 | .m[PSC_VOLTAGE_OUT] = 1, | ||
124 | .b[PSC_VOLTAGE_OUT] = 0, | ||
125 | .R[PSC_VOLTAGE_OUT] = 3, | ||
126 | .m[PSC_CURRENT_OUT] = 1, | ||
127 | .b[PSC_CURRENT_OUT] = 0, | ||
128 | .R[PSC_CURRENT_OUT] = 3, | ||
129 | .m[PSC_TEMPERATURE] = 1, | ||
130 | .b[PSC_TEMPERATURE] = 0, | ||
131 | .R[PSC_TEMPERATURE] = 2, | ||
132 | .m[PSC_FAN] = 1, | ||
133 | .b[PSC_FAN] = 0, | ||
134 | .R[PSC_FAN] = 0, | ||
135 | .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
136 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, | ||
137 | .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
138 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, | ||
139 | .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
140 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, | ||
141 | .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
142 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, | ||
143 | .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | ||
144 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, | ||
145 | .func[5] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12, | ||
146 | .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
147 | .func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
148 | .func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
149 | .func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
150 | .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
151 | .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, | ||
152 | .get_status = max34440_get_status, | ||
153 | }, | ||
154 | }; | ||
155 | |||
156 | static int max34440_probe(struct i2c_client *client, | ||
157 | const struct i2c_device_id *id) | ||
158 | { | ||
159 | return pmbus_do_probe(client, id, &max34440_info[id->driver_data]); | ||
160 | } | ||
161 | |||
162 | static int max34440_remove(struct i2c_client *client) | ||
163 | { | ||
164 | return pmbus_do_remove(client); | ||
165 | } | ||
166 | |||
167 | static const struct i2c_device_id max34440_id[] = { | ||
168 | {"max34440", max34440}, | ||
169 | {"max34441", max34441}, | ||
170 | {} | ||
171 | }; | ||
172 | |||
173 | MODULE_DEVICE_TABLE(i2c, max34440_id); | ||
174 | |||
175 | /* This is the driver that will be inserted */ | ||
176 | static struct i2c_driver max34440_driver = { | ||
177 | .driver = { | ||
178 | .name = "max34440", | ||
179 | }, | ||
180 | .probe = max34440_probe, | ||
181 | .remove = max34440_remove, | ||
182 | .id_table = max34440_id, | ||
183 | }; | ||
184 | |||
185 | static int __init max34440_init(void) | ||
186 | { | ||
187 | return i2c_add_driver(&max34440_driver); | ||
188 | } | ||
189 | |||
190 | static void __exit max34440_exit(void) | ||
191 | { | ||
192 | i2c_del_driver(&max34440_driver); | ||
193 | } | ||
194 | |||
195 | MODULE_AUTHOR("Guenter Roeck"); | ||
196 | MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441"); | ||
197 | MODULE_LICENSE("GPL"); | ||
198 | module_init(max34440_init); | ||
199 | module_exit(max34440_exit); | ||