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

pxe1610.c (3600B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Hardware monitoring driver for Infineon PXE1610
      4 *
      5 * Copyright (c) 2019 Facebook Inc
      6 *
      7 */
      8
      9#include <linux/err.h>
     10#include <linux/i2c.h>
     11#include <linux/init.h>
     12#include <linux/kernel.h>
     13#include <linux/module.h>
     14#include "pmbus.h"
     15
     16#define PXE1610_NUM_PAGES 3
     17
     18/* Identify chip parameters. */
     19static int pxe1610_identify(struct i2c_client *client,
     20			     struct pmbus_driver_info *info)
     21{
     22	int i;
     23
     24	for (i = 0; i < PXE1610_NUM_PAGES; i++) {
     25		if (pmbus_check_byte_register(client, i, PMBUS_VOUT_MODE)) {
     26			u8 vout_mode;
     27			int ret;
     28
     29			/* Read the register with VOUT scaling value.*/
     30			ret = pmbus_read_byte_data(client, i, PMBUS_VOUT_MODE);
     31			if (ret < 0)
     32				return ret;
     33
     34			vout_mode = ret & GENMASK(4, 0);
     35
     36			switch (vout_mode) {
     37			case 1:
     38				info->vrm_version[i] = vr12;
     39				break;
     40			case 2:
     41				info->vrm_version[i] = vr13;
     42				break;
     43			default:
     44				/*
     45				 * If prior pages are available limit operation
     46				 * to them
     47				 */
     48				if (i != 0) {
     49					info->pages = i;
     50					return 0;
     51				}
     52
     53				return -ENODEV;
     54			}
     55		}
     56	}
     57
     58	return 0;
     59}
     60
     61static struct pmbus_driver_info pxe1610_info = {
     62	.pages = PXE1610_NUM_PAGES,
     63	.format[PSC_VOLTAGE_IN] = linear,
     64	.format[PSC_VOLTAGE_OUT] = vid,
     65	.format[PSC_CURRENT_IN] = linear,
     66	.format[PSC_CURRENT_OUT] = linear,
     67	.format[PSC_TEMPERATURE] = linear,
     68	.format[PSC_POWER] = linear,
     69	.func[0] = PMBUS_HAVE_VIN
     70		| PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN
     71		| PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN
     72		| PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
     73		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
     74		| PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
     75	.func[1] = PMBUS_HAVE_VIN
     76		| PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN
     77		| PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN
     78		| PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
     79		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
     80		| PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
     81	.func[2] = PMBUS_HAVE_VIN
     82		| PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN
     83		| PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN
     84		| PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
     85		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
     86		| PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
     87	.identify = pxe1610_identify,
     88};
     89
     90static int pxe1610_probe(struct i2c_client *client)
     91{
     92	struct pmbus_driver_info *info;
     93	u8 buf[I2C_SMBUS_BLOCK_MAX];
     94	int ret;
     95
     96	if (!i2c_check_functionality(
     97			client->adapter,
     98			I2C_FUNC_SMBUS_READ_BYTE_DATA
     99			| I2C_FUNC_SMBUS_READ_WORD_DATA
    100			| I2C_FUNC_SMBUS_READ_BLOCK_DATA))
    101		return -ENODEV;
    102
    103	/*
    104	 * By default this device doesn't boot to page 0, so set page 0
    105	 * to access all pmbus registers.
    106	 */
    107	i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
    108
    109	/* Read Manufacturer id */
    110	ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
    111	if (ret < 0) {
    112		dev_err(&client->dev, "Failed to read PMBUS_MFR_ID\n");
    113		return ret;
    114	}
    115	if (ret != 2 || strncmp(buf, "XP", 2)) {
    116		dev_err(&client->dev, "MFR_ID unrecognized\n");
    117		return -ENODEV;
    118	}
    119
    120	info = devm_kmemdup(&client->dev, &pxe1610_info,
    121			    sizeof(struct pmbus_driver_info),
    122			    GFP_KERNEL);
    123	if (!info)
    124		return -ENOMEM;
    125
    126	return pmbus_do_probe(client, info);
    127}
    128
    129static const struct i2c_device_id pxe1610_id[] = {
    130	{"pxe1610", 0},
    131	{"pxe1110", 0},
    132	{"pxm1310", 0},
    133	{}
    134};
    135
    136MODULE_DEVICE_TABLE(i2c, pxe1610_id);
    137
    138static struct i2c_driver pxe1610_driver = {
    139	.driver = {
    140			.name = "pxe1610",
    141			},
    142	.probe_new = pxe1610_probe,
    143	.id_table = pxe1610_id,
    144};
    145
    146module_i2c_driver(pxe1610_driver);
    147
    148MODULE_AUTHOR("Vijay Khemka <vijaykhemka@fb.com>");
    149MODULE_DESCRIPTION("PMBus driver for Infineon PXE1610, PXE1110 and PXM1310");
    150MODULE_LICENSE("GPL");
    151MODULE_IMPORT_NS(PMBUS);