12509632aSRobert Mustacchi /*
22509632aSRobert Mustacchi * This file and its contents are supplied under the terms of the
32509632aSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
42509632aSRobert Mustacchi * You may only use this file in accordance with the terms of version
52509632aSRobert Mustacchi * 1.0 of the CDDL.
62509632aSRobert Mustacchi *
72509632aSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
82509632aSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
92509632aSRobert Mustacchi * http://www.illumos.org/license/CDDL.
102509632aSRobert Mustacchi */
112509632aSRobert Mustacchi
122509632aSRobert Mustacchi /*
132509632aSRobert Mustacchi * Copyright 2020 Oxide Computer Company
142509632aSRobert Mustacchi */
152509632aSRobert Mustacchi
162509632aSRobert Mustacchi /*
172509632aSRobert Mustacchi * Handle and report sensors found on some igb parts.
182509632aSRobert Mustacchi *
192509632aSRobert Mustacchi * The Intel I350 has a built-in thermal sensor diode and an optional External
202509632aSRobert Mustacchi * Thermal Sensor configuration. This external configuration is provided through
212509632aSRobert Mustacchi * an optional space in the NVM and allows for up to 4 external sensors to be
222509632aSRobert Mustacchi * defined. Currently, the only defined external thermal sensor is the Microchip
232509632aSRobert Mustacchi * EMC 1413. As of this time, we haven't encountered a device that uses the EMC
242509632aSRobert Mustacchi * 1413 in the wild, so while the definitions here are present, that is stubbed
252509632aSRobert Mustacchi * out for the time.
262509632aSRobert Mustacchi *
272509632aSRobert Mustacchi * When accessing the internal sensor, the I350 Datasheet requires that we take
282509632aSRobert Mustacchi * software/firmware semaphore before proceeding.
292509632aSRobert Mustacchi */
302509632aSRobert Mustacchi
312509632aSRobert Mustacchi #include "igb_sw.h"
322509632aSRobert Mustacchi #include <sys/sensors.h>
332509632aSRobert Mustacchi #include <sys/bitmap.h>
342509632aSRobert Mustacchi
352509632aSRobert Mustacchi /*
362509632aSRobert Mustacchi * Thermal register values.
372509632aSRobert Mustacchi */
382509632aSRobert Mustacchi #define E1000_THMJT_TEMP(x) BITX(x, 8, 0)
392509632aSRobert Mustacchi #define E1000_THMJT_VALID(x) BITX(x, 31, 31)
402509632aSRobert Mustacchi #define E1000_THMJT_RESOLUTION 1
412509632aSRobert Mustacchi #define E1000_THMJT_PRECISION 5
422509632aSRobert Mustacchi
432509632aSRobert Mustacchi /*
442509632aSRobert Mustacchi * Misc. definitions required for accessing the NVM space.
452509632aSRobert Mustacchi */
462509632aSRobert Mustacchi #define IGB_NVM_ETS_CFG 0x3e
472509632aSRobert Mustacchi #define IGB_NVM_ETS_CFG_NSENSORS(x) BITX(x, 2, 0)
482509632aSRobert Mustacchi #define IGB_NVM_ETS_CFG_TYPE(x) BITX(x, 5, 3)
492509632aSRobert Mustacchi #define IGB_NVM_ETS_CFG_TYPE_EMC1413 0
502509632aSRobert Mustacchi
512509632aSRobert Mustacchi #define IGB_NVM_ETS_SENSOR_LOC(x) BITX(x, 13, 10)
522509632aSRobert Mustacchi #define IGB_NVM_ETS_SENSOR_INDEX(x) BITX(x, 9, 8)
532509632aSRobert Mustacchi #define IGB_NVM_ETS_SENSOR_THRESH(x) BITX(x, 7, 0)
542509632aSRobert Mustacchi
552509632aSRobert Mustacchi #define IGB_ETS_I2C_ADDRESS 0xf8
562509632aSRobert Mustacchi
572509632aSRobert Mustacchi /*
582509632aSRobert Mustacchi * These definitions come from the Microchip datasheet for the thermal diode
592509632aSRobert Mustacchi * sensor defined by the external spec. These parts have an accuracy of 1 degree
602509632aSRobert Mustacchi * and a granularity of 1/8th of a degree.
612509632aSRobert Mustacchi */
622509632aSRobert Mustacchi #define EMC1413_REG_CFG 0x03
632509632aSRobert Mustacchi #define EMC1413_REG_CFG_RANGE (1 << 2)
642509632aSRobert Mustacchi #define EMC1413_RANGE_ADJ (-64)
652509632aSRobert Mustacchi #define EMC1413_REG_INT_DIODE_HI 0x00
662509632aSRobert Mustacchi #define EMC1413_REG_INT_DIODE_LO 0x29
672509632aSRobert Mustacchi #define EMC1413_REG_EXT1_DIODE_HI 0x01
682509632aSRobert Mustacchi #define EMC1413_REG_EXT1_DIODE_LO 0x10
692509632aSRobert Mustacchi #define EMC1413_REG_EXT2_DIODE_HI 0x23
702509632aSRobert Mustacchi #define EMC1413_REG_EXT2_DIODE_LO 0x24
712509632aSRobert Mustacchi #define EMC1413_REG_EXT3_DIODE_HI 0x2a
722509632aSRobert Mustacchi #define EMC1413_REG_EXT3_DIODE_LO 0x2b
732509632aSRobert Mustacchi
742509632aSRobert Mustacchi static int
igb_sensor_reg_temperature(void * arg,sensor_ioctl_scalar_t * scalar)75*1045e13aSRobert Mustacchi igb_sensor_reg_temperature(void *arg, sensor_ioctl_scalar_t *scalar)
762509632aSRobert Mustacchi {
772509632aSRobert Mustacchi igb_t *igb = arg;
782509632aSRobert Mustacchi uint32_t reg;
792509632aSRobert Mustacchi
802509632aSRobert Mustacchi if (igb->hw.mac.ops.acquire_swfw_sync(&igb->hw, E1000_SWFW_PWRTS_SM) !=
812509632aSRobert Mustacchi E1000_SUCCESS) {
822509632aSRobert Mustacchi return (EIO);
832509632aSRobert Mustacchi }
842509632aSRobert Mustacchi reg = E1000_READ_REG(&igb->hw, E1000_THMJT);
852509632aSRobert Mustacchi igb->hw.mac.ops.release_swfw_sync(&igb->hw, E1000_SWFW_PWRTS_SM);
862509632aSRobert Mustacchi if (E1000_THMJT_VALID(reg) == 0) {
872509632aSRobert Mustacchi return (EIO);
882509632aSRobert Mustacchi }
892509632aSRobert Mustacchi
90*1045e13aSRobert Mustacchi scalar->sis_unit = SENSOR_UNIT_CELSIUS;
91*1045e13aSRobert Mustacchi scalar->sis_gran = E1000_THMJT_RESOLUTION;
92*1045e13aSRobert Mustacchi scalar->sis_prec = E1000_THMJT_PRECISION;
93*1045e13aSRobert Mustacchi scalar->sis_value = E1000_THMJT_TEMP(reg);
942509632aSRobert Mustacchi
952509632aSRobert Mustacchi return (0);
962509632aSRobert Mustacchi }
972509632aSRobert Mustacchi
982509632aSRobert Mustacchi static const ksensor_ops_t igb_sensor_reg_ops = {
992509632aSRobert Mustacchi .kso_kind = ksensor_kind_temperature,
100*1045e13aSRobert Mustacchi .kso_scalar = igb_sensor_reg_temperature
1012509632aSRobert Mustacchi };
1022509632aSRobert Mustacchi
1032509632aSRobert Mustacchi static boolean_t
igb_sensors_create_minors(igb_t * igb)1042509632aSRobert Mustacchi igb_sensors_create_minors(igb_t *igb)
1052509632aSRobert Mustacchi {
1062509632aSRobert Mustacchi int ret;
1072509632aSRobert Mustacchi igb_sensors_t *sp = &igb->igb_sensors;
1082509632aSRobert Mustacchi
109*1045e13aSRobert Mustacchi if ((ret = ksensor_create_scalar_pcidev(igb->dip,
110*1045e13aSRobert Mustacchi SENSOR_KIND_TEMPERATURE, &igb_sensor_reg_ops, igb, "builtin",
111*1045e13aSRobert Mustacchi &sp->isn_reg_ksensor)) != 0) {
1122509632aSRobert Mustacchi igb_log(igb, IGB_LOG_ERROR, "failed to create main sensor: %d",
1132509632aSRobert Mustacchi ret);
1142509632aSRobert Mustacchi return (B_FALSE);
1152509632aSRobert Mustacchi }
1162509632aSRobert Mustacchi
1172509632aSRobert Mustacchi return (B_TRUE);
1182509632aSRobert Mustacchi }
1192509632aSRobert Mustacchi
1202509632aSRobert Mustacchi static boolean_t
igb_sensors_init_ets(igb_t * igb,uint_t ets_off,uint_t index)1212509632aSRobert Mustacchi igb_sensors_init_ets(igb_t *igb, uint_t ets_off, uint_t index)
1222509632aSRobert Mustacchi {
1232509632aSRobert Mustacchi uint16_t val;
1242509632aSRobert Mustacchi int ret;
1252509632aSRobert Mustacchi igb_sensors_t *sensors = &igb->igb_sensors;
1262509632aSRobert Mustacchi igb_ets_t *etsp = &sensors->isn_ets[sensors->isn_nents];
1272509632aSRobert Mustacchi igb_ets_loc_t loc;
1282509632aSRobert Mustacchi
1292509632aSRobert Mustacchi if ((ret = e1000_read_nvm(&igb->hw, ets_off, 1, &val)) !=
1302509632aSRobert Mustacchi E1000_SUCCESS) {
1312509632aSRobert Mustacchi igb_log(igb, IGB_LOG_ERROR, "failed to read ETS word "
1322509632aSRobert Mustacchi "at offset 0x%x: error %d", ets_off, ret);
1332509632aSRobert Mustacchi return (B_FALSE);
1342509632aSRobert Mustacchi }
1352509632aSRobert Mustacchi
1362509632aSRobert Mustacchi /*
1372509632aSRobert Mustacchi * The data sheet says that if the location is listed as N/A, then we
1382509632aSRobert Mustacchi * should not display this sensor. In this case, we just skip it.
1392509632aSRobert Mustacchi */
1402509632aSRobert Mustacchi loc = IGB_NVM_ETS_SENSOR_LOC(val);
1412509632aSRobert Mustacchi if (loc == IGB_ETS_LOC_NA) {
1422509632aSRobert Mustacchi return (B_TRUE);
1432509632aSRobert Mustacchi }
1442509632aSRobert Mustacchi
1452509632aSRobert Mustacchi etsp->iet_loc = loc;
1462509632aSRobert Mustacchi etsp->iet_index = IGB_NVM_ETS_SENSOR_INDEX(val);
1472509632aSRobert Mustacchi etsp->iet_thresh = IGB_NVM_ETS_SENSOR_THRESH(val);
1482509632aSRobert Mustacchi sensors->isn_nents++;
1492509632aSRobert Mustacchi
1502509632aSRobert Mustacchi return (B_TRUE);
1512509632aSRobert Mustacchi }
1522509632aSRobert Mustacchi
1532509632aSRobert Mustacchi void
igb_init_sensors(igb_t * igb)1542509632aSRobert Mustacchi igb_init_sensors(igb_t *igb)
1552509632aSRobert Mustacchi {
1562509632aSRobert Mustacchi struct e1000_hw *hw = &igb->hw;
1572509632aSRobert Mustacchi uint16_t ets_off;
1582509632aSRobert Mustacchi
1592509632aSRobert Mustacchi /*
1602509632aSRobert Mustacchi * Only the I350 supports the thermal temperature sensor values. This is
1612509632aSRobert Mustacchi * device-wide, so only enumerate on bus zero.
1622509632aSRobert Mustacchi */
1632509632aSRobert Mustacchi hw = &igb->hw;
1642509632aSRobert Mustacchi if (hw->mac.type != e1000_i350 || hw->bus.func != 0) {
1652509632aSRobert Mustacchi return;
1662509632aSRobert Mustacchi }
1672509632aSRobert Mustacchi
1682509632aSRobert Mustacchi ets_off = 0xffff;
1692509632aSRobert Mustacchi (void) e1000_read_nvm(hw, IGB_NVM_ETS_CFG, 1, &ets_off);
1702509632aSRobert Mustacchi if (ets_off != 0 && ets_off != 0xffff) {
1712509632aSRobert Mustacchi int ret;
1722509632aSRobert Mustacchi uint_t nents, i;
1732509632aSRobert Mustacchi uint16_t val;
1742509632aSRobert Mustacchi
1752509632aSRobert Mustacchi /*
1762509632aSRobert Mustacchi * Swallow the fact that we can't read the ETS config.
1772509632aSRobert Mustacchi */
1782509632aSRobert Mustacchi if ((ret = e1000_read_nvm(hw, ets_off, 1, &val)) !=
1792509632aSRobert Mustacchi E1000_SUCCESS) {
1802509632aSRobert Mustacchi igb_log(igb, IGB_LOG_ERROR, "failed to read ETS word "
1812509632aSRobert Mustacchi "at offset 0x%x: error %d", ets_off, ret);
1822509632aSRobert Mustacchi return;
1832509632aSRobert Mustacchi }
1842509632aSRobert Mustacchi
1852509632aSRobert Mustacchi /*
1862509632aSRobert Mustacchi * If we don't find this, assume we can't use the external
1872509632aSRobert Mustacchi * sensor either.
1882509632aSRobert Mustacchi */
1892509632aSRobert Mustacchi if (IGB_NVM_ETS_CFG_TYPE(val) != IGB_NVM_ETS_CFG_TYPE_EMC1413) {
1902509632aSRobert Mustacchi return;
1912509632aSRobert Mustacchi }
1922509632aSRobert Mustacchi
1932509632aSRobert Mustacchi nents = IGB_NVM_ETS_CFG_NSENSORS(val);
1942509632aSRobert Mustacchi if (nents > IGB_ETS_MAX) {
1952509632aSRobert Mustacchi igb_log(igb, IGB_LOG_ERROR, "firmware NVM ETS "
1962509632aSRobert Mustacchi "configuration has more entries (%d) than allowed",
1972509632aSRobert Mustacchi nents);
1982509632aSRobert Mustacchi nents = IGB_ETS_MAX;
1992509632aSRobert Mustacchi }
2002509632aSRobert Mustacchi
2012509632aSRobert Mustacchi for (i = 0; i < nents; i++) {
2022509632aSRobert Mustacchi if (!igb_sensors_init_ets(igb, ets_off, i)) {
2032509632aSRobert Mustacchi return;
2042509632aSRobert Mustacchi }
2052509632aSRobert Mustacchi }
2062509632aSRobert Mustacchi }
2072509632aSRobert Mustacchi
2082509632aSRobert Mustacchi if (!igb_sensors_create_minors(igb)) {
2092509632aSRobert Mustacchi (void) ksensor_remove(igb->dip, KSENSOR_ALL_IDS);
2102509632aSRobert Mustacchi return;
2112509632aSRobert Mustacchi }
2122509632aSRobert Mustacchi
2132509632aSRobert Mustacchi igb->igb_sensors.isn_valid = B_TRUE;
2142509632aSRobert Mustacchi }
2152509632aSRobert Mustacchi
2162509632aSRobert Mustacchi void
igb_fini_sensors(igb_t * igb)2172509632aSRobert Mustacchi igb_fini_sensors(igb_t *igb)
2182509632aSRobert Mustacchi {
2192509632aSRobert Mustacchi if (igb->igb_sensors.isn_valid) {
2202509632aSRobert Mustacchi (void) ksensor_remove(igb->dip, KSENSOR_ALL_IDS);
2212509632aSRobert Mustacchi igb->igb_sensors.isn_valid = B_FALSE;
2222509632aSRobert Mustacchi }
2232509632aSRobert Mustacchi }
224