hwmon: (pmbus) Add support for VID output voltage mode
[linux-2.6.git] / drivers / hwmon / pmbus / max8688.c
1 /*
2  * Hardware monitoring driver for Maxim MAX8688
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 #define MAX8688_MFG_STATUS              0xd8
29
30 #define MAX8688_STATUS_OC_FAULT         (1 << 4)
31 #define MAX8688_STATUS_OV_FAULT         (1 << 5)
32 #define MAX8688_STATUS_OV_WARNING       (1 << 8)
33 #define MAX8688_STATUS_UV_FAULT         (1 << 9)
34 #define MAX8688_STATUS_UV_WARNING       (1 << 10)
35 #define MAX8688_STATUS_UC_FAULT         (1 << 11)
36 #define MAX8688_STATUS_OC_WARNING       (1 << 12)
37 #define MAX8688_STATUS_OT_FAULT         (1 << 13)
38 #define MAX8688_STATUS_OT_WARNING       (1 << 14)
39
40 static int max8688_read_byte_data(struct i2c_client *client, int page, int reg)
41 {
42         int ret = 0;
43         int mfg_status;
44
45         if (page)
46                 return -EINVAL;
47
48         switch (reg) {
49         case PMBUS_STATUS_VOUT:
50                 mfg_status = pmbus_read_word_data(client, 0,
51                                                   MAX8688_MFG_STATUS);
52                 if (mfg_status < 0)
53                         return mfg_status;
54                 if (mfg_status & MAX8688_STATUS_UV_WARNING)
55                         ret |= PB_VOLTAGE_UV_WARNING;
56                 if (mfg_status & MAX8688_STATUS_UV_FAULT)
57                         ret |= PB_VOLTAGE_UV_FAULT;
58                 if (mfg_status & MAX8688_STATUS_OV_WARNING)
59                         ret |= PB_VOLTAGE_OV_WARNING;
60                 if (mfg_status & MAX8688_STATUS_OV_FAULT)
61                         ret |= PB_VOLTAGE_OV_FAULT;
62                 break;
63         case PMBUS_STATUS_IOUT:
64                 mfg_status = pmbus_read_word_data(client, 0,
65                                                   MAX8688_MFG_STATUS);
66                 if (mfg_status < 0)
67                         return mfg_status;
68                 if (mfg_status & MAX8688_STATUS_UC_FAULT)
69                         ret |= PB_IOUT_UC_FAULT;
70                 if (mfg_status & MAX8688_STATUS_OC_WARNING)
71                         ret |= PB_IOUT_OC_WARNING;
72                 if (mfg_status & MAX8688_STATUS_OC_FAULT)
73                         ret |= PB_IOUT_OC_FAULT;
74                 break;
75         case PMBUS_STATUS_TEMPERATURE:
76                 mfg_status = pmbus_read_word_data(client, 0,
77                                                   MAX8688_MFG_STATUS);
78                 if (mfg_status < 0)
79                         return mfg_status;
80                 if (mfg_status & MAX8688_STATUS_OT_WARNING)
81                         ret |= PB_TEMP_OT_WARNING;
82                 if (mfg_status & MAX8688_STATUS_OT_FAULT)
83                         ret |= PB_TEMP_OT_FAULT;
84                 break;
85         default:
86                 ret = -ENODATA;
87                 break;
88         }
89         return ret;
90 }
91
92 static struct pmbus_driver_info max8688_info = {
93         .pages = 1,
94         .format[PSC_VOLTAGE_IN] = direct,
95         .format[PSC_VOLTAGE_OUT] = direct,
96         .format[PSC_TEMPERATURE] = direct,
97         .format[PSC_CURRENT_OUT] = direct,
98         .m[PSC_VOLTAGE_IN] = 19995,
99         .b[PSC_VOLTAGE_IN] = 0,
100         .R[PSC_VOLTAGE_IN] = -1,
101         .m[PSC_VOLTAGE_OUT] = 19995,
102         .b[PSC_VOLTAGE_OUT] = 0,
103         .R[PSC_VOLTAGE_OUT] = -1,
104         .m[PSC_CURRENT_OUT] = 23109,
105         .b[PSC_CURRENT_OUT] = 0,
106         .R[PSC_CURRENT_OUT] = -2,
107         .m[PSC_TEMPERATURE] = -7612,
108         .b[PSC_TEMPERATURE] = 335,
109         .R[PSC_TEMPERATURE] = -3,
110         .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP
111                 | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
112                 | PMBUS_HAVE_STATUS_TEMP,
113         .read_byte_data = max8688_read_byte_data,
114 };
115
116 static int max8688_probe(struct i2c_client *client,
117                          const struct i2c_device_id *id)
118 {
119         return pmbus_do_probe(client, id, &max8688_info);
120 }
121
122 static int max8688_remove(struct i2c_client *client)
123 {
124         return pmbus_do_remove(client);
125 }
126
127 static const struct i2c_device_id max8688_id[] = {
128         {"max8688", 0},
129         { }
130 };
131
132 MODULE_DEVICE_TABLE(i2c, max8688_id);
133
134 /* This is the driver that will be inserted */
135 static struct i2c_driver max8688_driver = {
136         .driver = {
137                    .name = "max8688",
138                    },
139         .probe = max8688_probe,
140         .remove = max8688_remove,
141         .id_table = max8688_id,
142 };
143
144 static int __init max8688_init(void)
145 {
146         return i2c_add_driver(&max8688_driver);
147 }
148
149 static void __exit max8688_exit(void)
150 {
151         i2c_del_driver(&max8688_driver);
152 }
153
154 MODULE_AUTHOR("Guenter Roeck");
155 MODULE_DESCRIPTION("PMBus driver for Maxim MAX8688");
156 MODULE_LICENSE("GPL");
157 module_init(max8688_init);
158 module_exit(max8688_exit);