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

bel-pfe.c (3528B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Hardware monitoring driver for BEL PFE family power supplies.
      4 *
      5 * Copyright (c) 2019 Facebook Inc.
      6 */
      7
      8#include <linux/err.h>
      9#include <linux/i2c.h>
     10#include <linux/init.h>
     11#include <linux/kernel.h>
     12#include <linux/module.h>
     13#include <linux/pmbus.h>
     14
     15#include "pmbus.h"
     16
     17enum chips {pfe1100, pfe3000};
     18
     19/*
     20 * Disable status check for pfe3000 devices, because some devices report
     21 * communication error (invalid command) for VOUT_MODE command (0x20)
     22 * although correct VOUT_MODE (0x16) is returned: it leads to incorrect
     23 * exponent in linear mode.
     24 */
     25static struct pmbus_platform_data pfe3000_plat_data = {
     26	.flags = PMBUS_SKIP_STATUS_CHECK,
     27};
     28
     29static struct pmbus_driver_info pfe_driver_info[] = {
     30	[pfe1100] = {
     31		.pages = 1,
     32		.format[PSC_VOLTAGE_IN] = linear,
     33		.format[PSC_VOLTAGE_OUT] = linear,
     34		.format[PSC_CURRENT_IN] = linear,
     35		.format[PSC_CURRENT_OUT] = linear,
     36		.format[PSC_POWER] = linear,
     37		.format[PSC_TEMPERATURE] = linear,
     38		.format[PSC_FAN] = linear,
     39
     40		.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
     41			   PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
     42			   PMBUS_HAVE_POUT |
     43			   PMBUS_HAVE_VIN | PMBUS_HAVE_IIN |
     44			   PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT |
     45			   PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 |
     46			   PMBUS_HAVE_STATUS_TEMP |
     47			   PMBUS_HAVE_FAN12,
     48	},
     49
     50	[pfe3000] = {
     51		.pages = 7,
     52		.format[PSC_VOLTAGE_IN] = linear,
     53		.format[PSC_VOLTAGE_OUT] = linear,
     54		.format[PSC_CURRENT_IN] = linear,
     55		.format[PSC_CURRENT_OUT] = linear,
     56		.format[PSC_POWER] = linear,
     57		.format[PSC_TEMPERATURE] = linear,
     58		.format[PSC_FAN] = linear,
     59
     60		/* Page 0: V1. */
     61		.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
     62			   PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
     63			   PMBUS_HAVE_POUT | PMBUS_HAVE_FAN12 |
     64			   PMBUS_HAVE_VIN | PMBUS_HAVE_IIN |
     65			   PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT |
     66			   PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 |
     67			   PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_TEMP |
     68			   PMBUS_HAVE_VCAP,
     69
     70		/* Page 1: Vsb. */
     71		.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
     72			   PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
     73			   PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT |
     74			   PMBUS_HAVE_POUT,
     75
     76		/*
     77		 * Page 2: V1 Ishare.
     78		 * Page 3: Reserved.
     79		 * Page 4: V1 Cathode.
     80		 * Page 5: Vsb Cathode.
     81		 * Page 6: V1 Sense.
     82		 */
     83		.func[2] = PMBUS_HAVE_VOUT,
     84		.func[4] = PMBUS_HAVE_VOUT,
     85		.func[5] = PMBUS_HAVE_VOUT,
     86		.func[6] = PMBUS_HAVE_VOUT,
     87	},
     88};
     89
     90static const struct i2c_device_id pfe_device_id[];
     91
     92static int pfe_pmbus_probe(struct i2c_client *client)
     93{
     94	int model;
     95
     96	model = (int)i2c_match_id(pfe_device_id, client)->driver_data;
     97
     98	/*
     99	 * PFE3000-12-069RA devices may not stay in page 0 during device
    100	 * probe which leads to probe failure (read status word failed).
    101	 * So let's set the device to page 0 at the beginning.
    102	 */
    103	if (model == pfe3000) {
    104		client->dev.platform_data = &pfe3000_plat_data;
    105		i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
    106	}
    107
    108	return pmbus_do_probe(client, &pfe_driver_info[model]);
    109}
    110
    111static const struct i2c_device_id pfe_device_id[] = {
    112	{"pfe1100", pfe1100},
    113	{"pfe3000", pfe3000},
    114	{}
    115};
    116
    117MODULE_DEVICE_TABLE(i2c, pfe_device_id);
    118
    119static struct i2c_driver pfe_pmbus_driver = {
    120	.driver = {
    121		   .name = "bel-pfe",
    122	},
    123	.probe_new = pfe_pmbus_probe,
    124	.id_table = pfe_device_id,
    125};
    126
    127module_i2c_driver(pfe_pmbus_driver);
    128
    129MODULE_AUTHOR("Tao Ren <rentao.bupt@gmail.com>");
    130MODULE_DESCRIPTION("PMBus driver for BEL PFE Family Power Supplies");
    131MODULE_LICENSE("GPL");
    132MODULE_IMPORT_NS(PMBUS);