Merge tag 'rproc-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/andersson...
[linux-2.6-microblaze.git] / drivers / hwmon / pmbus / ltc3815.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Hardware monitoring driver for LTC3815
4  *
5  * Copyright (c) 2015 Linear Technology
6  * Copyright (c) 2015 Guenter Roeck
7  */
8
9 #include <linux/err.h>
10 #include <linux/i2c.h>
11 #include <linux/init.h>
12 #include <linux/jiffies.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include "pmbus.h"
16
17 #define LTC3815_MFR_IOUT_PEAK   0xd7
18 #define LTC3815_MFR_VOUT_PEAK   0xdd
19 #define LTC3815_MFR_VIN_PEAK    0xde
20 #define LTC3815_MFR_TEMP_PEAK   0xdf
21 #define LTC3815_MFR_IIN_PEAK    0xe1
22 #define LTC3815_MFR_SPECIAL_ID  0xe7
23
24 #define LTC3815_ID              0x8000
25 #define LTC3815_ID_MASK         0xff00
26
27 static int ltc3815_read_byte_data(struct i2c_client *client, int page, int reg)
28 {
29         int ret;
30
31         switch (reg) {
32         case PMBUS_VOUT_MODE:
33                 /*
34                  * The chip returns 0x3e, suggesting VID mode with manufacturer
35                  * specific VID codes. Since the output voltage is reported
36                  * with a LSB of 0.5mV, override and report direct mode with
37                  * appropriate coefficients.
38                  */
39                 ret = 0x40;
40                 break;
41         default:
42                 ret = -ENODATA;
43                 break;
44         }
45         return ret;
46 }
47
48 static int ltc3815_write_byte(struct i2c_client *client, int page, u8 reg)
49 {
50         int ret;
51
52         switch (reg) {
53         case PMBUS_CLEAR_FAULTS:
54                 /*
55                  * LTC3815 does not support the CLEAR_FAULTS command.
56                  * Emulate it by clearing the status register.
57                  */
58                 ret = pmbus_read_word_data(client, 0, 0xff, PMBUS_STATUS_WORD);
59                 if (ret > 0) {
60                         pmbus_write_word_data(client, 0, PMBUS_STATUS_WORD,
61                                               ret);
62                         ret = 0;
63                 }
64                 break;
65         default:
66                 ret = -ENODATA;
67                 break;
68         }
69         return ret;
70 }
71
72 static int ltc3815_read_word_data(struct i2c_client *client, int page,
73                                   int phase, int reg)
74 {
75         int ret;
76
77         switch (reg) {
78         case PMBUS_VIRT_READ_VIN_MAX:
79                 ret = pmbus_read_word_data(client, page, phase,
80                                            LTC3815_MFR_VIN_PEAK);
81                 break;
82         case PMBUS_VIRT_READ_VOUT_MAX:
83                 ret = pmbus_read_word_data(client, page, phase,
84                                            LTC3815_MFR_VOUT_PEAK);
85                 break;
86         case PMBUS_VIRT_READ_TEMP_MAX:
87                 ret = pmbus_read_word_data(client, page, phase,
88                                            LTC3815_MFR_TEMP_PEAK);
89                 break;
90         case PMBUS_VIRT_READ_IOUT_MAX:
91                 ret = pmbus_read_word_data(client, page, phase,
92                                            LTC3815_MFR_IOUT_PEAK);
93                 break;
94         case PMBUS_VIRT_READ_IIN_MAX:
95                 ret = pmbus_read_word_data(client, page, phase,
96                                            LTC3815_MFR_IIN_PEAK);
97                 break;
98         case PMBUS_VIRT_RESET_VOUT_HISTORY:
99         case PMBUS_VIRT_RESET_VIN_HISTORY:
100         case PMBUS_VIRT_RESET_TEMP_HISTORY:
101         case PMBUS_VIRT_RESET_IOUT_HISTORY:
102         case PMBUS_VIRT_RESET_IIN_HISTORY:
103                 ret = 0;
104                 break;
105         default:
106                 ret = -ENODATA;
107                 break;
108         }
109         return ret;
110 }
111
112 static int ltc3815_write_word_data(struct i2c_client *client, int page,
113                                    int reg, u16 word)
114 {
115         int ret;
116
117         switch (reg) {
118         case PMBUS_VIRT_RESET_IIN_HISTORY:
119                 ret = pmbus_write_word_data(client, page,
120                                             LTC3815_MFR_IIN_PEAK, 0);
121                 break;
122         case PMBUS_VIRT_RESET_IOUT_HISTORY:
123                 ret = pmbus_write_word_data(client, page,
124                                             LTC3815_MFR_IOUT_PEAK, 0);
125                 break;
126         case PMBUS_VIRT_RESET_VOUT_HISTORY:
127                 ret = pmbus_write_word_data(client, page,
128                                             LTC3815_MFR_VOUT_PEAK, 0);
129                 break;
130         case PMBUS_VIRT_RESET_VIN_HISTORY:
131                 ret = pmbus_write_word_data(client, page,
132                                             LTC3815_MFR_VIN_PEAK, 0);
133                 break;
134         case PMBUS_VIRT_RESET_TEMP_HISTORY:
135                 ret = pmbus_write_word_data(client, page,
136                                             LTC3815_MFR_TEMP_PEAK, 0);
137                 break;
138         default:
139                 ret = -ENODATA;
140                 break;
141         }
142         return ret;
143 }
144
145 static const struct i2c_device_id ltc3815_id[] = {
146         {"ltc3815", 0},
147         { }
148 };
149 MODULE_DEVICE_TABLE(i2c, ltc3815_id);
150
151 static struct pmbus_driver_info ltc3815_info = {
152         .pages = 1,
153         .format[PSC_VOLTAGE_IN] = direct,
154         .format[PSC_VOLTAGE_OUT] = direct,
155         .format[PSC_CURRENT_IN] = direct,
156         .format[PSC_CURRENT_OUT] = direct,
157         .format[PSC_TEMPERATURE] = direct,
158         .m[PSC_VOLTAGE_IN] = 250,
159         .b[PSC_VOLTAGE_IN] = 0,
160         .R[PSC_VOLTAGE_IN] = 0,
161         .m[PSC_VOLTAGE_OUT] = 2,
162         .b[PSC_VOLTAGE_OUT] = 0,
163         .R[PSC_VOLTAGE_OUT] = 3,
164         .m[PSC_CURRENT_IN] = 1,
165         .b[PSC_CURRENT_IN] = 0,
166         .R[PSC_CURRENT_IN] = 2,
167         .m[PSC_CURRENT_OUT] = 1,
168         .b[PSC_CURRENT_OUT] = 0,
169         .R[PSC_CURRENT_OUT] = 2,
170         .m[PSC_TEMPERATURE] = 1,
171         .b[PSC_TEMPERATURE] = 0,
172         .R[PSC_TEMPERATURE] = 0,
173         .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_VOUT |
174                 PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP,
175         .read_byte_data = ltc3815_read_byte_data,
176         .read_word_data = ltc3815_read_word_data,
177         .write_byte = ltc3815_write_byte,
178         .write_word_data = ltc3815_write_word_data,
179 };
180
181 static int ltc3815_probe(struct i2c_client *client)
182 {
183         int chip_id;
184
185         if (!i2c_check_functionality(client->adapter,
186                                      I2C_FUNC_SMBUS_READ_WORD_DATA))
187                 return -ENODEV;
188
189         chip_id = i2c_smbus_read_word_data(client, LTC3815_MFR_SPECIAL_ID);
190         if (chip_id < 0)
191                 return chip_id;
192         if ((chip_id & LTC3815_ID_MASK) != LTC3815_ID)
193                 return -ENODEV;
194
195         return pmbus_do_probe(client, &ltc3815_info);
196 }
197
198 static struct i2c_driver ltc3815_driver = {
199         .driver = {
200                    .name = "ltc3815",
201                    },
202         .probe_new = ltc3815_probe,
203         .id_table = ltc3815_id,
204 };
205
206 module_i2c_driver(ltc3815_driver);
207
208 MODULE_AUTHOR("Guenter Roeck");
209 MODULE_DESCRIPTION("PMBus driver for LTC3815");
210 MODULE_LICENSE("GPL");