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"); | ||
