[Quanta/platform] Update IX1B to support Stretch (#2358)

* [Quanta/platform] Update IX1B to support Stretch

What I did
Update IX1B's platform folders to support Stretch
How I did it
Follow https://github.com/Azure/SONiC/wiki/Porting-Guide
How to verify it
Follow https://github.com/Azure/SONiC/wiki/Command-Reference
to verify hardware information can get from CLI correctly

Signed-off-by: Jonathan Tsai <jonathan.tsai@quantatw.com>
This commit is contained in:
Jonathan Tsai 2019-08-15 17:25:43 +08:00 committed by lguohan
parent 05d75dec07
commit a5c351a467
8 changed files with 840 additions and 1580 deletions

View File

@ -0,0 +1 @@
Quanta-IX1B-32X t1

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1 @@
obj-m:=qci_pmbus.o qci_cpld_qsfp28.o qci_platform_ix1b.o obj-m:=qci_pmbus.o qci_cpld_qsfp28.o qci_platform_ix1b.o qci_hwmon_ix1b.o

View File

@ -1,387 +0,0 @@
/*
* pmbus.h - Common defines and structures for PMBus devices
*
* Copyright (c) 2010, 2011 Ericsson AB.
* Copyright (c) 2012 Guenter Roeck
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef PMBUS_H
#define PMBUS_H
/*
* Registers
*/
#define PMBUS_PAGE 0x00
#define PMBUS_OPERATION 0x01
#define PMBUS_ON_OFF_CONFIG 0x02
#define PMBUS_CLEAR_FAULTS 0x03
#define PMBUS_PHASE 0x04
#define PMBUS_CAPABILITY 0x19
#define PMBUS_QUERY 0x1A
#define PMBUS_VOUT_MODE 0x20
#define PMBUS_VOUT_COMMAND 0x21
#define PMBUS_VOUT_TRIM 0x22
#define PMBUS_VOUT_CAL_OFFSET 0x23
#define PMBUS_VOUT_MAX 0x24
#define PMBUS_VOUT_MARGIN_HIGH 0x25
#define PMBUS_VOUT_MARGIN_LOW 0x26
#define PMBUS_VOUT_TRANSITION_RATE 0x27
#define PMBUS_VOUT_DROOP 0x28
#define PMBUS_VOUT_SCALE_LOOP 0x29
#define PMBUS_VOUT_SCALE_MONITOR 0x2A
#define PMBUS_COEFFICIENTS 0x30
#define PMBUS_POUT_MAX 0x31
#define PMBUS_FAN_CONFIG_12 0x3A
#define PMBUS_FAN_COMMAND_1 0x3B
#define PMBUS_FAN_COMMAND_2 0x3C
#define PMBUS_FAN_CONFIG_34 0x3D
#define PMBUS_FAN_COMMAND_3 0x3E
#define PMBUS_FAN_COMMAND_4 0x3F
#define PMBUS_VOUT_OV_FAULT_LIMIT 0x40
#define PMBUS_VOUT_OV_FAULT_RESPONSE 0x41
#define PMBUS_VOUT_OV_WARN_LIMIT 0x42
#define PMBUS_VOUT_UV_WARN_LIMIT 0x43
#define PMBUS_VOUT_UV_FAULT_LIMIT 0x44
#define PMBUS_VOUT_UV_FAULT_RESPONSE 0x45
#define PMBUS_IOUT_OC_FAULT_LIMIT 0x46
#define PMBUS_IOUT_OC_FAULT_RESPONSE 0x47
#define PMBUS_IOUT_OC_LV_FAULT_LIMIT 0x48
#define PMBUS_IOUT_OC_LV_FAULT_RESPONSE 0x49
#define PMBUS_IOUT_OC_WARN_LIMIT 0x4A
#define PMBUS_IOUT_UC_FAULT_LIMIT 0x4B
#define PMBUS_IOUT_UC_FAULT_RESPONSE 0x4C
#define PMBUS_OT_FAULT_LIMIT 0x4F
#define PMBUS_OT_FAULT_RESPONSE 0x50
#define PMBUS_OT_WARN_LIMIT 0x51
#define PMBUS_UT_WARN_LIMIT 0x52
#define PMBUS_UT_FAULT_LIMIT 0x53
#define PMBUS_UT_FAULT_RESPONSE 0x54
#define PMBUS_VIN_OV_FAULT_LIMIT 0x55
#define PMBUS_VIN_OV_FAULT_RESPONSE 0x56
#define PMBUS_VIN_OV_WARN_LIMIT 0x57
#define PMBUS_VIN_UV_WARN_LIMIT 0x58
#define PMBUS_VIN_UV_FAULT_LIMIT 0x59
#define PMBUS_IIN_OC_FAULT_LIMIT 0x5B
#define PMBUS_IIN_OC_WARN_LIMIT 0x5D
#define PMBUS_POUT_OP_FAULT_LIMIT 0x68
#define PMBUS_POUT_OP_WARN_LIMIT 0x6A
#define PMBUS_PIN_OP_WARN_LIMIT 0x6B
#define PMBUS_STATUS_BYTE 0x78
#define PMBUS_STATUS_WORD 0x79
#define PMBUS_STATUS_VOUT 0x7A
#define PMBUS_STATUS_IOUT 0x7B
#define PMBUS_STATUS_INPUT 0x7C
#define PMBUS_STATUS_TEMPERATURE 0x7D
#define PMBUS_STATUS_CML 0x7E
#define PMBUS_STATUS_OTHER 0x7F
#define PMBUS_STATUS_MFR_SPECIFIC 0x80
#define PMBUS_STATUS_FAN_12 0x81
#define PMBUS_STATUS_FAN_34 0x82
#define PMBUS_READ_VIN 0x88
#define PMBUS_READ_IIN 0x89
#define PMBUS_READ_VCAP 0x8A
#define PMBUS_READ_VOUT 0x8B
#define PMBUS_READ_IOUT 0x8C
#define PMBUS_READ_TEMPERATURE_1 0x8D
#define PMBUS_READ_TEMPERATURE_2 0x8E
#define PMBUS_READ_TEMPERATURE_3 0x8F
#define PMBUS_READ_FAN_SPEED_1 0x90
#define PMBUS_READ_FAN_SPEED_2 0x91
#define PMBUS_READ_FAN_SPEED_3 0x92
#define PMBUS_READ_FAN_SPEED_4 0x93
#define PMBUS_READ_DUTY_CYCLE 0x94
#define PMBUS_READ_FREQUENCY 0x95
#define PMBUS_READ_POUT 0x96
#define PMBUS_READ_PIN 0x97
#define PMBUS_REVISION 0x98
#define PMBUS_MFR_ID 0x99
#define PMBUS_MFR_MODEL 0x9A
#define PMBUS_MFR_REVISION 0x9B
#define PMBUS_MFR_LOCATION 0x9C
#define PMBUS_MFR_DATE 0x9D
#define PMBUS_MFR_SERIAL 0x9E
/*
* Virtual registers.
* Useful to support attributes which are not supported by standard PMBus
* registers but exist as manufacturer specific registers on individual chips.
* Must be mapped to real registers in device specific code.
*
* Semantics:
* Virtual registers are all word size.
* READ registers are read-only; writes are either ignored or return an error.
* RESET registers are read/write. Reading reset registers returns zero
* (used for detection), writing any value causes the associated history to be
* reset.
* Virtual registers have to be handled in device specific driver code. Chip
* driver code returns non-negative register values if a virtual register is
* supported, or a negative error code if not. The chip driver may return
* -ENODATA or any other error code in this case, though an error code other
* than -ENODATA is handled more efficiently and thus preferred. Either case,
* the calling PMBus core code will abort if the chip driver returns an error
* code when reading or writing virtual registers.
*/
#define PMBUS_VIRT_BASE 0x100
#define PMBUS_VIRT_READ_TEMP_AVG (PMBUS_VIRT_BASE + 0)
#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 1)
#define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 2)
#define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 3)
#define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 4)
#define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 5)
#define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 6)
#define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 7)
#define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 8)
#define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 9)
#define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 10)
#define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 11)
#define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 12)
#define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 13)
#define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 14)
#define PMBUS_VIRT_READ_POUT_AVG (PMBUS_VIRT_BASE + 15)
#define PMBUS_VIRT_READ_POUT_MAX (PMBUS_VIRT_BASE + 16)
#define PMBUS_VIRT_RESET_POUT_HISTORY (PMBUS_VIRT_BASE + 17)
#define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 18)
#define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 19)
#define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 20)
#define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 21)
#define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 22)
#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 23)
#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 24)
#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 25)
#define PMBUS_VIRT_READ_TEMP2_AVG (PMBUS_VIRT_BASE + 26)
#define PMBUS_VIRT_READ_TEMP2_MIN (PMBUS_VIRT_BASE + 27)
#define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 28)
#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 29)
#define PMBUS_VIRT_READ_VMON (PMBUS_VIRT_BASE + 30)
#define PMBUS_VIRT_VMON_UV_WARN_LIMIT (PMBUS_VIRT_BASE + 31)
#define PMBUS_VIRT_VMON_OV_WARN_LIMIT (PMBUS_VIRT_BASE + 32)
#define PMBUS_VIRT_VMON_UV_FAULT_LIMIT (PMBUS_VIRT_BASE + 33)
#define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34)
#define PMBUS_VIRT_STATUS_VMON (PMBUS_VIRT_BASE + 35)
/*
* CAPABILITY
*/
#define PB_CAPABILITY_SMBALERT (1<<4)
#define PB_CAPABILITY_ERROR_CHECK (1<<7)
/*
* VOUT_MODE
*/
#define PB_VOUT_MODE_MODE_MASK 0xe0
#define PB_VOUT_MODE_PARAM_MASK 0x1f
#define PB_VOUT_MODE_LINEAR 0x00
#define PB_VOUT_MODE_VID 0x20
#define PB_VOUT_MODE_DIRECT 0x40
/*
* Fan configuration
*/
#define PB_FAN_2_PULSE_MASK ((1 << 0) | (1 << 1))
#define PB_FAN_2_RPM (1 << 2)
#define PB_FAN_2_INSTALLED (1 << 3)
#define PB_FAN_1_PULSE_MASK ((1 << 4) | (1 << 5))
#define PB_FAN_1_RPM (1 << 6)
#define PB_FAN_1_INSTALLED (1 << 7)
/*
* STATUS_BYTE, STATUS_WORD (lower)
*/
#define PB_STATUS_NONE_ABOVE (1<<0)
#define PB_STATUS_CML (1<<1)
#define PB_STATUS_TEMPERATURE (1<<2)
#define PB_STATUS_VIN_UV (1<<3)
#define PB_STATUS_IOUT_OC (1<<4)
#define PB_STATUS_VOUT_OV (1<<5)
#define PB_STATUS_OFF (1<<6)
#define PB_STATUS_BUSY (1<<7)
/*
* STATUS_WORD (upper)
*/
#define PB_STATUS_UNKNOWN (1<<8)
#define PB_STATUS_OTHER (1<<9)
#define PB_STATUS_FANS (1<<10)
#define PB_STATUS_POWER_GOOD_N (1<<11)
#define PB_STATUS_WORD_MFR (1<<12)
#define PB_STATUS_INPUT (1<<13)
#define PB_STATUS_IOUT_POUT (1<<14)
#define PB_STATUS_VOUT (1<<15)
/*
* STATUS_IOUT
*/
#define PB_POUT_OP_WARNING (1<<0)
#define PB_POUT_OP_FAULT (1<<1)
#define PB_POWER_LIMITING (1<<2)
#define PB_CURRENT_SHARE_FAULT (1<<3)
#define PB_IOUT_UC_FAULT (1<<4)
#define PB_IOUT_OC_WARNING (1<<5)
#define PB_IOUT_OC_LV_FAULT (1<<6)
#define PB_IOUT_OC_FAULT (1<<7)
/*
* STATUS_VOUT, STATUS_INPUT
*/
#define PB_VOLTAGE_UV_FAULT (1<<4)
#define PB_VOLTAGE_UV_WARNING (1<<5)
#define PB_VOLTAGE_OV_WARNING (1<<6)
#define PB_VOLTAGE_OV_FAULT (1<<7)
/*
* STATUS_INPUT
*/
#define PB_PIN_OP_WARNING (1<<0)
#define PB_IIN_OC_WARNING (1<<1)
#define PB_IIN_OC_FAULT (1<<2)
/*
* STATUS_TEMPERATURE
*/
#define PB_TEMP_UT_FAULT (1<<4)
#define PB_TEMP_UT_WARNING (1<<5)
#define PB_TEMP_OT_WARNING (1<<6)
#define PB_TEMP_OT_FAULT (1<<7)
/*
* STATUS_FAN
*/
#define PB_FAN_AIRFLOW_WARNING (1<<0)
#define PB_FAN_AIRFLOW_FAULT (1<<1)
#define PB_FAN_FAN2_SPEED_OVERRIDE (1<<2)
#define PB_FAN_FAN1_SPEED_OVERRIDE (1<<3)
#define PB_FAN_FAN2_WARNING (1<<4)
#define PB_FAN_FAN1_WARNING (1<<5)
#define PB_FAN_FAN2_FAULT (1<<6)
#define PB_FAN_FAN1_FAULT (1<<7)
/*
* CML_FAULT_STATUS
*/
#define PB_CML_FAULT_OTHER_MEM_LOGIC (1<<0)
#define PB_CML_FAULT_OTHER_COMM (1<<1)
#define PB_CML_FAULT_PROCESSOR (1<<3)
#define PB_CML_FAULT_MEMORY (1<<4)
#define PB_CML_FAULT_PACKET_ERROR (1<<5)
#define PB_CML_FAULT_INVALID_DATA (1<<6)
#define PB_CML_FAULT_INVALID_COMMAND (1<<7)
enum pmbus_sensor_classes {
PSC_VOLTAGE_IN = 0,
PSC_VOLTAGE_OUT,
PSC_CURRENT_IN,
PSC_CURRENT_OUT,
PSC_POWER,
PSC_TEMPERATURE,
PSC_FAN,
PSC_NUM_CLASSES /* Number of power sensor classes */
};
#define PMBUS_PAGES 32 /* Per PMBus specification */
/* Functionality bit mask */
#define PMBUS_HAVE_VIN (1 << 0)
#define PMBUS_HAVE_VCAP (1 << 1)
#define PMBUS_HAVE_VOUT (1 << 2)
#define PMBUS_HAVE_IIN (1 << 3)
#define PMBUS_HAVE_IOUT (1 << 4)
#define PMBUS_HAVE_PIN (1 << 5)
#define PMBUS_HAVE_POUT (1 << 6)
#define PMBUS_HAVE_FAN12 (1 << 7)
#define PMBUS_HAVE_FAN34 (1 << 8)
#define PMBUS_HAVE_TEMP (1 << 9)
#define PMBUS_HAVE_TEMP2 (1 << 10)
#define PMBUS_HAVE_TEMP3 (1 << 11)
#define PMBUS_HAVE_STATUS_VOUT (1 << 12)
#define PMBUS_HAVE_STATUS_IOUT (1 << 13)
#define PMBUS_HAVE_STATUS_INPUT (1 << 14)
#define PMBUS_HAVE_STATUS_TEMP (1 << 15)
#define PMBUS_HAVE_STATUS_FAN12 (1 << 16)
#define PMBUS_HAVE_STATUS_FAN34 (1 << 17)
#define PMBUS_HAVE_VMON (1 << 18)
#define PMBUS_HAVE_STATUS_VMON (1 << 19)
enum pmbus_data_format { linear = 0, direct, vid };
struct pmbus_driver_info {
int pages; /* Total number of pages */
enum pmbus_data_format format[PSC_NUM_CLASSES];
/*
* Support one set of coefficients for each sensor type
* Used for chips providing data in direct mode.
*/
int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */
int b[PSC_NUM_CLASSES]; /* offset */
int R[PSC_NUM_CLASSES]; /* exponent */
u32 func[PMBUS_PAGES]; /* Functionality, per page */
/*
* The following functions map manufacturing specific register values
* to PMBus standard register values. Specify only if mapping is
* necessary.
* Functions return the register value (read) or zero (write) if
* successful. A return value of -ENODATA indicates that there is no
* manufacturer specific register, but that a standard PMBus register
* may exist. Any other negative return value indicates that the
* register does not exist, and that no attempt should be made to read
* the standard register.
*/
int (*read_byte_data)(struct i2c_client *client, int page, int reg);
int (*read_word_data)(struct i2c_client *client, int page, int reg);
int (*write_word_data)(struct i2c_client *client, int page, int reg,
u16 word);
int (*write_byte)(struct i2c_client *client, int page, u8 value);
/*
* The identify function determines supported PMBus functionality.
* This function is only necessary if a chip driver supports multiple
* chips, and the chip functionality is not pre-determined.
*/
int (*identify)(struct i2c_client *client,
struct pmbus_driver_info *info);
};
/* Function declarations */
void pmbus_clear_cache(struct i2c_client *client);
int pmbus_set_page(struct i2c_client *client, u8 page);
int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word);
int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
void pmbus_clear_faults(struct i2c_client *client);
bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
struct pmbus_driver_info *info);
int pmbus_do_remove(struct i2c_client *client);
const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client
*client);
#endif /* PMBUS_H */

View File

@ -0,0 +1,425 @@
/*
* A hwmon driver for Cypress PSoC fan controller and thermal sensor
*
* This PSoC is a specific customize design only for Quanta Switch
* This driver is also monitoring pca9555 which is related to
* RPSU detection and LED controll in front panel. Instead a standalone
* driver, it should be combined with gpio lib to work correctly.
*
* Copyright (C) 2014 Quanta Inc.
*
* Author: Luffy Cheng <luffy.cheng@quantatw.com>
*
* Based on:
* adt7470.c from Darrick J. Wong <djwong@us.ibm.com>
* Copyright (C) 2007 IBM
*
* 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
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/log2.h>
#include <linux/kthread.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/leds.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#define QUANTA_IX1_PSU_GPIO_PSU1_PRSNT_N 16
#define QUANTA_IX1_PSU_GPIO_PSU1_PWRGD 17
#define QUANTA_IX1_PSU_GPIO_PSU2_PRSNT_N 19
#define QUANTA_IX1_PSU_GPIO_PSU2_PWRGD 20
#define QUANTA_IX1_FAN_GPIO_FAN1_PRSNT_N 36
#define QUANTA_IX1_FAN_GPIO_FAN2_PRSNT_N 37
#define QUANTA_IX1_FAN_GPIO_FAN3_PRSNT_N 38
#define QUANTA_IX1_FAN_GPIO_FAN4_PRSNT_N 39
#define AUTO_UPDATE_INTERVAL 10000
enum psu_nr {
PSU1 = 0,
PSU2
};
enum fan_nr {
FAN1 = 0,
FAN2,
FAN3,
FAN4,
};
enum led_color {
LED_RED = 1,
LED_GREEN,
LED_COLOR_OFF
};
int hwmon_enable = 1;
struct qci_hwmon_data {
struct device *hwmon_dev;
struct task_struct *auto_update;
struct completion auto_update_stop;
unsigned int auto_update_interval;
struct attribute_group attrs;
};
static void simple_atoi(const char *buf, int *output_val)
{
int negative = 0;
if (buf[0] == '-')
{
negative = 1;
buf++;
}
while (*buf >= '0' && *buf <= '9') {
*output_val = *output_val * 10 + *buf - '0';
buf++;
}
if (negative)
*output_val = 0 - *output_val;
}
int read_gpio_file(int gpio)
{
struct file *fp;
char buffer[512], file_path[255];
int offset = 0;
int ret;
/*open the file in read mode*/
sprintf(file_path, "/sys/class/gpio/gpio%d/value", gpio);
fp = filp_open(file_path, O_RDONLY, 0);
if (IS_ERR(fp)) {
printk("Cannot open the file %ld\n", PTR_ERR(fp));
return -1;
}
/*Read the data to the end of the file*/
while (1) {
ret = kernel_read(fp, offset, buffer, 512);
if (ret > 0) {
offset += ret;
}
else {
break;
}
}
filp_close(fp, NULL);
simple_atoi(buffer, &ret);
return ret;
}
static ssize_t get_hwmon_status(struct device *dev,
struct device_attribute *devattr, char *buf)
{
return sprintf(buf, "%d\n", hwmon_enable);
}
static ssize_t set_hwmon_status(struct device *dev,
struct device_attribute *devattr, const char *buf, size_t count)
{
long enable;
if (kstrtol(buf, 0, &enable))
return -EINVAL;
if ((enable != 1) && (enable != 0))
return -EINVAL;
hwmon_enable = enable;
return count;
}
static u8 read_fan_present(u8 fan_nr)
{
u8 value = 0;
if (fan_nr == PSU1)
value = read_gpio_file(QUANTA_IX1_FAN_GPIO_FAN1_PRSNT_N);
else if (fan_nr == FAN2)
value = read_gpio_file(QUANTA_IX1_FAN_GPIO_FAN2_PRSNT_N);
else if (fan_nr == FAN3)
value = read_gpio_file(QUANTA_IX1_FAN_GPIO_FAN3_PRSNT_N);
else if (fan_nr == FAN4)
value = read_gpio_file(QUANTA_IX1_FAN_GPIO_FAN4_PRSNT_N);
else
return -1;
return value;
}
static u8 read_psu_present(u8 psu_nr)
{
u8 value = 0;
if (psu_nr == PSU1)
value = read_gpio_file(QUANTA_IX1_PSU_GPIO_PSU1_PRSNT_N);
else if (psu_nr == PSU2)
value = read_gpio_file(QUANTA_IX1_PSU_GPIO_PSU2_PRSNT_N);
else
return -1;
return value;
}
static u8 read_psu_AC_good(u8 psu_nr)
{
u8 value = 0;
if (psu_nr == PSU1)
value = read_gpio_file(QUANTA_IX1_PSU_GPIO_PSU1_PWRGD);
else if (psu_nr == PSU2)
value = read_gpio_file(QUANTA_IX1_PSU_GPIO_PSU2_PWRGD);
else
return -1;
return value;
}
static u8 front_led_set(char *name, char *value)
{
struct file *fp;
char file_path[255];
int ret;
mm_segment_t oldfs;
sprintf(file_path, "/sys/class/leds/%s/brightness", name);
fp = filp_open(file_path, O_RDWR | O_CREAT, 0644);
if (IS_ERR(fp)) {
printk("Cannot open the file %ld\n", PTR_ERR(fp));
return -1;
}
oldfs = get_fs();
set_fs(get_ds());
ret = vfs_write(fp, value, sizeof(value), &fp->f_pos);
set_fs(oldfs);
filp_close(fp, NULL);
return 0;
}
static u8 update_led(u8 *fan_status, u8 *psu_status)
{
u8 i = 0, fan_color = LED_GREEN;
// Update FAN front LED
for (i = 0; i < 4; i++)
{
if (fan_status[i] == 1)
{
fan_color = LED_RED;
front_led_set("front_led_fan_red", "1");
front_led_set("front_led_fan_green", "0");
break;
}
}
if (fan_color == LED_GREEN)
{
front_led_set("front_led_fan_red", "0");
front_led_set("front_led_fan_green", "1");
}
// Update PSU1 front LED
if ((psu_status[0] == 0) && (psu_status[2] == 1))
{
front_led_set("front_led_psu1_green", "1");
front_led_set("front_led_psu1_red", "0");
}
else if (psu_status[0] == 1)
{
front_led_set("front_led_psu1_green", "0");
front_led_set("front_led_psu1_red", "0");
}
else
{
front_led_set("front_led_psu1_green", "0");
front_led_set("front_led_psu1_red", "1");
}
// Update PSU2 front LED
if ((psu_status[1] == 0) && (psu_status[3] == 1))
{
front_led_set("front_led_psu2_green", "1");
front_led_set("front_led_psu2_red", "0");
}
else if (psu_status[1] == 1)
{
front_led_set("front_led_psu2_green", "0");
front_led_set("front_led_psu2_red", "0");
}
else
{
front_led_set("front_led_psu2_green", "0");
front_led_set("front_led_psu2_red", "1");
}
return 0;
}
static int led_update_thread(void *p)
{
struct platform_device *pdev = p;
struct qci_hwmon_data *data = platform_get_drvdata(pdev);
u8 i = 0;
u8 psu_status[4] = {0}; // {PSU1-2 present, PSU1-2 AC good}
u8 fan_status[4] = {0}; // {FAN1-4 present}
while (!kthread_should_stop()) {
if (hwmon_enable)
{
for (i = 0; i < 4; i++)
{
fan_status[i] = read_fan_present(i);
}
for (i = 0; i < 2; i++)
{
psu_status[i] = read_psu_present(i);
psu_status[i+2] = read_psu_AC_good(i);
}
update_led(fan_status, psu_status);
}
if (kthread_should_stop())
break;
msleep_interruptible(data->auto_update_interval);
}
complete_all(&data->auto_update_stop);
return 0;
}
static DEVICE_ATTR(hwmon_status, S_IWUSR | S_IRUGO, get_hwmon_status, set_hwmon_status);
static struct attribute *qci_hwmon_attr[] = {
&dev_attr_hwmon_status.attr,
NULL
};
static int qci_hwmon_probe(struct platform_device *pdev)
{
struct qci_hwmon_data *data;
int err;
data = devm_kzalloc(&pdev->dev, sizeof(struct qci_hwmon_data),
GFP_KERNEL);
if (!data)
{
return -ENOMEM;
}
data->auto_update_interval = AUTO_UPDATE_INTERVAL;
data->attrs.attrs = qci_hwmon_attr;
platform_set_drvdata(pdev, data);
dev_info(&pdev->dev, "%s device found\n", pdev->name);
data->hwmon_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
}
err = sysfs_create_group(&pdev->dev.kobj, &data->attrs);
if (err)
return err;
init_completion(&data->auto_update_stop);
data->auto_update = kthread_run(led_update_thread, pdev,
dev_name(data->hwmon_dev));
if (IS_ERR(data->auto_update)) {
err = PTR_ERR(data->auto_update);
goto exit_unregister;
}
return 0;
exit_unregister:
hwmon_device_unregister(data->hwmon_dev);
return err;
}
static int qci_hwmon_remove(struct platform_device *pdev)
{
struct qci_hwmon_data *data = platform_get_drvdata(pdev);
kthread_stop(data->auto_update);
wait_for_completion(&data->auto_update_stop);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&pdev->dev.kobj, &data->attrs);
return 0;
}
static struct platform_driver qci_hwmon_driver = {
.probe = qci_hwmon_probe,
.remove = qci_hwmon_remove,
.driver = {
.name = "qci-hwmon",
.owner = THIS_MODULE,
},
};
static int __init qci_hwmon_init(void)
{
platform_driver_register(&qci_hwmon_driver);
return 0;
}
static void __exit qci_hwmon_exit(void)
{
platform_driver_unregister(&qci_hwmon_driver);
}
module_init(qci_hwmon_init);
module_exit(qci_hwmon_exit);
MODULE_AUTHOR("Quanta Computer Inc.");
MODULE_DESCRIPTION("Quanta Switch Hardware Monitor driver");
MODULE_LICENSE("GPL");

View File

@ -179,67 +179,67 @@ static struct pca953x_platform_data pca9555ID_data = {
static struct i2c_board_info ix1b_i2c_devices[] = { static struct i2c_board_info ix1b_i2c_devices[] = {
{ {
I2C_BOARD_INFO("pca9546", 0x77), I2C_BOARD_INFO("pca9546", 0x77), // 0
.platform_data = &pca9546_1_data, .platform_data = &pca9546_1_data,
}, },
{ {
I2C_BOARD_INFO("pca9546", 0x72), I2C_BOARD_INFO("pca9546", 0x72), // 1
.platform_data = &pca9546_2_data, .platform_data = &pca9546_2_data,
}, },
{ {
I2C_BOARD_INFO("pca9555", 0x26), I2C_BOARD_INFO("pca9555", 0x26), // 2
.platform_data = &pca9555psu1_data, .platform_data = &pca9555psu1_data,
}, },
{ {
I2C_BOARD_INFO("24c02", 0x54), I2C_BOARD_INFO("24c02", 0x54), // 3
}, },
{ {
I2C_BOARD_INFO("pca9548", 0x73), I2C_BOARD_INFO("pca9548", 0x73), // 4
.platform_data = &pca9548sfp1_data, .platform_data = &pca9548sfp1_data,
}, },
{ {
I2C_BOARD_INFO("pca9548", 0x74), I2C_BOARD_INFO("pca9548", 0x74), // 5
.platform_data = &pca9548sfp2_data, .platform_data = &pca9548sfp2_data,
}, },
{ {
I2C_BOARD_INFO("pca9548", 0x75), I2C_BOARD_INFO("pca9548", 0x75), // 6
.platform_data = &pca9548sfp3_data, .platform_data = &pca9548sfp3_data,
}, },
{ {
I2C_BOARD_INFO("pca9548", 0x76), I2C_BOARD_INFO("pca9548", 0x76), // 7
.platform_data = &pca9548sfp4_data, .platform_data = &pca9548sfp4_data,
}, },
{ {
I2C_BOARD_INFO("CPLD-QSFP28", 0x38), I2C_BOARD_INFO("CPLD-QSFP28", 0x38), // 8
}, },
{ {
I2C_BOARD_INFO("CPLD-QSFP28", 0x39), I2C_BOARD_INFO("CPLD-QSFP28", 0x39), // 9
}, },
{ {
I2C_BOARD_INFO("pca9555", 0x23), I2C_BOARD_INFO("pca9555", 0x23), // 10
.platform_data = &pca9555ID_data, .platform_data = &pca9555ID_data,
}, },
{ {
I2C_BOARD_INFO("pca9555", 0x25), I2C_BOARD_INFO("pca9555", 0x25), // 11
.platform_data = &pca9555fan_data, .platform_data = &pca9555fan_data,
}, },
{ {
I2C_BOARD_INFO("qci_pmbus_ix1b", 0x5f), I2C_BOARD_INFO("qci_pmbus_ix1b", 0x5f), // 12
}, },
{ {
I2C_BOARD_INFO("qci_pmbus_ix1b", 0x59), I2C_BOARD_INFO("qci_pmbus_ix1b", 0x59), // 13
}, },
#if defined(QUANTA_CPU_RGL) #if defined(QUANTA_CPU_RGL)
{ {
I2C_BOARD_INFO("pca9546", 0x71), I2C_BOARD_INFO("pca9546", 0x71), // 14
.platform_data = &pca9546_cpu1_data, .platform_data = &pca9546_cpu1_data,
}, },
{ {
I2C_BOARD_INFO("pca9555", 0x20), I2C_BOARD_INFO("pca9555", 0x20), // 15
.platform_data = &pca9555_cpuled_data, .platform_data = &pca9555_cpuled_data,
}, },
{ {
I2C_BOARD_INFO("24c02", 0x50), I2C_BOARD_INFO("optoe1", 0x50), // 16
}, },
#endif #endif
}; };
@ -347,6 +347,13 @@ static struct platform_device system_led_dev = {
}, },
}; };
static struct platform_device qci_hwmon_device = {
.name = "qci-hwmon",
.id = 0,
.dev = {
},
};
static struct platform_device *ix1b_device; static struct platform_device *ix1b_device;
struct gpio_led_data { struct gpio_led_data {
@ -390,68 +397,68 @@ static int __init ix1b_platform_init(void)
goto fail_platform_device; goto fail_platform_device;
adapter = i2c_get_adapter(0); adapter = i2c_get_adapter(0);
client = i2c_new_device(adapter, &ix1b_i2c_devices[0]); // pca9546_1 client = i2c_new_device(adapter, &ix1b_i2c_devices[0]); // pca9546_1 - Address: 0x77
printk("[CC] NEW device pca9546_1\n"); printk("[CC] NEW device pca9546_1\n");
client = i2c_new_device(adapter, &ix1b_i2c_devices[1]); // pca9546_2 client = i2c_new_device(adapter, &ix1b_i2c_devices[1]); // pca9546_2 - Address: 0x72
printk("[CC] NEW device pca9546_2\n"); printk("[CC] NEW device pca9546_2\n");
#if defined(QUANTA_CPU_RGL) #if defined(QUANTA_CPU_RGL)
client = i2c_new_device(adapter, &ix1b_i2c_devices[14]); // cpu pca9546_1 client = i2c_new_device(adapter, &ix1b_i2c_devices[14]); // cpu pca9546_1 - Address: 0x71
printk("[CC] NEW device cpu pca9546_1\n"); printk("[CC] NEW device cpu pca9546_1\n");
#endif #endif
i2c_put_adapter(adapter); i2c_put_adapter(adapter);
adapter = i2c_get_adapter(0x14); adapter = i2c_get_adapter(0x14);
client = i2c_new_device(adapter, &ix1b_i2c_devices[12]); // pmbus_psu1 client = i2c_new_device(adapter, &ix1b_i2c_devices[12]); // pmbus_psu1 - Address: 0x5f
printk("[CC] NEW device pmbus_psu1\n"); printk("[CC] NEW device pmbus_psu1\n");
i2c_put_adapter(adapter); i2c_put_adapter(adapter);
adapter = i2c_get_adapter(0x15); adapter = i2c_get_adapter(0x15);
client = i2c_new_device(adapter, &ix1b_i2c_devices[13]); // pmbus_psu2 client = i2c_new_device(adapter, &ix1b_i2c_devices[13]); // pmbus_psu2 - Address: 0x59
printk("[CC] NEW device pmbus_psu2\n"); printk("[CC] NEW device pmbus_psu2\n");
i2c_put_adapter(adapter); i2c_put_adapter(adapter);
adapter = i2c_get_adapter(0x16); adapter = i2c_get_adapter(0x16);
client = i2c_new_device(adapter, &ix1b_i2c_devices[2]); // pca9555-PSU1 client = i2c_new_device(adapter, &ix1b_i2c_devices[2]); // pca9555-PSU1 - Address: 0x26
printk("[CC] NEW device pca9555-PSU1\n"); printk("[CC] NEW device pca9555-PSU1\n");
client = i2c_new_device(adapter, &ix1b_i2c_devices[3]); // MB_BOARDINFO_EEPROM client = i2c_new_device(adapter, &ix1b_i2c_devices[3]); // MB_BOARDINFO_EEPROM - Address: 0x54
printk("[CC] NEW device MB_BOARDINFO_EEPROM\n"); printk("[CC] NEW device MB_BOARDINFO_EEPROM\n");
client = i2c_new_device(adapter, &ix1b_i2c_devices[10]); // pca9555-ID client = i2c_new_device(adapter, &ix1b_i2c_devices[10]); // pca9555-ID - Address: 0x23
printk("[CC] NEW device pca9555-ID\n"); printk("[CC] NEW device pca9555-ID\n");
i2c_put_adapter(adapter); i2c_put_adapter(adapter);
adapter = i2c_get_adapter(0x17); adapter = i2c_get_adapter(0x17);
client = i2c_new_device(adapter, &ix1b_i2c_devices[11]); // pca9555-fan client = i2c_new_device(adapter, &ix1b_i2c_devices[11]); // pca9555-fan - Address: 0x25
printk("[CC] NEW device pca9555-fan\n"); printk("[CC] NEW device pca9555-fan\n");
i2c_put_adapter(adapter); i2c_put_adapter(adapter);
adapter = i2c_get_adapter(0x10); adapter = i2c_get_adapter(0x10);
client = i2c_new_device(adapter, &ix1b_i2c_devices[4]); // pca9548_2 SFP client = i2c_new_device(adapter, &ix1b_i2c_devices[4]); // pca9548_1 SFP - Address: 0x73
printk("[CC] NEW device pca9548_1 SFP\n");
client = i2c_new_device(adapter, &ix1b_i2c_devices[5]); // pca9548_2 SFP - Address: 0x74
printk("[CC] NEW device pca9548_2 SFP\n"); printk("[CC] NEW device pca9548_2 SFP\n");
client = i2c_new_device(adapter, &ix1b_i2c_devices[5]); // pca9548_3 SFP client = i2c_new_device(adapter, &ix1b_i2c_devices[6]); // pca9548_3 SFP - Address: 0x75
printk("[CC] NEW device pca9548_3 SFP\n"); printk("[CC] NEW device pca9548_3 SFP\n");
client = i2c_new_device(adapter, &ix1b_i2c_devices[6]); // pca9548_4 SFP client = i2c_new_device(adapter, &ix1b_i2c_devices[8]); // CPLD2 - Address: 0x38
printk("[CC] NEW device pca9548_4 SFP\n");
client = i2c_new_device(adapter, &ix1b_i2c_devices[8]); // CPLD2
printk("[CC] NEW device CPLD2\n"); printk("[CC] NEW device CPLD2\n");
client = i2c_new_device(adapter, &ix1b_i2c_devices[9]); // CPLD3 client = i2c_new_device(adapter, &ix1b_i2c_devices[9]); // CPLD3 - Address: 0x39
printk("[CC] NEW device CPLD3\n"); printk("[CC] NEW device CPLD3\n");
i2c_put_adapter(adapter); i2c_put_adapter(adapter);
adapter = i2c_get_adapter(0x11); adapter = i2c_get_adapter(0x11);
client = i2c_new_device(adapter, &ix1b_i2c_devices[7]); // pca9548_5 SFP client = i2c_new_device(adapter, &ix1b_i2c_devices[7]); // pca9548_4 SFP - Address: 0x76
printk("[CC] NEW device pca9548_5 SFP\n"); printk("[CC] NEW device pca9548_4 SFP\n");
i2c_put_adapter(adapter); i2c_put_adapter(adapter);
#if defined(QUANTA_CPU_RGL) #if defined(QUANTA_CPU_RGL)
adapter = i2c_get_adapter(0x18); adapter = i2c_get_adapter(0x18);
client = i2c_new_device(adapter, &ix1b_i2c_devices[15]); // cpu pca9555_1 client = i2c_new_device(adapter, &ix1b_i2c_devices[15]); // cpu pca9555_1 - Address: 0x20
printk("[CC] NEW device cpu pca9555_1\n"); printk("[CC] NEW device cpu pca9555_1\n");
i2c_put_adapter(adapter); i2c_put_adapter(adapter);
for(i = 0x20; i < 0x40; i++) for(i = 0x20; i < 0x40; i++)
{ {
adapter = i2c_get_adapter(i); adapter = i2c_get_adapter(i);
client = i2c_new_device(adapter, &ix1b_i2c_devices[16]); // eeprom for loopback module client = i2c_new_device(adapter, &ix1b_i2c_devices[16]); // eeprom for loopback module - Address: 0x50
i2c_put_adapter(adapter); i2c_put_adapter(adapter);
} }
printk("[CC] NEW device eeprom\n"); printk("[CC] NEW device eeprom\n");
@ -466,6 +473,9 @@ static int __init ix1b_platform_init(void)
} }
printk("[CC] NEW device led\n"); printk("[CC] NEW device led\n");
platform_device_register(&qci_hwmon_device);
printk("[CC] NEW device hwmon\n");
return 0; return 0;
fail_platform_device: fail_platform_device:

View File

@ -27,14 +27,268 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
//#include <../drivers/hwmon/pmbus/pmbus.h>
#include "pmbus.h"
#include <linux/delay.h> #include <linux/delay.h>
enum projects { ly8, ix1, ix2, ix1b }; enum projects { ly8, ix1, ix2, ix1b };
#define DELAY_TIME 1000 /* uS */ #define DELAY_TIME 1000 /* uS */
/* Pmbus reg defines are copied from drivers/hwmon/pmbus/pmbus.h*/
/*
* Registers
*/
enum pmbus_regs {
PMBUS_PAGE = 0x00,
PMBUS_OPERATION = 0x01,
PMBUS_ON_OFF_CONFIG = 0x02,
PMBUS_CLEAR_FAULTS = 0x03,
PMBUS_PHASE = 0x04,
PMBUS_CAPABILITY = 0x19,
PMBUS_QUERY = 0x1A,
PMBUS_VOUT_MODE = 0x20,
PMBUS_VOUT_COMMAND = 0x21,
PMBUS_VOUT_TRIM = 0x22,
PMBUS_VOUT_CAL_OFFSET = 0x23,
PMBUS_VOUT_MAX = 0x24,
PMBUS_VOUT_MARGIN_HIGH = 0x25,
PMBUS_VOUT_MARGIN_LOW = 0x26,
PMBUS_VOUT_TRANSITION_RATE = 0x27,
PMBUS_VOUT_DROOP = 0x28,
PMBUS_VOUT_SCALE_LOOP = 0x29,
PMBUS_VOUT_SCALE_MONITOR = 0x2A,
PMBUS_COEFFICIENTS = 0x30,
PMBUS_POUT_MAX = 0x31,
PMBUS_FAN_CONFIG_12 = 0x3A,
PMBUS_FAN_COMMAND_1 = 0x3B,
PMBUS_FAN_COMMAND_2 = 0x3C,
PMBUS_FAN_CONFIG_34 = 0x3D,
PMBUS_FAN_COMMAND_3 = 0x3E,
PMBUS_FAN_COMMAND_4 = 0x3F,
PMBUS_VOUT_OV_FAULT_LIMIT = 0x40,
PMBUS_VOUT_OV_FAULT_RESPONSE = 0x41,
PMBUS_VOUT_OV_WARN_LIMIT = 0x42,
PMBUS_VOUT_UV_WARN_LIMIT = 0x43,
PMBUS_VOUT_UV_FAULT_LIMIT = 0x44,
PMBUS_VOUT_UV_FAULT_RESPONSE = 0x45,
PMBUS_IOUT_OC_FAULT_LIMIT = 0x46,
PMBUS_IOUT_OC_FAULT_RESPONSE = 0x47,
PMBUS_IOUT_OC_LV_FAULT_LIMIT = 0x48,
PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49,
PMBUS_IOUT_OC_WARN_LIMIT = 0x4A,
PMBUS_IOUT_UC_FAULT_LIMIT = 0x4B,
PMBUS_IOUT_UC_FAULT_RESPONSE = 0x4C,
PMBUS_OT_FAULT_LIMIT = 0x4F,
PMBUS_OT_FAULT_RESPONSE = 0x50,
PMBUS_OT_WARN_LIMIT = 0x51,
PMBUS_UT_WARN_LIMIT = 0x52,
PMBUS_UT_FAULT_LIMIT = 0x53,
PMBUS_UT_FAULT_RESPONSE = 0x54,
PMBUS_VIN_OV_FAULT_LIMIT = 0x55,
PMBUS_VIN_OV_FAULT_RESPONSE = 0x56,
PMBUS_VIN_OV_WARN_LIMIT = 0x57,
PMBUS_VIN_UV_WARN_LIMIT = 0x58,
PMBUS_VIN_UV_FAULT_LIMIT = 0x59,
PMBUS_IIN_OC_FAULT_LIMIT = 0x5B,
PMBUS_IIN_OC_WARN_LIMIT = 0x5D,
PMBUS_POUT_OP_FAULT_LIMIT = 0x68,
PMBUS_POUT_OP_WARN_LIMIT = 0x6A,
PMBUS_PIN_OP_WARN_LIMIT = 0x6B,
PMBUS_STATUS_BYTE = 0x78,
PMBUS_STATUS_WORD = 0x79,
PMBUS_STATUS_VOUT = 0x7A,
PMBUS_STATUS_IOUT = 0x7B,
PMBUS_STATUS_INPUT = 0x7C,
PMBUS_STATUS_TEMPERATURE = 0x7D,
PMBUS_STATUS_CML = 0x7E,
PMBUS_STATUS_OTHER = 0x7F,
PMBUS_STATUS_MFR_SPECIFIC = 0x80,
PMBUS_STATUS_FAN_12 = 0x81,
PMBUS_STATUS_FAN_34 = 0x82,
PMBUS_READ_VIN = 0x88,
PMBUS_READ_IIN = 0x89,
PMBUS_READ_VCAP = 0x8A,
PMBUS_READ_VOUT = 0x8B,
PMBUS_READ_IOUT = 0x8C,
PMBUS_READ_TEMPERATURE_1 = 0x8D,
PMBUS_READ_TEMPERATURE_2 = 0x8E,
PMBUS_READ_TEMPERATURE_3 = 0x8F,
PMBUS_READ_FAN_SPEED_1 = 0x90,
PMBUS_READ_FAN_SPEED_2 = 0x91,
PMBUS_READ_FAN_SPEED_3 = 0x92,
PMBUS_READ_FAN_SPEED_4 = 0x93,
PMBUS_READ_DUTY_CYCLE = 0x94,
PMBUS_READ_FREQUENCY = 0x95,
PMBUS_READ_POUT = 0x96,
PMBUS_READ_PIN = 0x97,
PMBUS_REVISION = 0x98,
PMBUS_MFR_ID = 0x99,
PMBUS_MFR_MODEL = 0x9A,
PMBUS_MFR_REVISION = 0x9B,
PMBUS_MFR_LOCATION = 0x9C,
PMBUS_MFR_DATE = 0x9D,
PMBUS_MFR_SERIAL = 0x9E,
/*
* Virtual registers.
* Useful to support attributes which are not supported by standard PMBus
* registers but exist as manufacturer specific registers on individual chips.
* Must be mapped to real registers in device specific code.
*
* Semantics:
* Virtual registers are all word size.
* READ registers are read-only; writes are either ignored or return an error.
* RESET registers are read/write. Reading reset registers returns zero
* (used for detection), writing any value causes the associated history to be
* reset.
* Virtual registers have to be handled in device specific driver code. Chip
* driver code returns non-negative register values if a virtual register is
* supported, or a negative error code if not. The chip driver may return
* -ENODATA or any other error code in this case, though an error code other
* than -ENODATA is handled more efficiently and thus preferred. Either case,
* the calling PMBus core code will abort if the chip driver returns an error
* code when reading or writing virtual registers.
*/
PMBUS_VIRT_BASE = 0x100,
PMBUS_VIRT_READ_TEMP_AVG,
PMBUS_VIRT_READ_TEMP_MIN,
PMBUS_VIRT_READ_TEMP_MAX,
PMBUS_VIRT_RESET_TEMP_HISTORY,
PMBUS_VIRT_READ_VIN_AVG,
PMBUS_VIRT_READ_VIN_MIN,
PMBUS_VIRT_READ_VIN_MAX,
PMBUS_VIRT_RESET_VIN_HISTORY,
PMBUS_VIRT_READ_IIN_AVG,
PMBUS_VIRT_READ_IIN_MIN,
PMBUS_VIRT_READ_IIN_MAX,
PMBUS_VIRT_RESET_IIN_HISTORY,
PMBUS_VIRT_READ_PIN_AVG,
PMBUS_VIRT_READ_PIN_MIN,
PMBUS_VIRT_READ_PIN_MAX,
PMBUS_VIRT_RESET_PIN_HISTORY,
PMBUS_VIRT_READ_POUT_AVG,
PMBUS_VIRT_READ_POUT_MIN,
PMBUS_VIRT_READ_POUT_MAX,
PMBUS_VIRT_RESET_POUT_HISTORY,
PMBUS_VIRT_READ_VOUT_AVG,
PMBUS_VIRT_READ_VOUT_MIN,
PMBUS_VIRT_READ_VOUT_MAX,
PMBUS_VIRT_RESET_VOUT_HISTORY,
PMBUS_VIRT_READ_IOUT_AVG,
PMBUS_VIRT_READ_IOUT_MIN,
PMBUS_VIRT_READ_IOUT_MAX,
PMBUS_VIRT_RESET_IOUT_HISTORY,
PMBUS_VIRT_READ_TEMP2_AVG,
PMBUS_VIRT_READ_TEMP2_MIN,
PMBUS_VIRT_READ_TEMP2_MAX,
PMBUS_VIRT_RESET_TEMP2_HISTORY,
PMBUS_VIRT_READ_VMON,
PMBUS_VIRT_VMON_UV_WARN_LIMIT,
PMBUS_VIRT_VMON_OV_WARN_LIMIT,
PMBUS_VIRT_VMON_UV_FAULT_LIMIT,
PMBUS_VIRT_VMON_OV_FAULT_LIMIT,
PMBUS_VIRT_STATUS_VMON,
};
enum pmbus_sensor_classes {
PSC_VOLTAGE_IN = 0,
PSC_VOLTAGE_OUT,
PSC_CURRENT_IN,
PSC_CURRENT_OUT,
PSC_POWER,
PSC_TEMPERATURE,
PSC_FAN,
PSC_NUM_CLASSES /* Number of power sensor classes */
};
#define PMBUS_PAGES 32 /* Per PMBus specification */
/* Functionality bit mask */
#define PMBUS_HAVE_VIN BIT(0)
#define PMBUS_HAVE_VCAP BIT(1)
#define PMBUS_HAVE_VOUT BIT(2)
#define PMBUS_HAVE_IIN BIT(3)
#define PMBUS_HAVE_IOUT BIT(4)
#define PMBUS_HAVE_PIN BIT(5)
#define PMBUS_HAVE_POUT BIT(6)
#define PMBUS_HAVE_FAN12 BIT(7)
#define PMBUS_HAVE_FAN34 BIT(8)
#define PMBUS_HAVE_TEMP BIT(9)
#define PMBUS_HAVE_TEMP2 BIT(10)
#define PMBUS_HAVE_TEMP3 BIT(11)
#define PMBUS_HAVE_STATUS_VOUT BIT(12)
#define PMBUS_HAVE_STATUS_IOUT BIT(13)
#define PMBUS_HAVE_STATUS_INPUT BIT(14)
#define PMBUS_HAVE_STATUS_TEMP BIT(15)
#define PMBUS_HAVE_STATUS_FAN12 BIT(16)
#define PMBUS_HAVE_STATUS_FAN34 BIT(17)
#define PMBUS_HAVE_VMON BIT(18)
#define PMBUS_HAVE_STATUS_VMON BIT(19)
enum pmbus_data_format { linear = 0, direct, vid };
enum vrm_version { vr11 = 0, vr12, vr13 };
struct pmbus_driver_info {
int pages; /* Total number of pages */
enum pmbus_data_format format[PSC_NUM_CLASSES];
enum vrm_version vrm_version;
/*
* Support one set of coefficients for each sensor type
* Used for chips providing data in direct mode.
*/
int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */
int b[PSC_NUM_CLASSES]; /* offset */
int R[PSC_NUM_CLASSES]; /* exponent */
u32 func[PMBUS_PAGES]; /* Functionality, per page */
/*
* The following functions map manufacturing specific register values
* to PMBus standard register values. Specify only if mapping is
* necessary.
* Functions return the register value (read) or zero (write) if
* successful. A return value of -ENODATA indicates that there is no
* manufacturer specific register, but that a standard PMBus register
* may exist. Any other negative return value indicates that the
* register does not exist, and that no attempt should be made to read
* the standard register.
*/
int (*read_byte_data)(struct i2c_client *client, int page, int reg);
int (*read_word_data)(struct i2c_client *client, int page, int reg);
int (*write_word_data)(struct i2c_client *client, int page, int reg,
u16 word);
int (*write_byte)(struct i2c_client *client, int page, u8 value);
/*
* The identify function determines supported PMBus functionality.
* This function is only necessary if a chip driver supports multiple
* chips, and the chip functionality is not pre-determined.
*/
int (*identify)(struct i2c_client *client,
struct pmbus_driver_info *info);
/* Regulator functionality, if supported by this chip driver. */
int num_regulators;
const struct regulator_desc *reg_desc;
};
extern int pmbus_set_page(struct i2c_client *client, u8 page);
extern int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
extern bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
extern bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
extern int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
struct pmbus_driver_info *info);
extern int pmbus_do_remove(struct i2c_client *client);
/* Needed to access the mutex. Copied from pmbus_core.c */ /* Needed to access the mutex. Copied from pmbus_core.c */
#define PB_STATUS_BASE 0 #define PB_STATUS_BASE 0
#define PB_STATUS_VOUT_BASE (PB_STATUS_BASE + PMBUS_PAGES) #define PB_STATUS_VOUT_BASE (PB_STATUS_BASE + PMBUS_PAGES)
@ -327,6 +581,7 @@ static int qci_pmbus_identify(struct i2c_client *client,
break; break;
case 1: case 1:
info->format[PSC_VOLTAGE_OUT] = vid; info->format[PSC_VOLTAGE_OUT] = vid;
info->vrm_version = vr11;
break; break;
case 2: case 2:
info->format[PSC_VOLTAGE_OUT] = direct; info->format[PSC_VOLTAGE_OUT] = direct;
@ -411,7 +666,7 @@ static int qci_pmbus_probe(struct i2c_client *client,
{ {
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct pmbus_driver_info *info; struct pmbus_driver_info *info;
int ret, i; int ret;
dev_info(dev, "qci_pmbus_probe\n"); dev_info(dev, "qci_pmbus_probe\n");
@ -419,8 +674,7 @@ static int qci_pmbus_probe(struct i2c_client *client,
I2C_FUNC_SMBUS_READ_WORD_DATA)) I2C_FUNC_SMBUS_READ_WORD_DATA))
return -ENODEV; return -ENODEV;
info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), info = devm_kzalloc(dev, sizeof(struct pmbus_driver_info), GFP_KERNEL);
GFP_KERNEL);
if (!info) if (!info)
return -ENOMEM; return -ENOMEM;

View File

@ -40,18 +40,16 @@ args = []
FORCE = 0 FORCE = 0
i2c_prefix = '/sys/bus/i2c/devices/' i2c_prefix = '/sys/bus/i2c/devices/'
if DEBUG == True: if DEBUG == True:
print sys.argv[0] print sys.argv[0]
print 'ARGV :', sys.argv[1:] print 'ARGV :', sys.argv[1:]
def main(): def main():
global DEBUG global DEBUG
global args global args
global FORCE global FORCE
if len(sys.argv)<2: if len(sys.argv) < 2:
show_help() show_help()
options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help', options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help',
@ -68,11 +66,12 @@ def main():
show_help() show_help()
elif opt in ('-d', '--debug'): elif opt in ('-d', '--debug'):
DEBUG = True DEBUG = True
logging.basicConfig(level=logging.INFO) logging.basicConfig(level = logging.INFO)
elif opt in ('-f', '--force'): elif opt in ('-f', '--force'):
FORCE = 1 FORCE = 1
else: else:
logging.info('no option') logging.info('no option')
for arg in args: for arg in args:
if arg == 'install': if arg == 'install':
install() install()
@ -81,7 +80,6 @@ def main():
else: else:
show_help() show_help()
return 0 return 0
def show_help(): def show_help():
@ -90,25 +88,48 @@ def show_help():
def show_log(txt): def show_log(txt):
if DEBUG == True: if DEBUG == True:
print "[IX1B-32X]"+txt print "[IX1B-32X]" + txt
return return
def exec_cmd(cmd, show): def exec_cmd(cmd, show):
logging.info('Run :'+cmd) logging.info('Run :' + cmd)
status, output = commands.getstatusoutput(cmd) status, output = commands.getstatusoutput(cmd)
show_log (cmd +"with result:" + str(status)) show_log (cmd + "with result:" + str(status))
show_log (" output:"+output) show_log (" output:" + output)
if status: if status:
logging.info('Failed :'+cmd) logging.info('Failed :' + cmd)
if show: if show:
print('Failed :'+cmd) print('Failed :' + cmd)
return status, output return status, output
instantiate =[ instantiate = [
#turn on module power #turn on module power
'echo 53 > /sys/class/gpio/export', 'echo 53 > /sys/class/gpio/export',
'echo out > /sys/class/gpio/gpio53/direction', 'echo out > /sys/class/gpio/gpio53/direction',
'echo 1 >/sys/class/gpio/gpio53/value', 'echo 1 > /sys/class/gpio/gpio53/value',
#PSU1 present
'echo 16 > /sys/class/gpio/export',
'echo in > /sys/class/gpio/gpio16/direction',
#PSU1 power good signal
'echo 17 > /sys/class/gpio/export',
'echo in > /sys/class/gpio/gpio17/direction',
#PSU2 present
'echo 19 > /sys/class/gpio/export',
'echo in > /sys/class/gpio/gpio19/direction',
#PSU2 power good signal
'echo 20 > /sys/class/gpio/export',
'echo in > /sys/class/gpio/gpio20/direction',
#FAN 1-4 present
'echo 36 > /sys/class/gpio/export',
'echo in > /sys/class/gpio/gpio36/direction',
'echo 37 > /sys/class/gpio/export',
'echo in > /sys/class/gpio/gpio37/direction',
'echo 38 > /sys/class/gpio/export',
'echo in > /sys/class/gpio/gpio38/direction',
'echo 39 > /sys/class/gpio/export',
'echo in > /sys/class/gpio/gpio39/direction',
#turn on 100G led by default #turn on 100G led by default
'i2cset -y 0x13 0x38 0x00 0xff', 'i2cset -y 0x13 0x38 0x00 0xff',
'i2cset -y 0x13 0x38 0x01 0xff', 'i2cset -y 0x13 0x38 0x01 0xff',
@ -124,76 +145,88 @@ drivers =[
'gpio-pca953x', 'gpio-pca953x',
'qci_pmbus', 'qci_pmbus',
'leds-gpio', 'leds-gpio',
'optoe',
'qci_cpld_qsfp28', 'qci_cpld_qsfp28',
'qci_platform_ix1b' 'qci_platform_ix1b'
] ]
def system_install(): def system_install():
global FORCE global FORCE
time.sleep(3)
#remove default drivers to avoid modprobe order conflicts #remove default drivers to avoid modprobe order conflicts
status, output = exec_cmd("rmmod i2c_ismt ", 1) status, output = exec_cmd("rmmod i2c_ismt ", 1)
status, output = exec_cmd("rmmod i2c-i801 ", 1) status, output = exec_cmd("rmmod i2c-i801 ", 1)
#setup driver dependency #setup driver dependency
status, output = exec_cmd("depmod -a ", 1) status, output = exec_cmd("depmod -a ", 1)
#install drivers #install drivers
for i in range(0,len(drivers)): for i in range(0, len(drivers)):
status, output = exec_cmd("modprobe "+drivers[i], 1) status, output = exec_cmd("modprobe " + drivers[i], 1)
if status: if status:
print output print output
if FORCE == 0: if FORCE == 0:
return status return status
#instantiate devices #instantiate devices
for i in range(0,len(instantiate)): for i in range(0, len(instantiate)):
time.sleep(1)
status, output = exec_cmd(instantiate[i], 1) status, output = exec_cmd(instantiate[i], 1)
if status: if status:
print output print output
if FORCE == 0: if FORCE == 0:
return status return status
#for i in range(22,30): #Mount Quanta hardware monitor driver
# status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-4/i2c-"+str(i)+"/new_device", 1) status, output = exec_cmd("modprobe qci_hwmon_ix1b", 1)
# if status:
# print output #QSFP for 1~32 port
# if FORCE == 0: for port_number in range(1, 33):
# return status bus_number = port_number + 31
os.system("echo %d >/sys/bus/i2c/devices/%d-0050/port_name" % (port_number, bus_number))
#Set system LED to green
status, output = exec_cmd("echo 1 > /sys/class/leds/sysled_green/brightness", 1)
return return
def system_ready(): def system_ready():
if not device_found(): if not device_found():
return False return False
return True return True
def install(): def install():
if not device_found(): if not device_found():
print "No device, installing...." print "No device, installing...."
status = system_install() status = system_install()
if status: if status:
if FORCE == 0: if FORCE == 0:
return status return status
else: else:
print " ix1b driver already installed...." print " ix1b driver already installed...."
return return
def uninstall(): def uninstall():
global FORCE global FORCE
#uninstall drivers #uninstall drivers
for i in range(len(drivers)-1,-1,-1): for i in range(len(drivers) - 1, -1, -1):
status, output = exec_cmd("rmmod "+drivers[i], 1) status, output = exec_cmd("rmmod " + drivers[i], 1)
if status: if status:
print output print output
if FORCE == 0: if FORCE == 0:
return status return status
return return
def device_found(): def device_found():
ret1, log = exec_cmd("ls "+i2c_prefix+"i2c-0", 0) ret1, log = exec_cmd("ls " + i2c_prefix + "i2c-0", 0)
return ret1 return ret1
if __name__ == "__main__": if __name__ == "__main__":