Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the coreboot project. |
| 3 | * |
| 4 | * Copyright (C) 2012 Advanced Micro Devices, Inc. |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 5 | * Copyright (C) 2015 Raptor Engineering |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 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; version 2 of the License. |
| 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. |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 15 | */ |
| 16 | |
| 17 | #include <stdint.h> |
| 18 | #include <arch/cpu.h> |
| 19 | #include <console/console.h> |
| 20 | #include <device/device.h> |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 21 | #include "w83795.h" |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 22 | #include <device/smbus.h> |
| 23 | #include "chip.h" |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 24 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 25 | static int w83795_set_bank(struct device *dev, uint8_t bank) |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 26 | { |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 27 | return smbus_write_byte(dev, W83795_REG_BANKSEL, bank); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 28 | } |
| 29 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 30 | static uint8_t w83795_read(struct device *dev, uint16_t reg) |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 31 | { |
Edward O'Callaghan | 660ec7c | 2015-01-14 02:14:21 +1100 | [diff] [blame] | 32 | int ret; |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 33 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 34 | ret = w83795_set_bank(dev, reg >> 8); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 35 | if (ret < 0) { |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 36 | printk(BIOS_DEBUG, "read failed to set bank %x\n", reg >> 8); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 37 | return -1; |
| 38 | } |
| 39 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 40 | ret = smbus_read_byte(dev, reg & 0xff); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 41 | return ret; |
| 42 | } |
| 43 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 44 | static uint8_t w83795_write(struct device *dev, uint16_t reg, uint8_t value) |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 45 | { |
Edward O'Callaghan | 660ec7c | 2015-01-14 02:14:21 +1100 | [diff] [blame] | 46 | int err; |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 47 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 48 | err = w83795_set_bank(dev, reg >> 8); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 49 | if (err < 0) { |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 50 | printk(BIOS_DEBUG, "write failed to set bank %x\n", reg >> 8); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 51 | return -1; |
| 52 | } |
| 53 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 54 | err = smbus_write_byte(dev, reg & 0xff, value); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 55 | return err; |
| 56 | } |
| 57 | |
| 58 | /* |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 59 | * Configure Digital Temperature Sensor |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 60 | */ |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 61 | static void w83795_dts_configure(struct device *dev, uint8_t dts_src) |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 62 | { |
| 63 | u8 val; |
| 64 | |
| 65 | /* DIS */ |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 66 | val = w83795_read(dev, W83795_REG_DTSC) & ~0x1; |
| 67 | val |= dts_src & 0x1; |
| 68 | w83795_write(dev, W83795_REG_DTSC, val); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 69 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 70 | /* TODO |
| 71 | * Determine if DTS interface needs to be reset |
| 72 | * (W83795_REG_DTSC bit 7) before operation. |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 73 | */ |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 74 | } |
| 75 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 76 | static u32 w83795_set_fan_mode(struct device *dev, w83795_fan_mode_t mode) |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 77 | { |
| 78 | if (mode == SPEED_CRUISE_MODE) { |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 79 | w83795_write(dev, W83795_REG_FCMS1, 0xFF); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 80 | printk(BIOS_INFO, "W83795G/ADG work in Speed Cruise Mode\n"); |
| 81 | } else { |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 82 | w83795_write(dev, W83795_REG_FCMS1, 0x00); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 83 | if (mode == THERMAL_CRUISE_MODE) { |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 84 | w83795_write(dev, W83795_REG_FCMS2, 0x00); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 85 | printk(BIOS_INFO, "W83795G/ADG work in Thermal Cruise Mode\n"); |
| 86 | } else if (mode == SMART_FAN_MODE) { |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 87 | w83795_write(dev, W83795_REG_FCMS2, 0x3F); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 88 | printk(BIOS_INFO, "W83795G/ADG work in Smart Fan Mode\n"); |
| 89 | } else { |
| 90 | printk(BIOS_INFO, "W83795G/ADG work in Manual Mode\n"); |
| 91 | return -1; |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | return 0; |
| 96 | } |
| 97 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 98 | static void w83795_set_fan(struct device *dev, w83795_fan_mode_t mode) |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 99 | { |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 100 | /* set fan output controlled mode (FCMS)*/ |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 101 | w83795_set_fan_mode(dev, mode); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 102 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 103 | if (mode == SMART_FAN_MODE) { |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 104 | /* Set the Relative Register-at SMART FAN IV Control Mode Table */ |
| 105 | //SFIV TODO |
| 106 | } |
| 107 | |
Martin Roth | 5688979 | 2013-07-09 21:39:46 -0600 | [diff] [blame] | 108 | /* Set Hysteresis of Temperature (HT) */ |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 109 | //TODO |
| 110 | } |
| 111 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 112 | static uint8_t fan_pct_to_cfg_val(uint8_t percent) |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 113 | { |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 114 | uint16_t cfg = (((unsigned int)percent * 10000) / 3922); |
| 115 | if (cfg > 0xff) |
| 116 | cfg = 0xff; |
| 117 | return cfg; |
| 118 | } |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 119 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 120 | static uint8_t millivolts_to_limit_value_type1(int millivolts) |
| 121 | { |
| 122 | /* Datasheet v1.41 pages 44 and 70 (VSEN1 - VSEN11, VTT) */ |
| 123 | return ((millivolts / 2) >> 2); |
| 124 | } |
| 125 | |
| 126 | static uint8_t millivolts_to_limit_value_type2(int millivolts) |
| 127 | { |
| 128 | /* Datasheet v1.41 page pages 44 and 70 (3VSB, 3VDD, VBAT) */ |
| 129 | return ((millivolts / 6) >> 2); |
| 130 | } |
| 131 | |
| 132 | static uint16_t millivolts_to_limit_value_type3(int millivolts) |
| 133 | { |
| 134 | /* Datasheet v1.41 page 45 (VSEN12, VSEN13, VDSEN14 - VDSEN17) */ |
| 135 | return (millivolts / 2); |
| 136 | } |
| 137 | |
| 138 | static void w83795_init(struct device *dev, w83795_fan_mode_t mode, u8 dts_src) |
| 139 | { |
| 140 | struct drivers_i2c_w83795_config *config = dev->chip_info; |
| 141 | uint8_t i; |
| 142 | uint8_t val; |
| 143 | uint16_t limit_value; |
| 144 | |
Timothy Pearson | f7e0a1a | 2015-10-17 04:37:10 -0500 | [diff] [blame] | 145 | #if IS_ENABLED(CONFIG_SMBUS_HAS_AUX_CHANNELS) |
| 146 | uint8_t smbus_aux_channel_prev = smbus_get_current_channel(); |
| 147 | smbus_switch_to_channel(config->smbus_aux); |
| 148 | printk(BIOS_DEBUG, "Set SMBUS controller to channel %d\n", config->smbus_aux); |
| 149 | #endif |
| 150 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 151 | if (smbus_read_byte(dev, 0x00) < 0) { |
Timothy Pearson | f7e0a1a | 2015-10-17 04:37:10 -0500 | [diff] [blame] | 152 | #if IS_ENABLED(CONFIG_SMBUS_HAS_AUX_CHANNELS) |
| 153 | /* Restore SMBUS channel setting */ |
| 154 | smbus_switch_to_channel(smbus_aux_channel_prev); |
| 155 | printk(BIOS_DEBUG, "Set SMBUS controller to channel %d\n", smbus_aux_channel_prev); |
| 156 | #endif |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 157 | printk(BIOS_ERR, "W83795G/ADG Nuvoton H/W Monitor not found\n"); |
| 158 | return; |
| 159 | } |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 160 | val = w83795_read(dev, W83795_REG_CONFIG); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 161 | if ((val & W83795_REG_CONFIG_CONFIG48) == 0) |
| 162 | printk(BIOS_INFO, "Found 64 pin W83795G Nuvoton H/W Monitor\n"); |
| 163 | else if ((val & W83795_REG_CONFIG_CONFIG48) == 1) |
| 164 | printk(BIOS_INFO, "Found 48 pin W83795ADG Nuvoton H/W Monitor\n"); |
| 165 | |
| 166 | /* Reset */ |
| 167 | val |= W83795_REG_CONFIG_INIT; |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 168 | w83795_write(dev, W83795_REG_CONFIG, val); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 169 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 170 | /* Fan monitor settings */ |
| 171 | w83795_write(dev, W83795_REG_FANIN_CTRL1, config->fanin_ctl1); |
| 172 | w83795_write(dev, W83795_REG_FANIN_CTRL2, config->fanin_ctl2); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 173 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 174 | /* Temperature thresholds */ |
| 175 | w83795_write(dev, W83795_REG_TEMP_CRIT(0), config->tr1_critical_temperature); |
| 176 | w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(0), config->tr1_critical_hysteresis); |
| 177 | w83795_write(dev, W83795_REG_TEMP_WARN(0), config->tr1_warning_temperature); |
| 178 | w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(0), config->tr1_warning_hysteresis); |
| 179 | w83795_write(dev, W83795_REG_TEMP_CRIT(1), config->tr2_critical_temperature); |
| 180 | w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(1), config->tr2_critical_hysteresis); |
| 181 | w83795_write(dev, W83795_REG_TEMP_WARN(1), config->tr2_warning_temperature); |
| 182 | w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(1), config->tr2_warning_hysteresis); |
| 183 | w83795_write(dev, W83795_REG_TEMP_CRIT(2), config->tr3_critical_temperature); |
| 184 | w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(2), config->tr3_critical_hysteresis); |
| 185 | w83795_write(dev, W83795_REG_TEMP_WARN(2), config->tr3_warning_temperature); |
| 186 | w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(2), config->tr3_warning_hysteresis); |
| 187 | w83795_write(dev, W83795_REG_TEMP_CRIT(3), config->tr4_critical_temperature); |
| 188 | w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(3), config->tr4_critical_hysteresis); |
| 189 | w83795_write(dev, W83795_REG_TEMP_WARN(3), config->tr4_warning_temperature); |
| 190 | w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(3), config->tr4_warning_hysteresis); |
| 191 | w83795_write(dev, W83795_REG_TEMP_CRIT(4), config->tr5_critical_temperature); |
| 192 | w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(4), config->tr5_critical_hysteresis); |
| 193 | w83795_write(dev, W83795_REG_TEMP_WARN(4), config->tr5_warning_temperature); |
| 194 | w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(4), config->tr5_warning_hysteresis); |
| 195 | w83795_write(dev, W83795_REG_TEMP_CRIT(5), config->tr6_critical_temperature); |
| 196 | w83795_write(dev, W83795_REG_TEMP_CRIT_HYSTER(5), config->tr6_critical_hysteresis); |
| 197 | w83795_write(dev, W83795_REG_TEMP_WARN(5), config->tr6_warning_temperature); |
| 198 | w83795_write(dev, W83795_REG_TEMP_WARN_HYSTER(5), config->tr6_warning_hysteresis); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 199 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 200 | /* DTS temperature thresholds */ |
| 201 | w83795_write(dev, W83795_REG_DTS_CRIT, config->dts_critical_temperature); |
| 202 | w83795_write(dev, W83795_REG_DTS_CRIT_HYSTER, config->dts_critical_hysteresis); |
| 203 | w83795_write(dev, W83795_REG_DTS_WARN, config->dts_warning_temperature); |
| 204 | w83795_write(dev, W83795_REG_DTS_WARN_HYSTER, config->dts_warning_hysteresis); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 205 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 206 | /* Configure DTS registers in bank3 before enabling DTS */ |
| 207 | w83795_dts_configure(dev, dts_src); |
| 208 | |
| 209 | /* DTS enable */ |
| 210 | w83795_write(dev, W83795_REG_DTSE, config->temp_dtse); |
| 211 | |
| 212 | /* Temperature monitor settings */ |
| 213 | w83795_write(dev, W83795_REG_TEMP_CTRL1, config->temp_ctl1); |
| 214 | w83795_write(dev, W83795_REG_TEMP_CTRL2, config->temp_ctl2); |
| 215 | |
| 216 | /* Temperature to fan mappings */ |
| 217 | w83795_write(dev, W83795_REG_TFMR(0), config->temp1_fan_select); |
| 218 | w83795_write(dev, W83795_REG_TFMR(1), config->temp2_fan_select); |
| 219 | w83795_write(dev, W83795_REG_TFMR(2), config->temp3_fan_select); |
| 220 | w83795_write(dev, W83795_REG_TFMR(3), config->temp4_fan_select); |
| 221 | w83795_write(dev, W83795_REG_TFMR(4), config->temp5_fan_select); |
| 222 | w83795_write(dev, W83795_REG_TFMR(5), config->temp6_fan_select); |
| 223 | |
| 224 | /* Temperature data source to temperature mappings */ |
| 225 | w83795_write(dev, W83795_REG_T12TSS, ((config->temp2_source_select & 0x0f) << 4) | (config->temp1_source_select & 0x0f)); |
| 226 | w83795_write(dev, W83795_REG_T34TSS, ((config->temp4_source_select & 0x0f) << 4) | (config->temp3_source_select & 0x0f)); |
| 227 | w83795_write(dev, W83795_REG_T56TSS, ((config->temp6_source_select & 0x0f) << 4) | (config->temp5_source_select & 0x0f)); |
| 228 | |
| 229 | /* Set critical temperatures |
| 230 | * If any sensor exceeds the associated critical temperature, |
| 231 | * all fans will be forced to full speed. |
| 232 | */ |
| 233 | w83795_write(dev, W83795_REG_CTFS(0), config->temp1_critical_temperature); |
| 234 | w83795_write(dev, W83795_REG_CTFS(1), config->temp2_critical_temperature); |
| 235 | w83795_write(dev, W83795_REG_CTFS(2), config->temp3_critical_temperature); |
| 236 | w83795_write(dev, W83795_REG_CTFS(3), config->temp4_critical_temperature); |
| 237 | w83795_write(dev, W83795_REG_CTFS(4), config->temp5_critical_temperature); |
| 238 | w83795_write(dev, W83795_REG_CTFS(5), config->temp6_critical_temperature); |
| 239 | |
| 240 | /* Set fan control target temperatures */ |
| 241 | w83795_write(dev, W83795_REG_TTTI(0), config->temp1_target_temperature); |
| 242 | w83795_write(dev, W83795_REG_TTTI(1), config->temp2_target_temperature); |
| 243 | w83795_write(dev, W83795_REG_TTTI(2), config->temp3_target_temperature); |
| 244 | w83795_write(dev, W83795_REG_TTTI(3), config->temp4_target_temperature); |
| 245 | w83795_write(dev, W83795_REG_TTTI(4), config->temp5_target_temperature); |
| 246 | w83795_write(dev, W83795_REG_TTTI(5), config->temp6_target_temperature); |
| 247 | |
| 248 | /* Set fan stall prevention parameters */ |
| 249 | w83795_write(dev, W83795_REG_FAN_NONSTOP(0), config->fan1_nonstop); |
| 250 | w83795_write(dev, W83795_REG_FAN_NONSTOP(1), config->fan2_nonstop); |
| 251 | w83795_write(dev, W83795_REG_FAN_NONSTOP(2), config->fan3_nonstop); |
| 252 | w83795_write(dev, W83795_REG_FAN_NONSTOP(3), config->fan4_nonstop); |
| 253 | w83795_write(dev, W83795_REG_FAN_NONSTOP(4), config->fan5_nonstop); |
| 254 | w83795_write(dev, W83795_REG_FAN_NONSTOP(5), config->fan6_nonstop); |
| 255 | w83795_write(dev, W83795_REG_FAN_NONSTOP(6), config->fan7_nonstop); |
| 256 | w83795_write(dev, W83795_REG_FAN_NONSTOP(7), config->fan8_nonstop); |
| 257 | |
| 258 | /* Set fan default speed */ |
| 259 | w83795_write(dev, W83795_REG_DFSP, fan_pct_to_cfg_val(config->default_speed)); |
| 260 | |
| 261 | /* Set initial fan speeds */ |
| 262 | w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(0), fan_pct_to_cfg_val(config->fan1_duty)); |
| 263 | w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(1), fan_pct_to_cfg_val(config->fan2_duty)); |
| 264 | w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(2), fan_pct_to_cfg_val(config->fan3_duty)); |
| 265 | w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(3), fan_pct_to_cfg_val(config->fan4_duty)); |
| 266 | w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(4), fan_pct_to_cfg_val(config->fan5_duty)); |
| 267 | w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(5), fan_pct_to_cfg_val(config->fan6_duty)); |
| 268 | w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(6), fan_pct_to_cfg_val(config->fan7_duty)); |
| 269 | w83795_write(dev, W83795_REG_FAN_MANUAL_SPEED(7), fan_pct_to_cfg_val(config->fan8_duty)); |
| 270 | |
| 271 | /* Voltage monitor settings */ |
| 272 | w83795_write(dev, W83795_REG_VOLT_CTRL1, config->volt_ctl1); |
| 273 | w83795_write(dev, W83795_REG_VOLT_CTRL2, config->volt_ctl2); |
| 274 | |
| 275 | /* Voltage high/low limits */ |
| 276 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(0), millivolts_to_limit_value_type1(config->vcore1_high_limit_mv)); |
| 277 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(0), millivolts_to_limit_value_type1(config->vcore1_low_limit_mv)); |
| 278 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(1), millivolts_to_limit_value_type1(config->vcore2_high_limit_mv)); |
| 279 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(1), millivolts_to_limit_value_type1(config->vcore2_low_limit_mv)); |
| 280 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(2), millivolts_to_limit_value_type1(config->vsen3_high_limit_mv)); |
| 281 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(2), millivolts_to_limit_value_type1(config->vsen3_low_limit_mv)); |
| 282 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(3), millivolts_to_limit_value_type1(config->vsen4_high_limit_mv)); |
| 283 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(3), millivolts_to_limit_value_type1(config->vsen4_low_limit_mv)); |
| 284 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(4), millivolts_to_limit_value_type1(config->vsen5_high_limit_mv)); |
| 285 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(4), millivolts_to_limit_value_type1(config->vsen5_low_limit_mv)); |
| 286 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(5), millivolts_to_limit_value_type1(config->vsen6_high_limit_mv)); |
| 287 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(5), millivolts_to_limit_value_type1(config->vsen6_low_limit_mv)); |
| 288 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(6), millivolts_to_limit_value_type1(config->vsen7_high_limit_mv)); |
| 289 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(6), millivolts_to_limit_value_type1(config->vsen7_low_limit_mv)); |
| 290 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(7), millivolts_to_limit_value_type1(config->vsen8_high_limit_mv)); |
| 291 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(7), millivolts_to_limit_value_type1(config->vsen8_low_limit_mv)); |
| 292 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(8), millivolts_to_limit_value_type1(config->vsen9_high_limit_mv)); |
| 293 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(8), millivolts_to_limit_value_type1(config->vsen9_low_limit_mv)); |
| 294 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(9), millivolts_to_limit_value_type1(config->vsen10_high_limit_mv)); |
| 295 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(9), millivolts_to_limit_value_type1(config->vsen10_low_limit_mv)); |
| 296 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(10), millivolts_to_limit_value_type1(config->vsen11_high_limit_mv)); |
| 297 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(10), millivolts_to_limit_value_type1(config->vsen11_low_limit_mv)); |
| 298 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(11), millivolts_to_limit_value_type1(config->vtt_high_limit_mv)); |
| 299 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(11), millivolts_to_limit_value_type1(config->vtt_low_limit_mv)); |
| 300 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(12), millivolts_to_limit_value_type2(config->vdd_high_limit_mv)); |
| 301 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(12), millivolts_to_limit_value_type2(config->vdd_low_limit_mv)); |
| 302 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(13), millivolts_to_limit_value_type2(config->vsb_high_limit_mv)); |
| 303 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(13), millivolts_to_limit_value_type2(config->vsb_low_limit_mv)); |
| 304 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH(14), millivolts_to_limit_value_type2(config->vbat_high_limit_mv)); |
| 305 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW(14), millivolts_to_limit_value_type2(config->vbat_low_limit_mv)); |
| 306 | |
| 307 | /* VSEN12 limits */ |
| 308 | if (config->temp_ctl1 & 0x2) { |
| 309 | limit_value = millivolts_to_limit_value_type3(config->vsen12_high_limit_mv); |
| 310 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH_2_M(4), limit_value >> 2); |
| 311 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH_2_L(4), limit_value & 0x3); |
| 312 | limit_value = millivolts_to_limit_value_type3(config->vsen12_low_limit_mv); |
| 313 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW_2_M(4), limit_value >> 2); |
| 314 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW_2_L(4), limit_value & 0x3); |
| 315 | } |
| 316 | |
| 317 | /* VSEN13 limits */ |
| 318 | if (config->temp_ctl1 & 0x8) { |
| 319 | limit_value = millivolts_to_limit_value_type3(config->vsen13_high_limit_mv); |
| 320 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH_2_M(5), limit_value >> 2); |
| 321 | w83795_write(dev, W83795_REG_VOLT_LIM_HIGH_2_L(5), limit_value & 0x3); |
| 322 | limit_value = millivolts_to_limit_value_type3(config->vsen13_low_limit_mv); |
| 323 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW_2_M(5), limit_value >> 2); |
| 324 | w83795_write(dev, W83795_REG_VOLT_LIM_LOW_2_L(5), limit_value & 0x3); |
| 325 | } |
| 326 | |
| 327 | w83795_set_fan(dev, mode); |
| 328 | |
| 329 | /* Show current fan control settings */ |
| 330 | printk(BIOS_INFO, "Fan\tCTFS(celsius)\tTTTI(celsius)\n"); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 331 | for (i = 0; i < 6; i++) { |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 332 | val = w83795_read(dev, W83795_REG_CTFS(i)); |
| 333 | printk(BIOS_INFO, " %x\t%d", i + 1, val); |
| 334 | val = w83795_read(dev, W83795_REG_TTTI(i)); |
| 335 | printk(BIOS_INFO, "\t%d\n", val); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 336 | } |
| 337 | |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 338 | /* Show current temperatures */ |
| 339 | for (i = 0; i < 8; i++) { |
| 340 | val = w83795_read(dev, W83795_REG_DTS(i)); |
| 341 | printk(BIOS_DEBUG, "DTS%x current value: %x\n", i + 1, val); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 342 | } |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 343 | |
| 344 | /* Start monitoring / fan control */ |
| 345 | val = w83795_read(dev, W83795_REG_CONFIG); |
| 346 | val |= W83795_REG_CONFIG_START; |
| 347 | w83795_write(dev, W83795_REG_CONFIG, val); |
Timothy Pearson | f7e0a1a | 2015-10-17 04:37:10 -0500 | [diff] [blame] | 348 | |
| 349 | #if IS_ENABLED(CONFIG_SMBUS_HAS_AUX_CHANNELS) |
| 350 | /* Restore SMBUS channel setting */ |
| 351 | smbus_switch_to_channel(smbus_aux_channel_prev); |
| 352 | printk(BIOS_DEBUG, "Set SMBUS controller to channel %d\n", smbus_aux_channel_prev); |
| 353 | #endif |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 354 | } |
| 355 | |
Edward O'Callaghan | 2c9d2cf | 2014-10-27 23:29:29 +1100 | [diff] [blame] | 356 | static void w83795_hwm_init(struct device *dev) |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 357 | { |
| 358 | struct device *cpu; |
Sven Schnelle | 51676b1 | 2012-07-29 19:18:03 +0200 | [diff] [blame] | 359 | struct cpu_info *info; |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 360 | |
Sven Schnelle | 51676b1 | 2012-07-29 19:18:03 +0200 | [diff] [blame] | 361 | info = cpu_info(); |
| 362 | cpu = info->cpu; |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 363 | if (!cpu) |
| 364 | die("CPU: missing cpu device structure"); |
| 365 | |
| 366 | if (cpu->vendor == X86_VENDOR_AMD) |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 367 | w83795_init(dev, THERMAL_CRUISE_MODE, DTS_SRC_AMD_SBTSI); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 368 | else if (cpu->vendor == X86_VENDOR_INTEL) |
Timothy Pearson | cab71b6 | 2015-09-05 17:53:20 -0500 | [diff] [blame] | 369 | w83795_init(dev, THERMAL_CRUISE_MODE, DTS_SRC_INTEL_PECI); |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 370 | else |
| 371 | printk(BIOS_ERR, "Neither AMD nor INTEL CPU detected\n"); |
| 372 | } |
| 373 | |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 374 | static struct device_operations w83795_operations = { |
Edward O'Callaghan | 524625d | 2014-10-31 07:55:45 +1100 | [diff] [blame] | 375 | .read_resources = DEVICE_NOOP, |
| 376 | .set_resources = DEVICE_NOOP, |
| 377 | .enable_resources = DEVICE_NOOP, |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 378 | .init = w83795_hwm_init, |
| 379 | }; |
| 380 | |
Edward O'Callaghan | 2c9d2cf | 2014-10-27 23:29:29 +1100 | [diff] [blame] | 381 | static void enable_dev(struct device *dev) |
Kerry Sheh | 134d8a9 | 2012-02-07 20:33:21 +0800 | [diff] [blame] | 382 | { |
| 383 | dev->ops = &w83795_operations; |
| 384 | } |
| 385 | |
| 386 | struct chip_operations drivers_i2c_w83795_ops = { |
| 387 | CHIP_NAME("Nuvoton W83795G/ADG Hardware Monitor") |
| 388 | .enable_dev = enable_dev, |
| 389 | }; |