Edward O'Callaghan | 63f28c0 | 2014-04-26 15:21:45 +1000 | [diff] [blame] | 1 | /* |
| 2 | * This file is part of the coreboot project. |
| 3 | * |
| 4 | * Copyright (C) 2014 Edward O'Callaghan <eocallaghan@alterapraxis.com> |
| 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. |
Edward O'Callaghan | 63f28c0 | 2014-04-26 15:21:45 +1000 | [diff] [blame] | 15 | */ |
| 16 | |
| 17 | #include <arch/io.h> |
| 18 | #include <console/console.h> |
| 19 | #include <device/device.h> |
| 20 | #include <device/pnp.h> |
| 21 | #include "chip.h" |
| 22 | #include "fintek_internal.h" |
| 23 | |
| 24 | /* |
| 25 | * The Fintek F71869AD Super I/O Hardware Monitor permits the configuration of |
| 26 | * three fans individually, where fan1 is typically taken as the CPU fan. Each |
| 27 | * fan is controlled by the relation: |
| 28 | * |
| 29 | * Tfan? = Tnow + (Ta - Tb)*Ct |
| 30 | * |
| 31 | * Parameters in this relation are specified in the devicetree.cb. |
| 32 | */ |
| 33 | |
| 34 | /* |
| 35 | * Register CR01 ~ CR03 -> Configuration Registers |
| 36 | * Register CR0A ~ CR0F -> PECI/TSI Control Register |
| 37 | * Register CR10 ~ CR37 -> Voltage Setting Register |
| 38 | * Register CR40 ~ CR4E -> PECI 3.0 Command and Register |
| 39 | * Register CR60 ~ CR8E -> Temperature Setting Register |
| 40 | * Register CR90 ~ CRDF -> Fan Control Setting Register |
| 41 | */ |
| 42 | #define HWM_SMBUS_ADDR 0x08 |
| 43 | #define HWM_SMBUS_CONTROL_REG 0x0A |
| 44 | #define HWM_FAN_TYPE_SEL_REG 0x94 |
| 45 | #define HWM_FAN1_TEMP_ADJ_RATE_REG 0x95 |
| 46 | #define HWM_FAN_MODE_SEL_REG 0x96 |
| 47 | #define HWM_FAN_FAULT_TIME_REG 0x9F /* bit7 FAN_PROG_SEL */ |
| 48 | #define HWM_FAN1_IDX_RPM_MODE 0xA3 |
| 49 | #define HWM_FAN1_SEG1_SPEED_COUNT 0xAA |
| 50 | #define HWM_FAN1_SEG2_SPEED_COUNT 0xAB |
| 51 | #define HWM_FAN1_SEG3_SPEED_COUNT 0xAC |
| 52 | #define HWM_FAN1_TEMP_MAP_SEL 0xAF |
| 53 | |
Edward O'Callaghan | 63f28c0 | 2014-04-26 15:21:45 +1000 | [diff] [blame] | 54 | /* note: multifunc registers need to be tweaked before here */ |
Edward O'Callaghan | 2c9d2cf | 2014-10-27 23:29:29 +1100 | [diff] [blame] | 55 | void f71869ad_hwm_init(struct device *dev) |
Edward O'Callaghan | 63f28c0 | 2014-04-26 15:21:45 +1000 | [diff] [blame] | 56 | { |
Edward O'Callaghan | ff7e676 | 2014-07-09 04:12:42 +1000 | [diff] [blame] | 57 | const struct superio_fintek_f71869ad_config *conf = dev->chip_info; |
Edward O'Callaghan | 63f28c0 | 2014-04-26 15:21:45 +1000 | [diff] [blame] | 58 | struct resource *res = find_resource(dev, PNP_IDX_IO0); |
| 59 | |
| 60 | if (!res) { |
| 61 | printk(BIOS_WARNING, "Super I/O HWM: No HWM resource found.\n"); |
| 62 | return; |
| 63 | } |
| 64 | u16 port = res->base; /* data-sheet default base = 0x229 */ |
| 65 | |
| 66 | printk(BIOS_INFO, |
| 67 | "Fintek F71869AD Super I/O HWM: Initializing Hardware Monitor..\n"); |
| 68 | printk(BIOS_DEBUG, |
| 69 | "Fintek F71869AD Super I/O HWM: Base Address at 0x%x\n", port); |
| 70 | |
| 71 | pnp_enter_conf_mode(dev); |
| 72 | pnp_set_logical_device(dev); |
| 73 | |
| 74 | /* Fintek F71869AD HWM (ordered) programming sequence. */ |
| 75 | |
| 76 | /* SMBus Address p.53 */ |
| 77 | pnp_write_index(port, HWM_SMBUS_ADDR, conf->hwm_smbus_address); |
| 78 | /* Configure pins 57/58 as PECI_REQ#/PECI (AMD_TSI) p.54 */ |
| 79 | pnp_write_index(port, HWM_SMBUS_CONTROL_REG, conf->hwm_smbus_control_reg); |
| 80 | /* Tfan1 = Tnow + (Ta - Tb)*Ct where, */ |
| 81 | /* FAN1_TEMP_SEL_DIG, FAN1_TEMP_SEL (Tnow) set to come from CR7Ah p.73 */ |
| 82 | pnp_write_index(port, HWM_FAN1_TEMP_MAP_SEL, conf->hwm_fan1_temp_map_sel); |
| 83 | /* set FAN_PROG_SEL = 1 */ |
| 84 | pnp_write_index(port, HWM_FAN_FAULT_TIME_REG, 0x8a); |
Elyes HAOUAS | cf13950 | 2016-09-16 20:32:00 +0200 | [diff] [blame] | 85 | /* FAN1_BASE_TEMP (Tb) set when FAN_PROG_SEL = 1, p.64-65 */ |
Edward O'Callaghan | 63f28c0 | 2014-04-26 15:21:45 +1000 | [diff] [blame] | 86 | pnp_write_index(port, HWM_FAN_TYPE_SEL_REG, conf->hwm_fan_type_sel_reg); |
| 87 | /* set TFAN1_ADJ_SEL (Ta) p.67 to use CR7Ah p.61 */ |
| 88 | pnp_write_index(port, HWM_FAN_MODE_SEL_REG, conf->hwm_fan_mode_sel_reg); |
Elyes HAOUAS | cf13950 | 2016-09-16 20:32:00 +0200 | [diff] [blame] | 89 | /* TFAN1_ADJ_{UP,DOWN}_RATE (Ct = 1/4 up & down) in 0x95 when FAN_PROG_SEL = |
Edward O'Callaghan | 63f28c0 | 2014-04-26 15:21:45 +1000 | [diff] [blame] | 90 | 1, p.88 */ |
| 91 | pnp_write_index(port, HWM_FAN1_TEMP_ADJ_RATE_REG, conf->hwm_fan1_temp_adj_rate_reg); |
| 92 | /* set FAN_PROG_SEL = 0 */ |
| 93 | pnp_write_index(port, HWM_FAN_FAULT_TIME_REG, 0x0a); |
| 94 | /* FAN1 RPM mode p.70 */ |
| 95 | pnp_write_index(port, HWM_FAN1_IDX_RPM_MODE, conf->hwm_fan1_idx_rpm_mode); |
| 96 | /* FAN1 Segment X Speed Count */ |
| 97 | pnp_write_index(port, HWM_FAN1_SEG1_SPEED_COUNT, conf->hwm_fan1_seg1_speed_count); |
| 98 | pnp_write_index(port, HWM_FAN1_SEG2_SPEED_COUNT, conf->hwm_fan1_seg2_speed_count); |
| 99 | pnp_write_index(port, HWM_FAN1_SEG3_SPEED_COUNT, conf->hwm_fan1_seg3_speed_count); |
| 100 | |
| 101 | pnp_exit_conf_mode(dev); |
| 102 | } |