/* * A hwmon driver for the Intel 5000 series chipset FB-DIMM AMB * temperature sensors * Copyright (C) 2007 IBM * * Author: Darrick J. Wong * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #define DRVNAME "i5k_amb" #define I5K_REG_AMB_BASE_ADDR 0x48 #define I5K_REG_AMB_LEN_ADDR 0x50 #define I5K_REG_CHAN0_PRESENCE_ADDR 0x64 #define I5K_REG_CHAN1_PRESENCE_ADDR 0x66 #define AMB_REG_TEMP_MIN_ADDR 0x80 #define AMB_REG_TEMP_MID_ADDR 0x81 #define AMB_REG_TEMP_MAX_ADDR 0x82 #define AMB_REG_TEMP_STATUS_ADDR 0x84 #define AMB_REG_TEMP_ADDR 0x85 #define AMB_CONFIG_SIZE 2048 #define AMB_FUNC_3_OFFSET 768 static unsigned long amb_reg_temp_status(unsigned int amb) { return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_STATUS_ADDR + AMB_CONFIG_SIZE * amb; } static unsigned long amb_reg_temp_min(unsigned int amb) { return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MIN_ADDR + AMB_CONFIG_SIZE * amb; } static unsigned long amb_reg_temp_mid(unsigned int amb) { return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MID_ADDR + AMB_CONFIG_SIZE * amb; } static unsigned long amb_reg_temp_max(unsigned int amb) { return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MAX_ADDR + AMB_CONFIG_SIZE * amb; } static unsigned long amb_reg_temp(unsigned int amb) { return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_ADDR + AMB_CONFIG_SIZE * amb; } #define MAX_MEM_CHANNELS 4 #define MAX_AMBS_PER_CHANNEL 16 #define MAX_AMBS (MAX_MEM_CHANNELS * \ MAX_AMBS_PER_CHANNEL) #define CHANNEL_SHIFT 4 #define DIMM_MASK 0xF /* * Ugly hack: For some reason the highest bit is set if there * are _any_ DIMMs in the channel. Attempting to read from * this "high-order" AMB results in a memory bus error, so * for now we'll just ignore that top bit, even though that * might prevent us from seeing the 16th DIMM in the channel. */ #define REAL_MAX_AMBS_PER_CHANNEL 15 #define KNOBS_PER_AMB 6 static unsigned long amb_num_from_reg(unsigned int byte_num, unsigned int bit) { return byte_num * MAX_AMBS_PER_CHANNEL + bit; } #define AMB_SYSFS_NAME_LEN 16 struct i5k_device_attribute { struct sensor_device_attribute s_attr; char name[AMB_SYSFS_NAME_LEN]; }; struct i5k_amb_data { struct device *hwmon_dev; unsigned long amb_base; unsigned long amb_len; u16 amb_present[MAX_MEM_CHANNELS]; void __iomem *amb_mmio; struct i5k_device_attribute *attrs; unsigned int num_attrs; }; static ssize_t show_name(struct device *dev, struct device_attribute *devattr, char *buf) { return sprintf(buf, "%s\n", DRVNAME); } static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); static struct platform_device *amb_pdev; static u8 amb_read_byte(struct i5k_amb_data *data, unsigned long offset) { return ioread8(data->amb_mmio + offset); } static void amb_write_byte(struct i5k_amb_data *data, unsigned long offset, u8 val) { iowrite8(val, data->amb_mmio + offset); } static ssize_t show_amb_alarm(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i5k_amb_data *data = dev_get_drvdata(dev); if (!(amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x20) && (amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x8)) return sprintf(buf, "1\n"); else return sprintf(buf, "0\n"); } static ssize_t store_amb_min(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i5k_amb_data *data = dev_get_drvdata(dev); unsigned long temp; int ret = kstrtoul(buf, 10, &temp); if (ret < 0) return ret; temp = temp / 500; if (temp > 255) temp = 255; amb_write_byte(data, amb_reg_temp_min(attr->index), temp); return count; } static ssize_t store_amb_mid(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i5k_amb_data *data = dev_get_drvdata(dev); unsigned long temp; int ret = kstrtoul(buf, 10, &temp); if (ret < 0) return ret; temp = temp / 500; if (temp > 255) temp = 255; amb_write_byte(data, amb_reg_temp_mid(attr->index), temp); return count; } static ssize_t store_amb_max(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i5k_amb_data *data = dev_get_drvdata(dev); unsigned long temp; int ret = kstrtoul(buf, 10, &temp); if (ret < 0) return ret; temp = temp / 500; if (temp > 255) temp = 255; amb_write_byte(data, amb_reg_temp_max(attr->index), temp); return count; } static ssize_t show_amb_min(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i5k_amb_data *data = dev_get_drvdata(dev); return sprintf(buf, "%d\n", 500 * amb_read_byte(data, amb_reg_temp_min(attr->index))); } static ssize_t show_amb_mid(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct i5k_amb_data *data = dev_get_drvdata(dev); return sprintf(buf, "%d\n", 500 * amb_read_byte(data, amb_reg_temp_mid(attr->index))); } static
import time

import testcase as base
import functest.utils.functest_utils as ft_utils
import functest.utils.functest_logger as ft_logger
from functest.utils.constants import CONST


class Feature(base.TestCase):

    def __init__(