cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

max8688.c (4889B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Hardware monitoring driver for Maxim MAX8688
      4 *
      5 * Copyright (c) 2011 Ericsson AB.
      6 */
      7
      8#include <linux/bitops.h>
      9#include <linux/kernel.h>
     10#include <linux/module.h>
     11#include <linux/init.h>
     12#include <linux/err.h>
     13#include <linux/i2c.h>
     14#include "pmbus.h"
     15
     16#define MAX8688_MFR_VOUT_PEAK		0xd4
     17#define MAX8688_MFR_IOUT_PEAK		0xd5
     18#define MAX8688_MFR_TEMPERATURE_PEAK	0xd6
     19#define MAX8688_MFG_STATUS		0xd8
     20
     21#define MAX8688_STATUS_OC_FAULT		BIT(4)
     22#define MAX8688_STATUS_OV_FAULT		BIT(5)
     23#define MAX8688_STATUS_OV_WARNING	BIT(8)
     24#define MAX8688_STATUS_UV_FAULT		BIT(9)
     25#define MAX8688_STATUS_UV_WARNING	BIT(10)
     26#define MAX8688_STATUS_UC_FAULT		BIT(11)
     27#define MAX8688_STATUS_OC_WARNING	BIT(12)
     28#define MAX8688_STATUS_OT_FAULT		BIT(13)
     29#define MAX8688_STATUS_OT_WARNING	BIT(14)
     30
     31static int max8688_read_word_data(struct i2c_client *client, int page,
     32				  int phase, int reg)
     33{
     34	int ret;
     35
     36	if (page > 0)
     37		return -ENXIO;
     38
     39	switch (reg) {
     40	case PMBUS_VIRT_READ_VOUT_MAX:
     41		ret = pmbus_read_word_data(client, 0, 0xff,
     42					   MAX8688_MFR_VOUT_PEAK);
     43		break;
     44	case PMBUS_VIRT_READ_IOUT_MAX:
     45		ret = pmbus_read_word_data(client, 0, 0xff,
     46					   MAX8688_MFR_IOUT_PEAK);
     47		break;
     48	case PMBUS_VIRT_READ_TEMP_MAX:
     49		ret = pmbus_read_word_data(client, 0, 0xff,
     50					   MAX8688_MFR_TEMPERATURE_PEAK);
     51		break;
     52	case PMBUS_VIRT_RESET_VOUT_HISTORY:
     53	case PMBUS_VIRT_RESET_IOUT_HISTORY:
     54	case PMBUS_VIRT_RESET_TEMP_HISTORY:
     55		ret = 0;
     56		break;
     57	default:
     58		ret = -ENODATA;
     59		break;
     60	}
     61	return ret;
     62}
     63
     64static int max8688_write_word_data(struct i2c_client *client, int page, int reg,
     65				   u16 word)
     66{
     67	int ret;
     68
     69	switch (reg) {
     70	case PMBUS_VIRT_RESET_VOUT_HISTORY:
     71		ret = pmbus_write_word_data(client, 0, MAX8688_MFR_VOUT_PEAK,
     72					    0);
     73		break;
     74	case PMBUS_VIRT_RESET_IOUT_HISTORY:
     75		ret = pmbus_write_word_data(client, 0, MAX8688_MFR_IOUT_PEAK,
     76					    0);
     77		break;
     78	case PMBUS_VIRT_RESET_TEMP_HISTORY:
     79		ret = pmbus_write_word_data(client, 0,
     80					    MAX8688_MFR_TEMPERATURE_PEAK,
     81					    0xffff);
     82		break;
     83	default:
     84		ret = -ENODATA;
     85		break;
     86	}
     87	return ret;
     88}
     89
     90static int max8688_read_byte_data(struct i2c_client *client, int page, int reg)
     91{
     92	int ret = 0;
     93	int mfg_status;
     94
     95	if (page > 0)
     96		return -ENXIO;
     97
     98	switch (reg) {
     99	case PMBUS_STATUS_VOUT:
    100		mfg_status = pmbus_read_word_data(client, 0, 0xff,
    101						  MAX8688_MFG_STATUS);
    102		if (mfg_status < 0)
    103			return mfg_status;
    104		if (mfg_status & MAX8688_STATUS_UV_WARNING)
    105			ret |= PB_VOLTAGE_UV_WARNING;
    106		if (mfg_status & MAX8688_STATUS_UV_FAULT)
    107			ret |= PB_VOLTAGE_UV_FAULT;
    108		if (mfg_status & MAX8688_STATUS_OV_WARNING)
    109			ret |= PB_VOLTAGE_OV_WARNING;
    110		if (mfg_status & MAX8688_STATUS_OV_FAULT)
    111			ret |= PB_VOLTAGE_OV_FAULT;
    112		break;
    113	case PMBUS_STATUS_IOUT:
    114		mfg_status = pmbus_read_word_data(client, 0, 0xff,
    115						  MAX8688_MFG_STATUS);
    116		if (mfg_status < 0)
    117			return mfg_status;
    118		if (mfg_status & MAX8688_STATUS_UC_FAULT)
    119			ret |= PB_IOUT_UC_FAULT;
    120		if (mfg_status & MAX8688_STATUS_OC_WARNING)
    121			ret |= PB_IOUT_OC_WARNING;
    122		if (mfg_status & MAX8688_STATUS_OC_FAULT)
    123			ret |= PB_IOUT_OC_FAULT;
    124		break;
    125	case PMBUS_STATUS_TEMPERATURE:
    126		mfg_status = pmbus_read_word_data(client, 0, 0xff,
    127						  MAX8688_MFG_STATUS);
    128		if (mfg_status < 0)
    129			return mfg_status;
    130		if (mfg_status & MAX8688_STATUS_OT_WARNING)
    131			ret |= PB_TEMP_OT_WARNING;
    132		if (mfg_status & MAX8688_STATUS_OT_FAULT)
    133			ret |= PB_TEMP_OT_FAULT;
    134		break;
    135	default:
    136		ret = -ENODATA;
    137		break;
    138	}
    139	return ret;
    140}
    141
    142static struct pmbus_driver_info max8688_info = {
    143	.pages = 1,
    144	.format[PSC_VOLTAGE_IN] = direct,
    145	.format[PSC_VOLTAGE_OUT] = direct,
    146	.format[PSC_TEMPERATURE] = direct,
    147	.format[PSC_CURRENT_OUT] = direct,
    148	.m[PSC_VOLTAGE_IN] = 19995,
    149	.b[PSC_VOLTAGE_IN] = 0,
    150	.R[PSC_VOLTAGE_IN] = -1,
    151	.m[PSC_VOLTAGE_OUT] = 19995,
    152	.b[PSC_VOLTAGE_OUT] = 0,
    153	.R[PSC_VOLTAGE_OUT] = -1,
    154	.m[PSC_CURRENT_OUT] = 23109,
    155	.b[PSC_CURRENT_OUT] = 0,
    156	.R[PSC_CURRENT_OUT] = -2,
    157	.m[PSC_TEMPERATURE] = -7612,
    158	.b[PSC_TEMPERATURE] = 335,
    159	.R[PSC_TEMPERATURE] = -3,
    160	.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP
    161		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
    162		| PMBUS_HAVE_STATUS_TEMP,
    163	.read_byte_data = max8688_read_byte_data,
    164	.read_word_data = max8688_read_word_data,
    165	.write_word_data = max8688_write_word_data,
    166};
    167
    168static int max8688_probe(struct i2c_client *client)
    169{
    170	return pmbus_do_probe(client, &max8688_info);
    171}
    172
    173static const struct i2c_device_id max8688_id[] = {
    174	{"max8688", 0},
    175	{ }
    176};
    177
    178MODULE_DEVICE_TABLE(i2c, max8688_id);
    179
    180/* This is the driver that will be inserted */
    181static struct i2c_driver max8688_driver = {
    182	.driver = {
    183		   .name = "max8688",
    184		   },
    185	.probe_new = max8688_probe,
    186	.id_table = max8688_id,
    187};
    188
    189module_i2c_driver(max8688_driver);
    190
    191MODULE_AUTHOR("Guenter Roeck");
    192MODULE_DESCRIPTION("PMBus driver for Maxim MAX8688");
    193MODULE_LICENSE("GPL");
    194MODULE_IMPORT_NS(PMBUS);