diff options
author | Guenter Roeck <linux@roeck-us.net> | 2015-08-22 03:49:37 -0400 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2015-12-18 11:20:59 -0500 |
commit | 8d28cd1b1f56f765dc691eeedf853d41f7aaafd3 (patch) | |
tree | 0d972d4ef2b26bdd4c0d598cefdcd33521e376c8 | |
parent | 2ff44072e34d5b6567d3d59b507e54c73b084db7 (diff) |
hwmon: (pmbus) Add client driver for LTC3815
LTC3815 is a Monolithic Synchronous DC/DC Step-Down Converter.
Cc: Michael Jones <mike@proclivis.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r-- | Documentation/hwmon/ltc3815 | 61 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/Kconfig | 10 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/Makefile | 1 | ||||
-rw-r--r-- | drivers/hwmon/pmbus/ltc3815.c | 215 |
4 files changed, 287 insertions, 0 deletions
diff --git a/Documentation/hwmon/ltc3815 b/Documentation/hwmon/ltc3815 new file mode 100644 index 000000000000..eb7db2d13587 --- /dev/null +++ b/Documentation/hwmon/ltc3815 | |||
@@ -0,0 +1,61 @@ | |||
1 | Kernel driver ltc3815 | ||
2 | ===================== | ||
3 | |||
4 | Supported chips: | ||
5 | * Linear Technology LTC3815 | ||
6 | Prefix: 'ltc3815' | ||
7 | Addresses scanned: - | ||
8 | Datasheet: http://www.linear.com/product/ltc3815 | ||
9 | |||
10 | Author: Guenter Roeck <linux@roeck-us.net> | ||
11 | |||
12 | |||
13 | Description | ||
14 | ----------- | ||
15 | |||
16 | LTC3815 is a Monolithic Synchronous DC/DC Step-Down Converter. | ||
17 | |||
18 | |||
19 | Usage Notes | ||
20 | ----------- | ||
21 | |||
22 | This driver does not probe for PMBus devices. You will have to instantiate | ||
23 | devices explicitly. | ||
24 | |||
25 | Example: the following commands will load the driver for an LTC3815 | ||
26 | at address 0x20 on I2C bus #1: | ||
27 | |||
28 | # modprobe ltc3815 | ||
29 | # echo ltc3815 0x20 > /sys/bus/i2c/devices/i2c-1/new_device | ||
30 | |||
31 | |||
32 | Sysfs attributes | ||
33 | ---------------- | ||
34 | |||
35 | in1_label "vin" | ||
36 | in1_input Measured input voltage. | ||
37 | in1_alarm Input voltage alarm. | ||
38 | in1_highest Highest input voltage. | ||
39 | in1_reset_history Reset input voltage history. | ||
40 | |||
41 | in2_label "vout1". | ||
42 | in2_input Measured output voltage. | ||
43 | in2_alarm Output voltage alarm. | ||
44 | in2_highest Highest output voltage. | ||
45 | in2_reset_history Reset output voltage history. | ||
46 | |||
47 | temp1_input Measured chip temperature. | ||
48 | temp1_alarm Temperature alarm. | ||
49 | temp1_highest Highest measured temperature. | ||
50 | temp1_reset_history Reset temperature history. | ||
51 | |||
52 | curr1_label "iin". | ||
53 | curr1_input Measured input current. | ||
54 | curr1_highest Highest input current. | ||
55 | curr1_reset_history Reset input current history. | ||
56 | |||
57 | curr2_label "iout1". | ||
58 | curr2_input Measured output current. | ||
59 | curr2_alarm Output current alarm. | ||
60 | curr2_highest Highest output current. | ||
61 | curr2_reset_history Reset output current history. | ||
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index df6ebb2b8f0f..7e5cc3d025ef 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig | |||
@@ -65,6 +65,16 @@ config SENSORS_LTC2978_REGULATOR | |||
65 | If you say yes here you get regulator support for Linear | 65 | If you say yes here you get regulator support for Linear |
66 | Technology LTC2974, LTC2977, LTC2978, LTC3880, LTC3883, and LTM4676. | 66 | Technology LTC2974, LTC2977, LTC2978, LTC3880, LTC3883, and LTM4676. |
67 | 67 | ||
68 | config SENSORS_LTC3815 | ||
69 | tristate "Linear Technologies LTC3815" | ||
70 | default n | ||
71 | help | ||
72 | If you say yes here you get hardware monitoring support for Linear | ||
73 | Technology LTC3815. | ||
74 | |||
75 | This driver can also be built as a module. If so, the module will | ||
76 | be called ltc3815. | ||
77 | |||
68 | config SENSORS_MAX16064 | 78 | config SENSORS_MAX16064 |
69 | tristate "Maxim MAX16064" | 79 | tristate "Maxim MAX16064" |
70 | default n | 80 | default n |
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile index bce046d37f02..562132054aaf 100644 --- a/drivers/hwmon/pmbus/Makefile +++ b/drivers/hwmon/pmbus/Makefile | |||
@@ -7,6 +7,7 @@ obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o | |||
7 | obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o | 7 | obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o |
8 | obj-$(CONFIG_SENSORS_LM25066) += lm25066.o | 8 | obj-$(CONFIG_SENSORS_LM25066) += lm25066.o |
9 | obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o | 9 | obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o |
10 | obj-$(CONFIG_SENSORS_LTC3815) += ltc3815.o | ||
10 | obj-$(CONFIG_SENSORS_MAX16064) += max16064.o | 11 | obj-$(CONFIG_SENSORS_MAX16064) += max16064.o |
11 | obj-$(CONFIG_SENSORS_MAX20751) += max20751.o | 12 | obj-$(CONFIG_SENSORS_MAX20751) += max20751.o |
12 | obj-$(CONFIG_SENSORS_MAX34440) += max34440.o | 13 | obj-$(CONFIG_SENSORS_MAX34440) += max34440.o |
diff --git a/drivers/hwmon/pmbus/ltc3815.c b/drivers/hwmon/pmbus/ltc3815.c new file mode 100644 index 000000000000..bb32e6276622 --- /dev/null +++ b/drivers/hwmon/pmbus/ltc3815.c | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | * Hardware monitoring driver for LTC3815 | ||
3 | * | ||
4 | * Copyright (c) 2015 Linear Technology | ||
5 | * Copyright (c) 2015 Guenter Roeck | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/err.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/jiffies.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include "pmbus.h" | ||
25 | |||
26 | #define LTC3815_MFR_IOUT_PEAK 0xd7 | ||
27 | #define LTC3815_MFR_VOUT_PEAK 0xdd | ||
28 | #define LTC3815_MFR_VIN_PEAK 0xde | ||
29 | #define LTC3815_MFR_TEMP_PEAK 0xdf | ||
30 | #define LTC3815_MFR_IIN_PEAK 0xe1 | ||
31 | #define LTC3815_MFR_SPECIAL_ID 0xe7 | ||
32 | |||
33 | #define LTC3815_ID 0x8000 | ||
34 | #define LTC3815_ID_MASK 0xff00 | ||
35 | |||
36 | static int ltc3815_read_byte_data(struct i2c_client *client, int page, int reg) | ||
37 | { | ||
38 | int ret; | ||
39 | |||
40 | switch (reg) { | ||
41 | case PMBUS_VOUT_MODE: | ||
42 | /* | ||
43 | * The chip returns 0x3e, suggesting VID mode with manufacturer | ||
44 | * specific VID codes. Since the output voltage is reported | ||
45 | * with a LSB of 0.5mV, override and report direct mode with | ||
46 | * appropriate coefficients. | ||
47 | */ | ||
48 | ret = 0x40; | ||
49 | break; | ||
50 | default: | ||
51 | ret = -ENODATA; | ||
52 | break; | ||
53 | } | ||
54 | return ret; | ||
55 | } | ||
56 | |||
57 | static int ltc3815_write_byte(struct i2c_client *client, int page, u8 reg) | ||
58 | { | ||
59 | int ret; | ||
60 | |||
61 | switch (reg) { | ||
62 | case PMBUS_CLEAR_FAULTS: | ||
63 | /* | ||
64 | * LTC3815 does not support the CLEAR_FAULTS command. | ||
65 | * Emulate it by clearing the status register. | ||
66 | */ | ||
67 | ret = pmbus_read_word_data(client, 0, PMBUS_STATUS_WORD); | ||
68 | if (ret > 0) { | ||
69 | pmbus_write_word_data(client, 0, PMBUS_STATUS_WORD, | ||
70 | ret); | ||
71 | ret = 0; | ||
72 | } | ||
73 | break; | ||
74 | default: | ||
75 | ret = -ENODATA; | ||
76 | break; | ||
77 | } | ||
78 | return ret; | ||
79 | } | ||
80 | |||
81 | static int ltc3815_read_word_data(struct i2c_client *client, int page, int reg) | ||
82 | { | ||
83 | int ret; | ||
84 | |||
85 | switch (reg) { | ||
86 | case PMBUS_VIRT_READ_VIN_MAX: | ||
87 | ret = pmbus_read_word_data(client, page, LTC3815_MFR_VIN_PEAK); | ||
88 | break; | ||
89 | case PMBUS_VIRT_READ_VOUT_MAX: | ||
90 | ret = pmbus_read_word_data(client, page, LTC3815_MFR_VOUT_PEAK); | ||
91 | break; | ||
92 | case PMBUS_VIRT_READ_TEMP_MAX: | ||
93 | ret = pmbus_read_word_data(client, page, LTC3815_MFR_TEMP_PEAK); | ||
94 | break; | ||
95 | case PMBUS_VIRT_READ_IOUT_MAX: | ||
96 | ret = pmbus_read_word_data(client, page, LTC3815_MFR_IOUT_PEAK); | ||
97 | break; | ||
98 | case PMBUS_VIRT_READ_IIN_MAX: | ||
99 | ret = pmbus_read_word_data(client, page, LTC3815_MFR_IIN_PEAK); | ||
100 | break; | ||
101 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | ||
102 | case PMBUS_VIRT_RESET_VIN_HISTORY: | ||
103 | case PMBUS_VIRT_RESET_TEMP_HISTORY: | ||
104 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | ||
105 | case PMBUS_VIRT_RESET_IIN_HISTORY: | ||
106 | ret = 0; | ||
107 | break; | ||
108 | default: | ||
109 | ret = -ENODATA; | ||
110 | break; | ||
111 | } | ||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | static int ltc3815_write_word_data(struct i2c_client *client, int page, | ||
116 | int reg, u16 word) | ||
117 | { | ||
118 | int ret; | ||
119 | |||
120 | switch (reg) { | ||
121 | case PMBUS_VIRT_RESET_IIN_HISTORY: | ||
122 | ret = pmbus_write_word_data(client, page, | ||
123 | LTC3815_MFR_IIN_PEAK, 0); | ||
124 | break; | ||
125 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | ||
126 | ret = pmbus_write_word_data(client, page, | ||
127 | LTC3815_MFR_IOUT_PEAK, 0); | ||
128 | break; | ||
129 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | ||
130 | ret = pmbus_write_word_data(client, page, | ||
131 | LTC3815_MFR_VOUT_PEAK, 0); | ||
132 | break; | ||
133 | case PMBUS_VIRT_RESET_VIN_HISTORY: | ||
134 | ret = pmbus_write_word_data(client, page, | ||
135 | LTC3815_MFR_VIN_PEAK, 0); | ||
136 | break; | ||
137 | case PMBUS_VIRT_RESET_TEMP_HISTORY: | ||
138 | ret = pmbus_write_word_data(client, page, | ||
139 | LTC3815_MFR_TEMP_PEAK, 0); | ||
140 | break; | ||
141 | default: | ||
142 | ret = -ENODATA; | ||
143 | break; | ||
144 | } | ||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | static const struct i2c_device_id ltc3815_id[] = { | ||
149 | {"ltc3815", 0}, | ||
150 | { } | ||
151 | }; | ||
152 | MODULE_DEVICE_TABLE(i2c, ltc3815_id); | ||
153 | |||
154 | static struct pmbus_driver_info ltc3815_info = { | ||
155 | .pages = 1, | ||
156 | .format[PSC_VOLTAGE_IN] = direct, | ||
157 | .format[PSC_VOLTAGE_OUT] = direct, | ||
158 | .format[PSC_CURRENT_IN] = direct, | ||
159 | .format[PSC_CURRENT_OUT] = direct, | ||
160 | .format[PSC_TEMPERATURE] = direct, | ||
161 | .m[PSC_VOLTAGE_IN] = 250, | ||
162 | .b[PSC_VOLTAGE_IN] = 0, | ||
163 | .R[PSC_VOLTAGE_IN] = 0, | ||
164 | .m[PSC_VOLTAGE_OUT] = 2, | ||
165 | .b[PSC_VOLTAGE_OUT] = 0, | ||
166 | .R[PSC_VOLTAGE_OUT] = 3, | ||
167 | .m[PSC_CURRENT_IN] = 1, | ||
168 | .b[PSC_CURRENT_IN] = 0, | ||
169 | .R[PSC_CURRENT_IN] = 2, | ||
170 | .m[PSC_CURRENT_OUT] = 1, | ||
171 | .b[PSC_CURRENT_OUT] = 0, | ||
172 | .R[PSC_CURRENT_OUT] = 2, | ||
173 | .m[PSC_TEMPERATURE] = 1, | ||
174 | .b[PSC_TEMPERATURE] = 0, | ||
175 | .R[PSC_TEMPERATURE] = 0, | ||
176 | .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_VOUT | | ||
177 | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP, | ||
178 | .read_byte_data = ltc3815_read_byte_data, | ||
179 | .read_word_data = ltc3815_read_word_data, | ||
180 | .write_byte = ltc3815_write_byte, | ||
181 | .write_word_data = ltc3815_write_word_data, | ||
182 | }; | ||
183 | |||
184 | static int ltc3815_probe(struct i2c_client *client, | ||
185 | const struct i2c_device_id *id) | ||
186 | { | ||
187 | int chip_id; | ||
188 | |||
189 | if (!i2c_check_functionality(client->adapter, | ||
190 | I2C_FUNC_SMBUS_READ_WORD_DATA)) | ||
191 | return -ENODEV; | ||
192 | |||
193 | chip_id = i2c_smbus_read_word_data(client, LTC3815_MFR_SPECIAL_ID); | ||
194 | if (chip_id < 0) | ||
195 | return chip_id; | ||
196 | if ((chip_id & LTC3815_ID_MASK) != LTC3815_ID) | ||
197 | return -ENODEV; | ||
198 | |||
199 | return pmbus_do_probe(client, id, <c3815_info); | ||
200 | } | ||
201 | |||
202 | static struct i2c_driver ltc3815_driver = { | ||
203 | .driver = { | ||
204 | .name = "ltc3815", | ||
205 | }, | ||
206 | .probe = ltc3815_probe, | ||
207 | .remove = pmbus_do_remove, | ||
208 | .id_table = ltc3815_id, | ||
209 | }; | ||
210 | |||
211 | module_i2c_driver(ltc3815_driver); | ||
212 | |||
213 | MODULE_AUTHOR("Guenter Roeck"); | ||
214 | MODULE_DESCRIPTION("PMBus driver for LTC3815"); | ||
215 | MODULE_LICENSE("GPL"); | ||