[devices]:Add attributes for cpupld and swpld. (#1516)

Signed-off-by: Stanley Chi <stanley.chi@deltaww.com>
This commit is contained in:
StanleyCi 2018-03-24 01:45:01 +08:00 committed by lguohan
parent 94c90cd5e5
commit baa9d45343
6 changed files with 2094 additions and 799 deletions

View File

@ -1,4 +1,6 @@
obj-m += delta_ag9064_platform.o
obj-m += delta_ag9064_cpld.o
obj-m += delta_ag9064_swpld.o
obj-m += i2c-mei.o
i2c-mei-objs := i2c-mei_io.o i2c-mei_main.o i2c-mei_rw.o

View File

@ -0,0 +1,567 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sysfs.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/completion.h>
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h>
#include <linux/hwmon-sysfs.h>
#include <linux/hwmon.h>
#define IPMI_MAX_INTF (4)
#define DELTA_NETFN 0x38
#define BMC_BUS_5 0x04
#define CMD_SETDATA 0x03
#define CMD_GETDATA 0x02
#define CPUPLD_ADDR 0x31
#define SWPLD1_ADDR 0x35
#define SWPLD2_ADDR 0x34
#define SWPLD3_ADDR 0x33
#define SWPLD4_ADDR 0x32
#define QSFP_PORT_MUX_REG 0x13
#define DEFAULT_NUM 1
#define BUS9_DEV_NUM 64
#define BUS9_BASE_NUM 20
extern int dni_bmc_cmd(char set_cmd, char *cmd_data, int cmd_data_len);
extern int dni_create_user(void);
extern unsigned char dni_log2 (unsigned char num);
extern void device_release(struct device *dev);
extern void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data);
extern void dummy_smi_free(struct ipmi_smi_msg *msg);
extern void dummy_recv_free(struct ipmi_recv_msg *msg);
static ipmi_user_t ipmi_mh_user = NULL;
static struct ipmi_user_hndl ipmi_hndlrs = { .ipmi_recv_hndl = msg_handler,};
static atomic_t dummy_count = ATOMIC_INIT(0);
static struct ipmi_smi_msg halt_smi_msg = {
.done = dummy_smi_free
};
static struct ipmi_recv_msg halt_recv_msg = {
.done = dummy_recv_free
};
enum{
BUS0 = 0,
BUS1,
BUS2,
BUS3,
BUS4,
BUS5,
BUS6,
BUS7,
BUS8,
BUS9,
BUS10,
BUS11,
BUS12,
BUS13,
BUS14,
};
static struct cpld_attribute_data {
uint8_t bus;
uint8_t addr;
uint8_t reg;
uint8_t mask;
char note[200];
};
enum cpld_type {
system_cpld,
swpld1,
swpld2,
swpld3,
swpld4,
};
struct cpld_platform_data {
int reg_addr;
struct i2c_client *client;
};
static struct cpld_platform_data ag9064_cpld_platform_data[] = {
[system_cpld] = {
.reg_addr = CPUPLD_ADDR,
},
};
static struct cpld_platform_data ag9064_swpld1_platform_data[] = {
[swpld1] = {
.reg_addr = SWPLD1_ADDR,
},
};
static struct cpld_platform_data ag9064_swpld2_platform_data[] = {
[swpld2] = {
.reg_addr = SWPLD2_ADDR,
},
};
static struct cpld_platform_data ag9064_swpld3_platform_data[] = {
[swpld3] = {
.reg_addr = SWPLD3_ADDR,
},
};
static struct cpld_platform_data ag9064_swpld4_platform_data[] = {
[swpld4] = {
.reg_addr = SWPLD4_ADDR,
},
};
enum cpld_attributes {
CPLD_REG_ADDR,
CPLD_REG_VALUE,
SWPLD1_REG_ADDR,
SWPLD1_REG_VALUE,
SWPLD2_REG_ADDR,
SWPLD2_REG_VALUE,
SWPLD3_REG_ADDR,
SWPLD3_REG_VALUE,
SWPLD4_REG_ADDR,
SWPLD4_REG_VALUE,
//CPLD
CPLD_VER,
CPU_BOARD_VER,
CPU_ID,
MB_ID,
MB_VER,
CPU0_PWR_OK,
PSU_OVER_TEMP,
PWR_RAIL_OVER_TEMP,
CPU_DISOMIC_OVER_TEMP,
DDR_OVER_TEMP,
CPLD_PWR_ON_RST,
CPLD_HARD_RST,
CPLD_RST,
MB_PWR,
MB_RST,
PSU_FAN_INT,
OP_MODULE_INT,
//SWPLD1
SWPLD1_MAJOR_VER,
SWPLD1_MINOR_VER,
SWPLD1_SCRTCH_REG,
PSU1_PWR_OK,
PSU1_INT,
PSU2_PWR_OK,
PSU2_INT,
SYNCE_INT,
SYNCE_RST,
SYNCE_EEPROM_WP,
PSU1_GREEN_LED,
PSU1_RED_LED,
PSU2_GREEN_LED,
PSU2_RED_LED,
PSU_LED_MODE,
//SWPLD2
SWPLD2_MAJOR_VER,
SWPLD2_MINOR_VER,
SWPLD2_SCRTCH_REG,
FAN_LED,
SYS_LED,
FAN_MOD1_LED,
FAN_MOD2_LED,
FAN_MOD3_LED,
FAN_MOD4_LED,
//SWPLD3
SWPLD3_MAJOR_VER,
SWPLD3_MINOR_VER,
SWPLD3_SCRTCH_REG,
SB_VER,
PLATFORM_TYPE,
//SWPLD4
SWPLD4_MAJOR_VER,
SWPLD4_MINOR_VER,
SWPLD4_SCRTCH_REG,
BMC_RST,
CPLD_LPC_RST,
CPLD_SW_RST,
MB_CPLD_RST,
BCM56970_RST,
CPLD_UPGRADE_RST,
MB_RST_CPLD,
CPU_RST_MB_OOB,
GPIO_PHY_RST,
PSU_FAN_EVENT,
CPU_THERMAL_INT,
FAN_INT,
CPLD_SPI_WP,
RJ45_CONSOLE_SEL,
SYSTEM_INT,
CPLD_MB_RST_DONE,
MB_PWR_OK,
FAN_EEPROM_WP,
};
static struct cpld_attribute_data attribute_data[] = {
[CPLD_REG_ADDR] = {
},
[CPLD_REG_VALUE] = {
},
[SWPLD1_REG_ADDR] = {
},
[SWPLD1_REG_VALUE] = {
},
[SWPLD2_REG_ADDR] = {
},
[SWPLD2_REG_VALUE] = {
},
[SWPLD3_REG_ADDR] = {
},
[SWPLD3_REG_VALUE] = {
},
[SWPLD4_REG_ADDR] = {
},
[SWPLD4_REG_VALUE] = {
},
//CPLD
[CPLD_VER] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x01, .mask = 0xFF,
.note = "CPLD Version, controlled by CPLD editor"
},
[CPU_BOARD_VER] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x02, .mask = 0xF0,
.note = "“0x0”: proto A1\n“0x1”: proto A2\n“0x2”: PR (Production)"
},
[CPU_ID] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x02, .mask = 0x0F,
.note = "“0x0”: C2558 ECC\n“0x1”: Rangeley ECC\n“0x2”: BROADWELL-DE ECC"
},
[MB_ID] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x03, .mask = 0xFF,
.note = "“0x00”: proto A1\n“0x01”: proto A2\n“0x02”: PR (Production)"
},
[MB_VER] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x04, .mask = 0x0F,
.note = "“0x0”: proto-A\n“0x1”: proto-B"
},
[CPU0_PWR_OK] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x08, .mask = 1 << 3,
.note = "“1” =Power rail is good\n“0” = Power rail is failed"
},
[PSU_OVER_TEMP] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x0b, .mask = 1 << 4,
.note = "“1” = Not over temperature\n“0” = Over temperature"
},
[PWR_RAIL_OVER_TEMP] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x0b, .mask = 1 << 3,
.note = "“1” = Not over temperature\n“0” = Over temperature"
},
[CPU_DISOMIC_OVER_TEMP] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x0b, .mask = 1 << 1,
.note = "“1” = Not over temperature\n“0” = Over temperature"
},
[DDR_OVER_TEMP] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x0b, .mask = 1 << 0,
.note = "“1” = Not over temperature\n“0” = Over temperature"
},
[CPLD_PWR_ON_RST] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x11, .mask = 1 << 4,
.note = "“0” = Reset\n“1” = Normal operation"
},
[CPLD_HARD_RST] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x11, .mask = 1 << 2,
.note = "“0” = Reset\n“1” = Normal operation"
},
[CPLD_RST] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x11, .mask = 1 << 0,
.note = "“0” = Reset\n“1” = Normal operation"
},
[MB_PWR] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x12, .mask = 1 << 2,
.note = "“0” = Power rail is failed\n“1” =Power rail is good"
},
[MB_RST] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x12, .mask = 1 << 0,
.note = "“0” = Reset\n“1” = Normal operation"
},
[PSU_FAN_INT] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x15, .mask = 1 << 1,
.note = "“0” = Interrupt occurs\n“1” = Interrupt doesn't occur"
},
[OP_MODULE_INT] = {
.bus = BUS0, .addr = CPUPLD_ADDR,
.reg = 0x15, .mask = 1 << 0,
.note = "“0” = Interrupt occurs\n“1” = Interrupt doesn't occur"
},
//SWPLD1
[SWPLD1_MAJOR_VER] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x00, .mask = 0xF0,
.note = "CPLD Major Version, controlled by CPLD editor."
},
[SWPLD1_MINOR_VER] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x00, .mask = 0x0F,
.note = "CPLD Minor Version, controlled by CPLD editor."
},
[SWPLD1_SCRTCH_REG] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x01, .mask = 0xFF,
.note = "CPLD read/write test register, to provide a way to test CPLD access."
},
[PSU1_PWR_OK] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x02, .mask = 1 << 6,
.note = "0 = Power rail is good\n1 = Power rail is failed"
},
[PSU1_INT] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x02, .mask = 1 << 5,
.note = "0 = Interrupt doesnt occur\n1 = Interrupt occurs"
},
[PSU2_PWR_OK] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x02, .mask = 1 << 2,
.note = "0 = Power rail is good\n1 = Power rail is failed"
},
[PSU2_INT] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x02, .mask = 1 << 1,
.note = "0 = Interrupt doesnt occur\n1 = Interrupt occurs"
},
[SYNCE_INT] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x12, .mask = 1 << 7,
.note = "0 = Interrupt occurs\n1 = Interrupt doesnt occur"
},
[SYNCE_RST] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x12, .mask = 1 << 6,
.note = "“0” = Reset\n“1” = Normal operation"
},
[SYNCE_EEPROM_WP] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x12, .mask = 1 << 5,
.note = "“1” = enables the lock-down mechanism.\n“0” = overrides the lock-down function enabling blocks to be erased or programmed using software commands."
},
[PSU1_GREEN_LED] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x13, .mask = 1 << 7,
.note = "“0”: Solid Green Power Supply 1 is supplied to the switch & operating normally\n“1”: OFF"
},
[PSU1_RED_LED] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x13, .mask = 1 << 6,
.note = "“0”: Solid Red Power Supply 1 is supplied to the switch & operating normally\n“1”: OFF"
},
[PSU2_GREEN_LED] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x13, .mask = 1 << 5,
.note = "“0”: Solid Green Power Supply 2 is supplied to the switch & operating normally\n“1”: OFF"
},
[PSU2_RED_LED] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x13, .mask = 1 << 4,
.note = "“0”: Solid Red Power Supply 1=2 is supplied to the switch & operating normally\n“1”: OFF"
},
[PSU_LED_MODE] = {
.bus = BUS0, .addr = SWPLD1_ADDR,
.reg = 0x13, .mask = 1 << 0,
.note = "“0”: PSU LED can be changed manually\n“1”: PSU LED cant be changed manually"
},
//SWPLD2
[SWPLD2_MAJOR_VER] = {
.bus = BUS0, .addr = SWPLD2_ADDR,
.reg = 0x00, .mask =0xF0 ,
.note = "CPLD Major Version, controlled by CPLD editor."
},
[SWPLD2_MINOR_VER] = {
.bus = BUS0, .addr = SWPLD2_ADDR,
.reg = 0x00, .mask = 0x0F,
.note = "CPLD Minor Version, controlled by CPLD editor."
},
[SWPLD2_SCRTCH_REG] = {
.bus = BUS0, .addr = SWPLD2_ADDR,
.reg = 0x01, .mask = 0xFF,
.note = "CPLD read/write test register, to provide a way to test CPLD access."
},
[FAN_LED] = {
.bus = BUS0, .addr = SWPLD2_ADDR,
.reg = 0x02, .mask = 0xC0,
.note = "“00/”11”: OFF\n“01”: Solid Green FANs are operating normally\n“10”: Solid Amber FANs are Error"
},
[SYS_LED] = {
.bus = BUS0, .addr = SWPLD2_ADDR,
.reg = 0x02, .mask = 0x30,
.note = "00: Off\n01: Solid Green Normal operation\n10: Blinking Green Booting Progress\n11: Solid Red System Fail"
},
[FAN_MOD1_LED] = {
.bus = BUS0, .addr = SWPLD2_ADDR,
.reg = 0x1b, .mask = 1 << 7,
.note = "0 = Amber\n1 = Green"
},
[FAN_MOD2_LED] = {
.bus = BUS0, .addr = SWPLD2_ADDR,
.reg = 0x1b, .mask = 1 << 6,
.note = "0 = Amber\n1 = Green"
},
[FAN_MOD3_LED] = {
.bus = BUS0, .addr = SWPLD2_ADDR,
.reg = 0x1b, .mask = 1 << 5,
.note = "0 = Amber\n1 = Green"
},
[FAN_MOD4_LED] = {
.bus = BUS0, .addr = SWPLD2_ADDR,
.reg = 0x1b, .mask = 1 << 4,
.note = "0 = Amber\n1 = Green"
},
//SWPLD3
[SWPLD3_MAJOR_VER] = {
.bus = BUS0, .addr = SWPLD3_ADDR,
.reg = 0x00, .mask = 0xF0,
.note = "CPLD Major Version, controlled by CPLD editor."
},
[SWPLD3_MINOR_VER] = {
.bus = BUS0, .addr = SWPLD3_ADDR,
.reg = 0x00, .mask = 0x0F,
.note = "CPLD Minor Version, controlled by CPLD editor."
},
[SWPLD3_SCRTCH_REG] = {
.bus = BUS0, .addr = SWPLD3_ADDR,
.reg = 0x01, .mask = 0xFF,
.note = "CPLD read/write test register, to provide a way to test CPLD access."
},
[SB_VER] = {
.bus = BUS0, .addr = SWPLD3_ADDR,
.reg = 0x02, .mask = 0xF0,
.note = "“0x0”: proto-A\n“0x1”: proto-B"
},
[PLATFORM_TYPE] = {
.bus = BUS0, .addr = SWPLD3_ADDR,
.reg = 0x02, .mask = 0x0F,
.note = "“0x0”: 64X100G_2U\n“0x1”~”0xF” Reserved"
},
//SWPLD4
[SWPLD4_MAJOR_VER] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x00, .mask = 0xF0,
.note = "CPLD Major Version, controlled by CPLD editor."
},
[SWPLD4_MINOR_VER] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x00, .mask = 0x0F,
.note = "CPLD Minor Version, controlled by CPLD editor."
},
[SWPLD4_SCRTCH_REG] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x01, .mask = 0xFF,
.note = "CPLD read/write test register, to provide a way to test CPLD access."
},
[BMC_RST] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x02, .mask = 1 << 6,
.note = "“0” = Reset\n“1” = Normal operation"
},
[CPLD_LPC_RST] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x02, .mask = 1 << 5,
.note = "“0” = Reset\n“1” = Normal operation"
},
[CPLD_SW_RST] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x02, .mask = 1 << 3,
.note = "“0” = Reset\n“1” = Normal operation"
},
[MB_CPLD_RST] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x02, .mask = 1 << 2,
.note = "“0” = Reset\n“1” = Normal operation"
},
[BCM56970_RST] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x02, .mask = 1 << 1,
.note = "“0” = Reset\n“1” = Normal operation"
},
[CPLD_UPGRADE_RST] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x03, .mask = 1 << 7,
.note = "“0” = Reset\n“1” = Normal operation"
},
[MB_RST_CPLD] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x03, .mask = 1 << 6,
.note = "“0” = Reset\n“1” = Normal operation"
},
[CPU_RST_MB_OOB] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x03, .mask = 1 << 5,
.note = "“0” = Reset\n“1” = Normal operation"
},
[GPIO_PHY_RST] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x03, .mask = 1 << 4,
.note = "“0” = Reset\n“1” = Normal operation"
},
[PSU_FAN_EVENT] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x04, .mask = 1 << 4,
.note = "0 = Interrupt occurs\n1 = Interrupt doesnt occur"
},
[CPU_THERMAL_INT] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x04, .mask = 1 << 1,
.note = "0 = Interrupt occurs\n1 = Interrupt doesnt occur"
},
[FAN_INT] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x04, .mask = 1 << 0,
.note = "0 = Interrupt occurs\n1 = Interrupt doesnt occur"
},
[CPLD_SPI_WP] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x06, .mask = 1 << 3,
.note = "“0” = SPI write operation is disabled\n“1” = SPI write operation is enabled"
},
[RJ45_CONSOLE_SEL] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x06, .mask = 1 << 2,
.note = "“0” = Use BCM UART\n“1” = Use CPU UART"
},
[SYSTEM_INT] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x07, .mask = 1 << 2,
.note = "“0” = Interrupt is asserted\n“1” = Interrupt is deasserted"
},
[CPLD_MB_RST_DONE] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x07, .mask = 1 << 1,
.note = "“0” = Is done\n“1” = Is not done"
},
[MB_PWR_OK] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x07, .mask = 1 << 0,
.note = "0 = Power is failed\n1 = Power is good"
},
[FAN_EEPROM_WP] = {
.bus = BUS0, .addr = SWPLD4_ADDR,
.reg = 0x15, .mask = 1 << 2,
.note = "“1” = enables the lock-down mechanism.\n“0” = overrides the lock-down function enabling blocks to be erased or programmed using software commands."
},
};

View File

@ -0,0 +1,860 @@
#include "delta_ag9064_common.h"
#define QSFP_PRESENCE_1 0x03
#define QSFP_PRESENCE_2 0x03
#define QSFP_PRESENCE_3 0x24
#define QSFP_PRESENCE_4 0x24
#define QSFP_PRESENCE_5 0x04
#define QSFP_PRESENCE_6 0x04
#define QSFP_PRESENCE_7 0x25
#define QSFP_PRESENCE_8 0x25
#define QSFP_LP_MODE_1 0x0c
#define QSFP_LP_MODE_2 0x0c
#define QSFP_LP_MODE_3 0x2a
#define QSFP_LP_MODE_4 0x2a
#define QSFP_LP_MODE_5 0x0d
#define QSFP_LP_MODE_6 0x0d
#define QSFP_LP_MODE_7 0x2b
#define QSFP_LP_MODE_8 0x2b
#define QSFP_RESET_1 0x06
#define QSFP_RESET_2 0x06
#define QSFP_RESET_3 0x26
#define QSFP_RESET_4 0x26
#define QSFP_RESET_5 0x07
#define QSFP_RESET_6 0x07
#define QSFP_RESET_7 0x27
#define QSFP_RESET_8 0x27
#define QSFP_RESPONSE_1 0x09
#define QSFP_RESPONSE_2 0x09
#define QSFP_RESPONSE_3 0x28
#define QSFP_RESPONSE_4 0x28
#define QSFP_RESPONSE_5 0x0a
#define QSFP_RESPONSE_6 0x0a
#define QSFP_RESPONSE_7 0x29
#define QSFP_RESPONSE_8 0x29
#define QSFP_INTERRUPT_1 0x0f
#define QSFP_INTERRUPT_2 0x0f
#define QSFP_INTERRUPT_3 0x2c
#define QSFP_INTERRUPT_4 0x2c
#define QSFP_INTERRUPT_5 0x10
#define QSFP_INTERRUPT_6 0x10
#define QSFP_INTERRUPT_7 0x2d
#define QSFP_INTERRUPT_8 0x2d
unsigned char cpupld_reg_addr;
/*---------------- CPLD - start ------------- */
/* CPLD -- device */
static struct platform_device ag9064_cpld = {
.name = "delta-ag9064-cpld",
.id = 0,
.dev = {
.platform_data = ag9064_cpld_platform_data,
.release = device_release
},
};
static ssize_t get_present(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
int ret;
u64 data = 0;
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_GETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_PRESENCE_1;
cmd_data[3] = 1;
cmd_data_len = sizeof(cmd_data);
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data = (u64)(ret & 0xff);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_PRESENCE_2;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 8;
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_PRESENCE_3;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 16;
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_PRESENCE_4;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 24;
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_PRESENCE_5;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 32;
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_PRESENCE_6;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 40;
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_PRESENCE_7;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 48;
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_PRESENCE_8;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 56;
return sprintf(buf, "0x%016llx\n", data);
}
static ssize_t get_lpmode(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
int ret;
u64 data = 0;
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_GETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_LP_MODE_1;
cmd_data[3] = 1;
cmd_data_len = sizeof(cmd_data);
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data = (u64)(ret & 0xff);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_LP_MODE_2;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 8;
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_LP_MODE_3;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 16;
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_LP_MODE_4;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 24;
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_LP_MODE_5;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 32;
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_LP_MODE_6;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 40;
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_LP_MODE_7;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 48;
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_LP_MODE_8;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 56;
return sprintf(buf, "0x%016llx\n", data);
}
static ssize_t get_reset(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
int ret;
u64 data = 0;
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_GETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESET_1;
cmd_data[3] = 1;
cmd_data_len = sizeof(cmd_data);
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data = (u64)(ret & 0xff);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESET_2;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 8;
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESET_3;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 16;
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESET_4;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 24;
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESET_5;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 32;
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESET_6;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 40;
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESET_7;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 48;
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESET_8;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 56;
return sprintf(buf, "0x%016llx\n", data);
}
static ssize_t get_response(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
int ret;
u64 data = 0;
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_GETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESPONSE_1;
cmd_data[3] = 1;
cmd_data_len = sizeof(cmd_data);
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data = (u64)(ret & 0xff);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESPONSE_2;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 8;
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESPONSE_3;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 16;
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESPONSE_4;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 24;
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESPONSE_5;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 32;
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESPONSE_6;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 40;
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESPONSE_7;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 48;
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESPONSE_8;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 56;
return sprintf(buf, "0x%016llx\n", data);
}
static ssize_t get_interrupt(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
int ret;
u64 data = 0;
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_GETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_INTERRUPT_1;
cmd_data[3] = 1;
cmd_data_len = sizeof(cmd_data);
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data = (u64)(ret & 0xff);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_INTERRUPT_2;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 8;
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_INTERRUPT_3;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 16;
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_INTERRUPT_4;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 24;
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_INTERRUPT_5;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 32;
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_INTERRUPT_6;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 40;
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_INTERRUPT_7;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 48;
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_INTERRUPT_8;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 56;
return sprintf(buf, "0x%016llx\n", data);
}
static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count)
{
unsigned long long set_data;
int err;
err = kstrtoull(buf, 16, &set_data);
if (err){
return err;
}
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_SETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_LP_MODE_1;
cmd_data[3] = (set_data & 0xff);
cmd_data_len = sizeof(cmd_data);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_LP_MODE_2;
cmd_data[3] = ((set_data >> 8 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_LP_MODE_3;
cmd_data[3] = ((set_data >> 16 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_LP_MODE_4;
cmd_data[3] = ((set_data >> 24 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_LP_MODE_5;
cmd_data[3] = ((set_data >> 32 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_LP_MODE_6;
cmd_data[3] = ((set_data >> 40 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_LP_MODE_7;
cmd_data[3] = ((set_data >> 48 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_LP_MODE_8;
cmd_data[3] = ((set_data >> 56 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
return count;
}
static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count)
{
unsigned long long set_data;
int err;
err = kstrtoull(buf, 16, &set_data);
if (err){
return err;
}
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_SETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESET_1;
cmd_data[3] = (set_data & 0xff);
cmd_data_len = sizeof(cmd_data);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESET_2;
cmd_data[3] = ((set_data >> 8 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESET_3;
cmd_data[3] = ((set_data >> 16 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESET_4;
cmd_data[3] = ((set_data >> 24 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESET_5;
cmd_data[3] = ((set_data >> 32 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESET_6;
cmd_data[3] = ((set_data >> 40 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESET_7;
cmd_data[3] = ((set_data >> 48 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESET_8;
cmd_data[3] = ((set_data >> 56 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
return count;
}
static ssize_t set_response(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count)
{
unsigned long long set_data;
int err;
err = kstrtoull(buf, 16, &set_data);
if (err){
return err;
}
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_SETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESPONSE_1;
cmd_data[3] = (set_data & 0xff);
cmd_data_len = sizeof(cmd_data);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESPONSE_2;
cmd_data[3] = ((set_data >> 8 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESPONSE_3;
cmd_data[3] = ((set_data >> 16 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESPONSE_4;
cmd_data[3] = ((set_data >> 24 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESPONSE_5;
cmd_data[3] = ((set_data >> 32 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESPONSE_6;
cmd_data[3] = ((set_data >> 40 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESPONSE_7;
cmd_data[3] = ((set_data >> 48 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESPONSE_8;
cmd_data[3] = ((set_data >> 56 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
return count;
}
static ssize_t get_cpld_reg(struct device *dev, struct device_attribute *dev_attr, char *buf)
{
int ret;
int mask;
int value;
char note[200];
unsigned char reg;
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cpld_platform_data *pdata = dev->platform_data;
switch (attr->index) {
case CPLD_REG_ADDR:
return sprintf(buf, "0x%02x\n", cpupld_reg_addr);
case CPLD_REG_VALUE:
ret = i2c_smbus_read_byte_data(pdata[system_cpld].client, cpupld_reg_addr);
return sprintf(buf, "0x%02x\n", ret);
case CPLD_VER ... OP_MODULE_INT:
reg = attribute_data[attr->index].reg;
mask = attribute_data[attr->index].mask;
value = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg);
sprintf(note, "\n%s\n",attribute_data[attr->index].note);
value = (value & mask);
break;
default:
return sprintf(buf, "%d not found", attr->index);
}
switch (mask) {
case 0xFF:
return sprintf(buf, "0x%02x%s", value, note);
case 0x0F:
return sprintf(buf, "0x%01x%s", value, note);
case 0xF0:
value = value >> 4;
return sprintf(buf, "0x%01x%s", value, note);
default :
value = value >> dni_log2(mask);
return sprintf(buf, "%d%s", value, note);
}
}
static ssize_t set_cpld_reg(struct device *dev, struct device_attribute *dev_attr,
const char *buf, size_t count)
{
int err;
int value;
int set_data;
unsigned char reg;
unsigned char mask;
unsigned char mask_out;
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
struct cpld_platform_data *pdata = dev->platform_data;
err = kstrtoul(buf, 0, &set_data);
if (err){
return err;
}
if (set_data > 0xff){
printk(KERN_ALERT "address out of range (0x00-0xFF)\n");
return count;
}
switch (attr->index) {
case CPLD_REG_ADDR:
cpupld_reg_addr = set_data;
return count;
case CPLD_REG_VALUE:
i2c_smbus_write_byte_data(pdata[system_cpld].client, cpupld_reg_addr, set_data);
return count;
case CPLD_VER ... OP_MODULE_INT:
reg = attribute_data[attr->index].reg;
mask = attribute_data[attr->index].mask;
value = i2c_smbus_read_byte_data(pdata[system_cpld].client, reg);
mask_out = value & ~(mask);
break;
default:
return sprintf(buf, "%d not found", attr->index);
}
switch (mask) {
case 0xFF:
set_data = mask_out | (set_data & mask);
break;
case 0x0F:
set_data = mask_out | (set_data & mask);
break;
case 0xF0:
set_data = set_data << 4;
set_data = mask_out | (set_data & mask);
break;
default :
set_data = mask_out | (set_data << dni_log2(mask) );
}
i2c_smbus_write_byte_data(pdata[system_cpld].client, reg, set_data);
return count;
}
static DEVICE_ATTR(qsfp_present, S_IRUGO, get_present, NULL);
static DEVICE_ATTR(qsfp_lpmode, S_IWUSR | S_IRUGO, get_lpmode, set_lpmode);
static DEVICE_ATTR(qsfp_reset, S_IWUSR | S_IRUGO, get_reset, set_reset);
static DEVICE_ATTR(qsfp_modsel, S_IWUSR | S_IRUGO, get_response, set_response);
static DEVICE_ATTR(qsfp_interrupt, S_IRUGO, get_interrupt, NULL);
static SENSOR_DEVICE_ATTR(cpld_reg_addr, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPLD_REG_ADDR);
static SENSOR_DEVICE_ATTR(cpld_reg_value, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPLD_REG_VALUE);
static SENSOR_DEVICE_ATTR(cpld_ver, S_IRUGO, get_cpld_reg, NULL, CPLD_VER);
static SENSOR_DEVICE_ATTR(cpu_board_ver, S_IRUGO, get_cpld_reg, NULL, CPU_BOARD_VER);
static SENSOR_DEVICE_ATTR(cpu_id, S_IRUGO, get_cpld_reg, NULL, CPU_ID);
static SENSOR_DEVICE_ATTR(mb_id, S_IRUGO, get_cpld_reg, NULL, MB_ID);
static SENSOR_DEVICE_ATTR(mb_ver, S_IRUGO, get_cpld_reg, NULL, MB_VER);
static SENSOR_DEVICE_ATTR(cpu0_pwr_ok, S_IRUGO, get_cpld_reg, NULL, CPU0_PWR_OK);
static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, get_cpld_reg, NULL, PSU_OVER_TEMP);
static SENSOR_DEVICE_ATTR(pwr_rail_over_temp, S_IRUGO, get_cpld_reg, NULL, PWR_RAIL_OVER_TEMP);
static SENSOR_DEVICE_ATTR(cpu_disomic_over_temp, S_IRUGO, get_cpld_reg, NULL, CPU_DISOMIC_OVER_TEMP);
static SENSOR_DEVICE_ATTR(ddr_over_temp, S_IRUGO, get_cpld_reg, NULL, DDR_OVER_TEMP);
static SENSOR_DEVICE_ATTR(cpld_pwr_on_rst, S_IRUGO, get_cpld_reg, NULL, CPLD_PWR_ON_RST);
static SENSOR_DEVICE_ATTR(cpld_hard_rst, S_IRUGO, get_cpld_reg, NULL, CPLD_HARD_RST);
static SENSOR_DEVICE_ATTR(cpld_rst, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, CPLD_RST);
static SENSOR_DEVICE_ATTR(mb_pwr, S_IRUGO, get_cpld_reg, NULL, MB_PWR);
static SENSOR_DEVICE_ATTR(mb_rst, S_IRUGO | S_IWUSR, get_cpld_reg, set_cpld_reg, MB_RST);
static SENSOR_DEVICE_ATTR(psu_fan_int, S_IRUGO, get_cpld_reg, NULL, PSU_FAN_INT);
static SENSOR_DEVICE_ATTR(op_module_int, S_IRUGO, get_cpld_reg, NULL, OP_MODULE_INT);
static struct attribute *ag9064_cpld_attrs[] = {
&dev_attr_qsfp_present.attr,
&dev_attr_qsfp_lpmode.attr,
&dev_attr_qsfp_reset.attr,
&dev_attr_qsfp_modsel.attr,
&dev_attr_qsfp_interrupt.attr,
&sensor_dev_attr_cpld_reg_value.dev_attr.attr,
&sensor_dev_attr_cpld_reg_addr.dev_attr.attr,
&sensor_dev_attr_cpld_ver.dev_attr.attr,
&sensor_dev_attr_cpu_board_ver.dev_attr.attr,
&sensor_dev_attr_cpu_id.dev_attr.attr,
&sensor_dev_attr_mb_id.dev_attr.attr,
&sensor_dev_attr_mb_ver.dev_attr.attr,
&sensor_dev_attr_cpu0_pwr_ok.dev_attr.attr,
&sensor_dev_attr_psu_over_temp.dev_attr.attr,
&sensor_dev_attr_pwr_rail_over_temp.dev_attr.attr,
&sensor_dev_attr_cpu_disomic_over_temp.dev_attr.attr,
&sensor_dev_attr_ddr_over_temp.dev_attr.attr,
&sensor_dev_attr_cpld_pwr_on_rst.dev_attr.attr,
&sensor_dev_attr_cpld_hard_rst.dev_attr.attr,
&sensor_dev_attr_cpld_rst.dev_attr.attr,
&sensor_dev_attr_mb_pwr.dev_attr.attr,
&sensor_dev_attr_mb_rst.dev_attr.attr,
&sensor_dev_attr_psu_fan_int.dev_attr.attr,
&sensor_dev_attr_op_module_int.dev_attr.attr,
NULL,
};
static struct attribute_group ag9064_cpld_attr_grp = {
.attrs = ag9064_cpld_attrs,
};
static int __init cpld_probe(struct platform_device *pdev)
{
struct cpld_platform_data *pdata;
struct i2c_adapter *parent;
int ret;
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "CPLD platform data not found\n");
return -ENODEV;
}
parent = i2c_get_adapter(BUS7);
if (!parent) {
printk(KERN_WARNING "Parent adapter (%d) not found\n",BUS7);
return -ENODEV;
}
pdata[system_cpld].client = i2c_new_dummy(parent, pdata[system_cpld].reg_addr);
if (!pdata[system_cpld].client) {
printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[system_cpld].reg_addr);
goto error;
}
ret = sysfs_create_group(&pdev->dev.kobj, &ag9064_cpld_attr_grp);
if (ret) {
printk(KERN_WARNING "Fail to create cpld attribute group");
goto error;
}
return 0;
error:
i2c_unregister_device(pdata[system_cpld].client);
i2c_put_adapter(parent);
return -ENODEV;
}
static int __exit cpld_remove(struct platform_device *pdev)
{
struct i2c_adapter *parent = NULL;
struct cpld_platform_data *pdata = pdev->dev.platform_data;
sysfs_remove_group(&pdev->dev.kobj, &ag9064_cpld_attr_grp);
if (!pdata) {
dev_err(&pdev->dev, "Missing platform data\n");
}
else {
if (pdata[system_cpld].client) {
if (!parent) {
parent = (pdata[system_cpld].client)->adapter;
}
i2c_unregister_device(pdata[system_cpld].client);
}
}
i2c_put_adapter(parent);
return 0;
}
static struct platform_driver cpld_driver = {
.probe = cpld_probe,
.remove = __exit_p(cpld_remove),
.driver = {
.owner = THIS_MODULE,
.name = "delta-ag9064-cpld",
},
};
/*---------------- CPLD - end ------------- */
/*---------------- module initialization ------------- */
static void __init delta_ag9064_cpupld_init(void)
{
int ret;
printk(KERN_WARNING "ag9064_platform_cpupld module initialization\n");
ret = dni_create_user();
if (ret != 0){
printk(KERN_WARNING "Fail to create IPMI user\n");
}
// set the CPUPLD prob and remove
ret = platform_driver_register(&cpld_driver);
if (ret) {
printk(KERN_WARNING "Fail to register cpupld driver\n");
goto error_cpupld_driver;
}
// register the CPUPLD
ret = platform_device_register(&ag9064_cpld);
if (ret) {
printk(KERN_WARNING "Fail to create cpupld device\n");
goto error_ag9064_cpupld;
}
return 0;
error_ag9064_cpupld:
platform_driver_unregister(&cpld_driver);
error_cpupld_driver:
return ret;
}
static void __exit delta_ag9064_cpupld_exit(void)
{
platform_device_unregister(&ag9064_cpld);
platform_driver_unregister(&cpld_driver);
}
module_init(delta_ag9064_cpupld_init);
module_exit(delta_ag9064_cpupld_exit);
MODULE_DESCRIPTION("DNI ag9064 CPLD Platform Support");
MODULE_AUTHOR("Stanley Chi <stanley.chi@deltaww.com>");
MODULE_LICENSE("GPL");

View File

@ -1,86 +1,14 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sysfs.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/dmi.h>
#include <linux/version.h>
#include <linux/ctype.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/i2c/pca954x.h>
#include <linux/i2c-mux.h>
#include <linux/i2c-mux-gpio.h>
#include <linux/i2c/sff-8436.h>
#include <linux/hwmon.h>
#include <linux/mutex.h>
#include <linux/completion.h>
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h>
#define DEFAULT_NUM 1
#define BUS9_DEV_NUM 64
#define BUS9_BASE_NUM 20
#define IPMI_MAX_INTF (4)
#define DELTA_NETFN 0x38
#define BMC_BUS_5 0x04
#define CMD_SETDATA 0x3
#define CMD_GETDATA 0x2
#define CPLD_REG 0x31
#define SWPLD1_ADDR 0x35
#define SWPLD2_ADDR 0x34
#define SWPLD3_ADDR 0x33
#define SWPLD4_ADDR 0x32
#define QSFP_PORT_MUX_REG 0x13
#define QSFP_PRESENCE_1 0x3
#define QSFP_PRESENCE_2 0x3
#define QSFP_PRESENCE_3 0x24
#define QSFP_PRESENCE_4 0x24
#define QSFP_PRESENCE_5 0x4
#define QSFP_PRESENCE_6 0x4
#define QSFP_PRESENCE_7 0x25
#define QSFP_PRESENCE_8 0x25
#define QSFP_LP_MODE_1 0x0c
#define QSFP_LP_MODE_2 0x0c
#define QSFP_LP_MODE_3 0x2a
#define QSFP_LP_MODE_4 0x2a
#define QSFP_LP_MODE_5 0x0d
#define QSFP_LP_MODE_6 0x0d
#define QSFP_LP_MODE_7 0x2b
#define QSFP_LP_MODE_8 0x2b
#define QSFP_RESET_1 0x06
#define QSFP_RESET_2 0x06
#define QSFP_RESET_3 0x26
#define QSFP_RESET_4 0x26
#define QSFP_RESET_5 0x07
#define QSFP_RESET_6 0x07
#define QSFP_RESET_7 0x27
#define QSFP_RESET_8 0x27
#define QSFP_RESPONSE_1 0x09
#define QSFP_RESPONSE_2 0x09
#define QSFP_RESPONSE_3 0x28
#define QSFP_RESPONSE_4 0x28
#define QSFP_RESPONSE_5 0x0a
#define QSFP_RESPONSE_6 0x0a
#define QSFP_RESPONSE_7 0x29
#define QSFP_RESPONSE_8 0x29
#define QSFP_INTERRUPT_1 0x0f
#define QSFP_INTERRUPT_2 0x0f
#define QSFP_INTERRUPT_3 0x2c
#define QSFP_INTERRUPT_4 0x2c
#define QSFP_INTERRUPT_5 0x10
#define QSFP_INTERRUPT_6 0x10
#define QSFP_INTERRUPT_7 0x2d
#define QSFP_INTERRUPT_8 0x2d
#include "delta_ag9064_common.h"
#define SFF8436_INFO(data) \
.type = "sff8436", .addr = 0x50, .platform_data = (data)
@ -97,56 +25,8 @@
}, \
}
static void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data)
{
struct completion *comp = recv_msg->user_msg_data;
if (comp)
complete(comp);
else
ipmi_free_recv_msg(recv_msg);
return;
}
static ipmi_user_t ipmi_mh_user = NULL;
static struct ipmi_user_hndl ipmi_hndlrs = { .ipmi_recv_hndl = msg_handler,};
static atomic_t dummy_count = ATOMIC_INIT(0);
static void dummy_smi_free(struct ipmi_smi_msg *msg)
{
atomic_dec(&dummy_count);
}
static void dummy_recv_free(struct ipmi_recv_msg *msg)
{
atomic_dec(&dummy_count);
}
static struct ipmi_smi_msg halt_smi_msg = {
.done = dummy_smi_free
};
static struct ipmi_recv_msg halt_recv_msg = {
.done = dummy_recv_free
};
struct i2c_client * i2c_client_9548;
enum{
BUS0 = 0,
BUS1,
BUS2,
BUS3,
BUS4,
BUS5,
BUS6,
BUS7,
BUS8,
BUS9,
BUS10,
BUS11,
BUS12,
BUS13,
BUS14,
};
/* pca9548 - add 8 bus */
static struct pca954x_platform_mode pca954x_mode[] =
{
@ -265,8 +145,45 @@ static struct sff_8436_platform_data sff_8436_port[] = {
{ SFF_8346_PORT() },
};
/*---------------- IPMI - start ------------- */
void device_release(struct device *dev)
{
return;
}
EXPORT_SYMBOL(device_release);
void msg_handler(struct ipmi_recv_msg *recv_msg, void* handler_data)
{
struct completion *comp = recv_msg->user_msg_data;
if (comp)
complete(comp);
else
ipmi_free_recv_msg(recv_msg);
return;
}
EXPORT_SYMBOL(msg_handler);
void dummy_smi_free(struct ipmi_smi_msg *msg)
{
atomic_dec(&dummy_count);
}
EXPORT_SYMBOL(dummy_smi_free);
void dummy_recv_free(struct ipmi_recv_msg *msg)
{
atomic_dec(&dummy_count);
}
EXPORT_SYMBOL(dummy_recv_free);
unsigned char dni_log2 (unsigned char num){
unsigned char num_log2 = 0;
while(num > 0){
num = num >> 1;
num_log2 += 1;
}
return num_log2 -1;
}
EXPORT_SYMBOL(dni_log2);
/*---------------- IPMI - start ------------- */
int dni_create_user(void)
{
int rv, i;
@ -281,6 +198,7 @@ int dni_create_user(void)
return rv;
}
}
EXPORT_SYMBOL(dni_create_user);
int dni_bmc_cmd(char set_cmd, char *cmd_data, int cmd_data_len)
{
@ -299,7 +217,7 @@ int dni_bmc_cmd(char set_cmd, char *cmd_data, int cmd_data_len)
msg.data = cmd_data;
init_completion(&comp);
rv = ipmi_request_supply_msgs(ipmi_mh_user, (struct ipmi_addr*)&addr, 0,&msg, &comp, &halt_smi_msg, &halt_recv_msg, 0);
rv = ipmi_request_supply_msgs(ipmi_mh_user, (struct ipmi_addr*)&addr, 0, &msg, &comp, &halt_smi_msg, &halt_recv_msg, 0);
if (rv) {
return -6;
}
@ -334,16 +252,11 @@ int dni_bmc_cmd(char set_cmd, char *cmd_data, int cmd_data_len)
return rv;
}
EXPORT_SYMBOL(dni_bmc_cmd);
/*---------------- IPMI - stop ------------- */
/*---------------- I2C device - start ------------- */
static void device_release(struct device *dev)
{
return;
}
struct i2c_device_platform_data {
int parent;
struct i2c_board_info info;
@ -1014,7 +927,6 @@ alloc_failed:
return ret;
}
static int __exit swpld_mux_remove(struct platform_device *pdev)
{
int i;
@ -1063,657 +975,8 @@ static struct platform_driver swpld_mux_driver = {
.name = "delta-ag9064-swpld-mux",
},
};
/*---------------- MUX - end ------------- */
/*---------------- CPLD - start ------------- */
/* CPLD -- device */
static ssize_t get_present(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
int ret;
u64 data = 0;
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_GETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_PRESENCE_1;
cmd_data[3] = 1;
cmd_data_len = sizeof(cmd_data);
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data = (u64)(ret & 0xff);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_PRESENCE_2;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 8;
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_PRESENCE_3;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 16;
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_PRESENCE_4;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 24;
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_PRESENCE_5;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 32;
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_PRESENCE_6;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 40;
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_PRESENCE_7;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 48;
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_PRESENCE_8;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 56;
return sprintf(buf, "0x%016llx\n", data);
}
static ssize_t get_lpmode(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
int ret;
u64 data = 0;
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_GETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_LP_MODE_1;
cmd_data[3] = 1;
cmd_data_len = sizeof(cmd_data);
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data = (u64)(ret & 0xff);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_LP_MODE_2;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 8;
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_LP_MODE_3;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 16;
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_LP_MODE_4;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 24;
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_LP_MODE_5;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 32;
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_LP_MODE_6;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 40;
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_LP_MODE_7;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 48;
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_LP_MODE_8;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 56;
return sprintf(buf, "0x%016llx\n", data);
}
static ssize_t get_reset(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
int ret;
u64 data = 0;
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_GETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESET_1;
cmd_data[3] = 1;
cmd_data_len = sizeof(cmd_data);
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data = (u64)(ret & 0xff);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESET_2;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 8;
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESET_3;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 16;
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESET_4;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 24;
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESET_5;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 32;
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESET_6;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 40;
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESET_7;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 48;
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESET_8;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 56;
return sprintf(buf, "0x%016llx\n", data);
}
static ssize_t get_response(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
int ret;
u64 data = 0;
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_GETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESPONSE_1;
cmd_data[3] = 1;
cmd_data_len = sizeof(cmd_data);
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data = (u64)(ret & 0xff);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESPONSE_2;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 8;
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESPONSE_3;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 16;
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESPONSE_4;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 24;
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESPONSE_5;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 32;
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESPONSE_6;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 40;
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESPONSE_7;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 48;
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESPONSE_8;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 56;
return sprintf(buf, "0x%016llx\n", data);
}
static ssize_t get_interrupt(struct device *dev, struct device_attribute \
*dev_attr, char *buf)
{
int ret;
u64 data = 0;
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_GETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_INTERRUPT_1;
cmd_data[3] = 1;
cmd_data_len = sizeof(cmd_data);
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data = (u64)(ret & 0xff);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_INTERRUPT_2;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 8;
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_INTERRUPT_3;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 16;
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_INTERRUPT_4;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 24;
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_INTERRUPT_5;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 32;
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_INTERRUPT_6;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 40;
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_INTERRUPT_7;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 48;
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_INTERRUPT_8;
ret = dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
data |= (u64)(ret & 0xff) << 56;
return sprintf(buf, "0x%016llx\n", data);
}
static ssize_t set_lpmode(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count)
{
unsigned long long set_data;
int err;
err = kstrtoull(buf, 16, &set_data);
if (err){
return err;
}
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_SETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_LP_MODE_1;
cmd_data[3] = (set_data & 0xff);
cmd_data_len = sizeof(cmd_data);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_LP_MODE_2;
cmd_data[3] = ((set_data >> 8 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_LP_MODE_3;
cmd_data[3] = ((set_data >> 16 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_LP_MODE_4;
cmd_data[3] = ((set_data >> 24 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_LP_MODE_5;
cmd_data[3] = ((set_data >> 32 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_LP_MODE_6;
cmd_data[3] = ((set_data >> 40 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_LP_MODE_7;
cmd_data[3] = ((set_data >> 48 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_LP_MODE_8;
cmd_data[3] = ((set_data >> 56 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
return count;
}
static ssize_t set_reset(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count)
{
unsigned long long set_data;
int err;
err = kstrtoull(buf, 16, &set_data);
if (err){
return err;
}
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_SETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESET_1;
cmd_data[3] = (set_data & 0xff);
cmd_data_len = sizeof(cmd_data);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESET_2;
cmd_data[3] = ((set_data >> 8 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESET_3;
cmd_data[3] = ((set_data >> 16 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESET_4;
cmd_data[3] = ((set_data >> 24 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESET_5;
cmd_data[3] = ((set_data >> 32 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESET_6;
cmd_data[3] = ((set_data >> 40 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESET_7;
cmd_data[3] = ((set_data >> 48 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESET_8;
cmd_data[3] = ((set_data >> 56 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
return count;
}
static ssize_t set_response(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count)
{
unsigned long long set_data;
int err;
err = kstrtoull(buf, 16, &set_data);
if (err){
return err;
}
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
int cmd_data_len;
set_cmd = CMD_SETDATA;
/*QSFP1~8*/
cmd_data[0] = BMC_BUS_5;
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESPONSE_1;
cmd_data[3] = (set_data & 0xff);
cmd_data_len = sizeof(cmd_data);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP9~16*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESPONSE_2;
cmd_data[3] = ((set_data >> 8 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP17~24*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESPONSE_3;
cmd_data[3] = ((set_data >> 16 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP25~32*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESPONSE_4;
cmd_data[3] = ((set_data >> 24 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP33~40*/
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = QSFP_RESPONSE_5;
cmd_data[3] = ((set_data >> 32 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP41~48*/
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = QSFP_RESPONSE_6;
cmd_data[3] = ((set_data >> 40 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP49~56*/
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = QSFP_RESPONSE_7;
cmd_data[3] = ((set_data >> 48 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
/*QSFP57~64*/
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = QSFP_RESPONSE_8;
cmd_data[3] = ((set_data >> 56 ) & 0xff);
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
return count;
}
static DEVICE_ATTR(qsfp_present, S_IRUGO, get_present, NULL);
static DEVICE_ATTR(qsfp_lpmode, S_IWUSR | S_IRUGO, get_lpmode, set_lpmode);
static DEVICE_ATTR(qsfp_reset, S_IWUSR | S_IRUGO, get_reset, set_reset);
static DEVICE_ATTR(qsfp_modsel, S_IWUSR | S_IRUGO, get_response, set_response);
static DEVICE_ATTR(qsfp_interrupt, S_IRUGO, get_interrupt, NULL);
static struct attribute *ag9064_cpld_attrs[] = {
&dev_attr_qsfp_present.attr,
&dev_attr_qsfp_lpmode.attr,
&dev_attr_qsfp_reset.attr,
&dev_attr_qsfp_modsel.attr,
&dev_attr_qsfp_interrupt.attr,
NULL,
};
static struct attribute_group ag9064_cpld_attr_grp = {
.attrs = ag9064_cpld_attrs,
};
enum cpld_type {
system_cpld,
};
struct cpld_platform_data {
int reg_addr;
struct i2c_client *client;
};
static struct cpld_platform_data ag9064_cpld_platform_data[] = {
[system_cpld] = {
.reg_addr = CPLD_REG,
},
};
static struct platform_device ag9064_cpld = {
.name = "delta-ag9064-cpld",
.id = 0,
.dev = {
.platform_data = ag9064_cpld_platform_data,
.release = device_release
},
};
static int __init cpld_probe(struct platform_device *pdev)
{
struct cpld_platform_data *pdata;
struct i2c_adapter *parent;
int ret;
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "CPLD platform data not found\n");
return -ENODEV;
}
parent = i2c_get_adapter(BUS7);
if (!parent) {
printk(KERN_WARNING "Parent adapter (%d) not found\n",BUS7);
return -ENODEV;
}
pdata[system_cpld].client = i2c_new_dummy(parent, pdata[system_cpld].reg_addr);
if (!pdata[system_cpld].client) {
printk(KERN_WARNING "Fail to create dummy i2c client for addr %d\n", pdata[system_cpld].reg_addr);
goto error;
}
ret = sysfs_create_group(&pdev->dev.kobj, &ag9064_cpld_attr_grp);
if (ret) {
printk(KERN_WARNING "Fail to create cpld attribute group");
goto error;
}
return 0;
error:
i2c_unregister_device(pdata[system_cpld].client);
i2c_put_adapter(parent);
return -ENODEV;
}
static int __exit cpld_remove(struct platform_device *pdev)
{
struct i2c_adapter *parent = NULL;
struct cpld_platform_data *pdata = pdev->dev.platform_data;
sysfs_remove_group(&pdev->dev.kobj, &ag9064_cpld_attr_grp);
if (!pdata) {
dev_err(&pdev->dev, "Missing platform data\n");
}
else {
if (pdata[system_cpld].client) {
if (!parent) {
parent = (pdata[system_cpld].client)->adapter;
}
i2c_unregister_device(pdata[system_cpld].client);
}
}
i2c_put_adapter(parent);
return 0;
}
static struct platform_driver cpld_driver = {
.probe = cpld_probe,
.remove = __exit_p(cpld_remove),
.driver = {
.owner = THIS_MODULE,
.name = "delta-ag9064-cpld",
},
};
/*---------------- CPLD - end ------------- */
/*---------------- module initialization ------------- */
static void __init delta_ag9064_platform_init(void)
@ -1734,12 +997,6 @@ static void __init delta_ag9064_platform_init(void)
printk(KERN_WARNING "Fail to create IPMI user\n");
}
ret = platform_driver_register(&cpld_driver);
if (ret) {
printk(KERN_WARNING "Fail to register cpld driver\n");
goto error_cpld_driver;
}
// register the mux prob which call the SWPLD
ret = platform_driver_register(&swpld_mux_driver);
if (ret) {
@ -1754,13 +1011,6 @@ static void __init delta_ag9064_platform_init(void)
goto error_i2c_device_driver;
}
// register the CPLD
ret = platform_device_register(&ag9064_cpld);
if (ret) {
printk(KERN_WARNING "Fail to create cpld device\n");
goto error_ag9064_cpld;
}
swpld_pdata = ag9064_swpld_mux[0].dev.platform_data;
//swpld_pdata->cpld = cpld_pdata[system_cpld].client;
ret = platform_device_register(&ag9064_swpld_mux);
@ -1794,14 +1044,10 @@ error_ag9064_swpld_mux:
for (; i >= 0; i--) {
platform_device_unregister(&ag9064_swpld_mux);
}
platform_driver_unregister(&ag9064_cpld);
error_ag9064_cpld:
platform_driver_unregister(&i2c_device_driver);
error_i2c_device_driver:
platform_driver_unregister(&swpld_mux_driver);
error_swpld_mux_driver:
platform_driver_unregister(&cpld_driver);
error_cpld_driver:
return ret;
}
@ -1814,10 +1060,8 @@ static void __exit delta_ag9064_platform_exit(void)
}
platform_device_unregister(&ag9064_swpld_mux);
platform_device_unregister(&ag9064_cpld);
platform_driver_unregister(&i2c_device_driver);
platform_driver_unregister(&swpld_mux_driver);
platform_driver_unregister(&cpld_driver);
i2c_unregister_device(i2c_client_9548);
}
@ -1826,4 +1070,4 @@ module_exit(delta_ag9064_platform_exit);
MODULE_DESCRIPTION("DELTA ag9064 Platform Support");
MODULE_AUTHOR("Johnson Lu <johnson.lu@deltaww.com>");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,620 @@
#include "delta_ag9064_common.h"
unsigned char swpld1_reg_addr;
unsigned char swpld2_reg_addr;
unsigned char swpld3_reg_addr;
unsigned char swpld4_reg_addr;
/*---------------- CPLD - start ------------- */
/* SWPLD1 -- device */
static struct platform_device swpld1_device = {
.name = "delta-ag9064-swpld1",
.id = 0,
.dev = {
.platform_data = ag9064_swpld1_platform_data,
.release = device_release
},
};
static struct platform_device swpld2_device = {
.name = "delta-ag9064-swpld2",
.id = 0,
.dev = {
.platform_data = ag9064_swpld2_platform_data,
.release = device_release
},
};
static struct platform_device swpld3_device = {
.name = "delta-ag9064-swpld3",
.id = 0,
.dev = {
.platform_data = ag9064_swpld3_platform_data,
.release = device_release
},
};
static struct platform_device swpld4_device = {
.name = "delta-ag9064-swpld4",
.id = 0,
.dev = {
.platform_data = ag9064_swpld4_platform_data,
.release = device_release
},
};
static ssize_t get_swpld_reg(struct device *dev, struct device_attribute *dev_attr, char *buf)
{
int ret;
int mask;
int value;
int cmd_data_len;
char note[200];
uint8_t cmd_data[4]={0};
uint8_t get_cmd;
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
cmd_data_len = sizeof(cmd_data);
get_cmd = CMD_GETDATA;
cmd_data[0] = BMC_BUS_5;
cmd_data[3] = 1;
mask = attribute_data[attr->index].mask;
sprintf(note, "\n%s\n",attribute_data[attr->index].note);
if (attr->index <= SWPLD4_REG_VALUE){
switch (attr->index) {
case SWPLD1_REG_ADDR:
return sprintf(buf, "0x%02x\n", swpld1_reg_addr);
case SWPLD2_REG_ADDR:
return sprintf(buf, "0x%02x\n", swpld2_reg_addr);
case SWPLD3_REG_ADDR:
return sprintf(buf, "0x%02x\n", swpld3_reg_addr);
case SWPLD4_REG_ADDR:
return sprintf(buf, "0x%02x\n", swpld4_reg_addr);
case SWPLD1_REG_VALUE:
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = swpld1_reg_addr;
break;
case SWPLD2_REG_VALUE:
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = swpld2_reg_addr;
break;
case SWPLD3_REG_VALUE:
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = swpld3_reg_addr;
break;
case SWPLD4_REG_VALUE:
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = swpld4_reg_addr;
break;
default:
return sprintf(buf, "%d not found", attr->index);
}
ret = dni_bmc_cmd(get_cmd, cmd_data, cmd_data_len);
ret = ret & 0xff;
return sprintf(buf, "0x%02x\n", ret);
}else{
switch (attr->index) {
case SWPLD1_MAJOR_VER ... PSU_LED_MODE :
cmd_data[1] = SWPLD1_ADDR;
break;
case SWPLD2_MAJOR_VER ... FAN_MOD4_LED :
cmd_data[1] = SWPLD2_ADDR;
break;
case SWPLD3_MAJOR_VER ... PLATFORM_TYPE :
cmd_data[1] = SWPLD3_ADDR;
break;
case SWPLD4_MAJOR_VER ... FAN_EEPROM_WP :
cmd_data[1] = SWPLD4_ADDR;
break;
default:
return sprintf(buf, "%d not found", attr->index);
}
cmd_data[2] = attribute_data[attr->index].reg;
value = dni_bmc_cmd(get_cmd, cmd_data, cmd_data_len);
value = value & mask;
switch (mask) {
case 0xFF:
return sprintf(buf, "0x%02x%s", value, note);
case 0x0F:
return sprintf(buf, "0x%01x%s", value, note);
case 0xF0:
value = value >> 4;
return sprintf(buf, "0x%01x%s", value, note);
case 0xC0:
value = value >> 6;
return sprintf(buf, "0x%01x%s", value, note);
case 0x30:
value = value >> 4;
return sprintf(buf, "0x%01x%s", value, note);
default :
value = value >> dni_log2(mask);
return sprintf(buf, "%d%s", value, note);
}
}
}
static ssize_t set_swpld_reg(struct device *dev, struct device_attribute *dev_attr,
const char *buf, size_t count)
{
int err;
int value;
int set_data;
int cmd_data_len;
uint8_t cmd_data[4]={0};
uint8_t set_cmd;
uint8_t get_cmd;
unsigned char mask;
unsigned char mask_out;
struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
cmd_data_len = sizeof(cmd_data);
set_cmd = CMD_SETDATA;
get_cmd = CMD_GETDATA;
err = kstrtoul(buf, 0, &set_data);
if (err){
return err;
}
if (set_data > 0xff){
printk(KERN_ALERT "address out of range (0x00-0xFF)\n");
return count;
}
if (attr->index <= SWPLD4_REG_VALUE){
cmd_data[0] = BMC_BUS_5;
cmd_data[3] = set_data;
switch (attr->index) {
//reg_addr
case SWPLD1_REG_ADDR:
swpld1_reg_addr = set_data;
return count;
case SWPLD2_REG_ADDR:
swpld2_reg_addr = set_data;
return count;
case SWPLD3_REG_ADDR:
swpld3_reg_addr = set_data;
return count;
case SWPLD4_REG_ADDR:
swpld4_reg_addr = set_data;
return count;
//reg_value
case SWPLD1_REG_VALUE:
cmd_data[1] = SWPLD1_ADDR;
cmd_data[2] = swpld1_reg_addr;
break;
case SWPLD2_REG_VALUE:
cmd_data[1] = SWPLD2_ADDR;
cmd_data[2] = swpld2_reg_addr;
break;
case SWPLD3_REG_VALUE:
cmd_data[1] = SWPLD3_ADDR;
cmd_data[2] = swpld3_reg_addr;
break;
case SWPLD4_REG_VALUE:
cmd_data[1] = SWPLD4_ADDR;
cmd_data[2] = swpld4_reg_addr;
break;
default :
return sprintf(buf, "%d not found", attr->index);
}
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
return count;
}
else{
cmd_data[0] = BMC_BUS_5;
cmd_data[2] = attribute_data[attr->index].reg;
cmd_data[3] = 1;
switch (attr->index) {
//attributes
case SWPLD1_MAJOR_VER ... PSU_LED_MODE://SWPLD1
cmd_data[1] = SWPLD1_ADDR;
break;
case SWPLD2_MAJOR_VER ... FAN_MOD4_LED://SWPLD2
cmd_data[1] = SWPLD2_ADDR;
break;
case SWPLD3_MAJOR_VER ... PLATFORM_TYPE://SWPLD3
cmd_data[1] = SWPLD3_ADDR;
break;
case SWPLD4_MAJOR_VER ... FAN_EEPROM_WP://SWPLD4
cmd_data[1] = SWPLD4_ADDR;
break;
default:
return sprintf(buf, "%d not found", attr->index);
}
value = dni_bmc_cmd(get_cmd, cmd_data, cmd_data_len);
mask = attribute_data[attr->index].mask;
mask_out = value & ~(mask);
cmd_data[3] = set_data;
switch (mask) {
case 0xFF:
set_data = mask_out | (set_data & mask);
break;
case 0x0F:
set_data = mask_out | (set_data & mask);
break;
case 0xF0:
set_data = set_data << 4;
set_data = mask_out | (set_data & mask);
break;
case 0xC0:
set_data = set_data << 6;
set_data = mask_out | (set_data & mask);
break;
case 0x30:
set_data = set_data << 4;
set_data = mask_out | (set_data & mask);
break;
default :
set_data = mask_out | (set_data << dni_log2(mask) );
}
dni_bmc_cmd(set_cmd, cmd_data, cmd_data_len);
return count;
}
}
//SWPLD
static SENSOR_DEVICE_ATTR(swpld1_reg_addr, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD1_REG_ADDR);
static SENSOR_DEVICE_ATTR(swpld1_reg_value, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD1_REG_VALUE);
static SENSOR_DEVICE_ATTR(swpld2_reg_addr, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD2_REG_ADDR);
static SENSOR_DEVICE_ATTR(swpld2_reg_value, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD2_REG_VALUE);
static SENSOR_DEVICE_ATTR(swpld3_reg_addr, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD3_REG_ADDR);
static SENSOR_DEVICE_ATTR(swpld3_reg_value, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD3_REG_VALUE);
static SENSOR_DEVICE_ATTR(swpld4_reg_addr, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD4_REG_ADDR);
static SENSOR_DEVICE_ATTR(swpld4_reg_value, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD4_REG_VALUE);
//SWPLD1
static SENSOR_DEVICE_ATTR(swpld1_major_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD1_MAJOR_VER);
static SENSOR_DEVICE_ATTR(swpld1_minor_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD1_MINOR_VER);
static SENSOR_DEVICE_ATTR(swpld1_scrtch_reg, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD1_SCRTCH_REG);
static SENSOR_DEVICE_ATTR(psu1_pwr_ok, S_IRUGO, get_swpld_reg, NULL, PSU1_PWR_OK);
static SENSOR_DEVICE_ATTR(psu1_int, S_IRUGO, get_swpld_reg, NULL, PSU1_INT);
static SENSOR_DEVICE_ATTR(psu2_pwr_ok, S_IRUGO, get_swpld_reg, NULL, PSU2_PWR_OK);
static SENSOR_DEVICE_ATTR(psu2_int, S_IRUGO, get_swpld_reg, NULL, PSU2_INT);
static SENSOR_DEVICE_ATTR(synce_int, S_IRUGO, get_swpld_reg, NULL, SYNCE_INT);
static SENSOR_DEVICE_ATTR(synce_rst, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SYNCE_RST);
static SENSOR_DEVICE_ATTR(synce_eeprom_wp, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SYNCE_EEPROM_WP);
static SENSOR_DEVICE_ATTR(psu1_green_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, PSU1_GREEN_LED);
static SENSOR_DEVICE_ATTR(psu1_red_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, PSU1_RED_LED);
static SENSOR_DEVICE_ATTR(psu2_green_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, PSU2_GREEN_LED);
static SENSOR_DEVICE_ATTR(psu2_red_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, PSU2_RED_LED);
static SENSOR_DEVICE_ATTR(psu_led_mode, S_IRUGO, get_swpld_reg, NULL, PSU_LED_MODE);
//SWPLD2
static SENSOR_DEVICE_ATTR(swpld2_major_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD2_MAJOR_VER);
static SENSOR_DEVICE_ATTR(swpld2_minor_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD2_MINOR_VER);
static SENSOR_DEVICE_ATTR(swpld2_scrtch_reg, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD2_SCRTCH_REG);
static SENSOR_DEVICE_ATTR(fan_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_LED);
static SENSOR_DEVICE_ATTR(sys_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SYS_LED);
static SENSOR_DEVICE_ATTR(fan_mod1_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_MOD1_LED);
static SENSOR_DEVICE_ATTR(fan_mod2_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_MOD2_LED);
static SENSOR_DEVICE_ATTR(fan_mod3_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_MOD3_LED);
static SENSOR_DEVICE_ATTR(fan_mod4_led, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_MOD4_LED);
//SWPLD3
static SENSOR_DEVICE_ATTR(swpld3_major_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD3_MAJOR_VER);
static SENSOR_DEVICE_ATTR(swpld3_minor_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD3_MINOR_VER);
static SENSOR_DEVICE_ATTR(swpld3_scrtch_reg, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD3_SCRTCH_REG);
static SENSOR_DEVICE_ATTR(sb_ver, S_IRUGO, get_swpld_reg, NULL, SB_VER);
static SENSOR_DEVICE_ATTR(platform_type, S_IRUGO, get_swpld_reg, NULL, PLATFORM_TYPE);
//SWPLD4
static SENSOR_DEVICE_ATTR(swpld4_major_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD4_MAJOR_VER);
static SENSOR_DEVICE_ATTR(swpld4_minor_ver, S_IRUGO, get_swpld_reg, NULL, SWPLD4_MINOR_VER);
static SENSOR_DEVICE_ATTR(swpld4_scrtch_reg, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SWPLD4_SCRTCH_REG);
static SENSOR_DEVICE_ATTR(bmc_rst, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, BMC_RST);
static SENSOR_DEVICE_ATTR(cpld_lpc_rst, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, CPLD_LPC_RST);
static SENSOR_DEVICE_ATTR(cpld_sw_rst, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, CPLD_SW_RST);
static SENSOR_DEVICE_ATTR(mb_cpld_rst, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, MB_CPLD_RST);
static SENSOR_DEVICE_ATTR(bcm56970_rst, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, BCM56970_RST);
static SENSOR_DEVICE_ATTR(cpld_upgrade_rst, S_IRUGO, get_swpld_reg, NULL, CPLD_UPGRADE_RST);
static SENSOR_DEVICE_ATTR(mb_rst_cpld, S_IRUGO, get_swpld_reg, NULL, MB_RST_CPLD);
static SENSOR_DEVICE_ATTR(cpu_rst_mb_oob, S_IRUGO, get_swpld_reg, NULL, CPU_RST_MB_OOB);
static SENSOR_DEVICE_ATTR(gpio_phy_rst, S_IRUGO, get_swpld_reg, NULL, GPIO_PHY_RST);
static SENSOR_DEVICE_ATTR(psu_fan_event, S_IRUGO, get_swpld_reg, NULL, PSU_FAN_EVENT);
static SENSOR_DEVICE_ATTR(cpu_thermal_int, S_IRUGO, get_swpld_reg, NULL, CPU_THERMAL_INT);
static SENSOR_DEVICE_ATTR(fan_int, S_IRUGO, get_swpld_reg, NULL, FAN_INT);
static SENSOR_DEVICE_ATTR(cpld_spi_wp, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, CPLD_SPI_WP);
static SENSOR_DEVICE_ATTR(rj45_console_sel, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, RJ45_CONSOLE_SEL);
static SENSOR_DEVICE_ATTR(system_int, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, SYSTEM_INT);
static SENSOR_DEVICE_ATTR(cpld_mb_rst_done, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, CPLD_MB_RST_DONE);
static SENSOR_DEVICE_ATTR(mb_pwr_ok, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, MB_PWR_OK);
static SENSOR_DEVICE_ATTR(fan_eeprom_wp, S_IRUGO | S_IWUSR, get_swpld_reg, set_swpld_reg, FAN_EEPROM_WP);
static struct attribute *swpld1_device_attrs[] = {
&sensor_dev_attr_swpld1_reg_value.dev_attr.attr,
&sensor_dev_attr_swpld1_reg_addr.dev_attr.attr,
&sensor_dev_attr_swpld1_major_ver.dev_attr.attr,
&sensor_dev_attr_swpld1_minor_ver.dev_attr.attr,
&sensor_dev_attr_swpld1_scrtch_reg.dev_attr.attr,
&sensor_dev_attr_psu1_pwr_ok.dev_attr.attr,
&sensor_dev_attr_psu1_int.dev_attr.attr,
&sensor_dev_attr_psu2_pwr_ok.dev_attr.attr,
&sensor_dev_attr_psu2_int.dev_attr.attr,
&sensor_dev_attr_synce_int.dev_attr.attr,
&sensor_dev_attr_synce_rst.dev_attr.attr,
&sensor_dev_attr_synce_eeprom_wp.dev_attr.attr,
&sensor_dev_attr_psu1_green_led.dev_attr.attr,
&sensor_dev_attr_psu1_red_led.dev_attr.attr,
&sensor_dev_attr_psu2_green_led.dev_attr.attr,
&sensor_dev_attr_psu2_red_led.dev_attr.attr,
&sensor_dev_attr_psu_led_mode.dev_attr.attr,
NULL,
};
static struct attribute *swpld2_device_attrs[] = {
&sensor_dev_attr_swpld2_reg_value.dev_attr.attr,
&sensor_dev_attr_swpld2_reg_addr.dev_attr.attr,
&sensor_dev_attr_swpld2_major_ver.dev_attr.attr,
&sensor_dev_attr_swpld2_minor_ver.dev_attr.attr,
&sensor_dev_attr_swpld2_scrtch_reg.dev_attr.attr,
&sensor_dev_attr_fan_led.dev_attr.attr,
&sensor_dev_attr_sys_led.dev_attr.attr,
&sensor_dev_attr_fan_mod1_led.dev_attr.attr,
&sensor_dev_attr_fan_mod2_led.dev_attr.attr,
&sensor_dev_attr_fan_mod3_led.dev_attr.attr,
&sensor_dev_attr_fan_mod4_led.dev_attr.attr,
NULL,
};
static struct attribute *swpld3_device_attrs[] = {
&sensor_dev_attr_swpld3_reg_value.dev_attr.attr,
&sensor_dev_attr_swpld3_reg_addr.dev_attr.attr,
&sensor_dev_attr_swpld3_major_ver.dev_attr.attr,
&sensor_dev_attr_swpld3_minor_ver.dev_attr.attr,
&sensor_dev_attr_swpld3_scrtch_reg.dev_attr.attr,
&sensor_dev_attr_sb_ver.dev_attr.attr,
&sensor_dev_attr_platform_type.dev_attr.attr,
NULL,
};
static struct attribute *swpld4_device_attrs[] = {
&sensor_dev_attr_swpld4_reg_value.dev_attr.attr,
&sensor_dev_attr_swpld4_reg_addr.dev_attr.attr,
&sensor_dev_attr_swpld4_major_ver.dev_attr.attr,
&sensor_dev_attr_swpld4_minor_ver.dev_attr.attr,
&sensor_dev_attr_swpld4_scrtch_reg.dev_attr.attr,
&sensor_dev_attr_bmc_rst.dev_attr.attr,
&sensor_dev_attr_cpld_lpc_rst.dev_attr.attr,
&sensor_dev_attr_cpld_sw_rst.dev_attr.attr,
&sensor_dev_attr_mb_cpld_rst.dev_attr.attr,
&sensor_dev_attr_bcm56970_rst.dev_attr.attr,
&sensor_dev_attr_cpld_upgrade_rst.dev_attr.attr,
&sensor_dev_attr_mb_rst_cpld.dev_attr.attr,
&sensor_dev_attr_cpu_rst_mb_oob.dev_attr.attr,
&sensor_dev_attr_gpio_phy_rst.dev_attr.attr,
&sensor_dev_attr_psu_fan_event.dev_attr.attr,
&sensor_dev_attr_cpu_thermal_int.dev_attr.attr,
&sensor_dev_attr_fan_int.dev_attr.attr,
&sensor_dev_attr_cpld_spi_wp.dev_attr.attr,
&sensor_dev_attr_rj45_console_sel.dev_attr.attr,
&sensor_dev_attr_system_int.dev_attr.attr,
&sensor_dev_attr_cpld_mb_rst_done.dev_attr.attr,
&sensor_dev_attr_mb_pwr_ok.dev_attr.attr,
&sensor_dev_attr_fan_eeprom_wp.dev_attr.attr,
NULL,
};
static struct attribute_group swpld1_device_attr_grp = {
.attrs = swpld1_device_attrs,
};
static struct attribute_group swpld2_device_attr_grp = {
.attrs = swpld2_device_attrs,
};
static struct attribute_group swpld3_device_attr_grp = {
.attrs = swpld3_device_attrs,
};
static struct attribute_group swpld4_device_attr_grp = {
.attrs = swpld4_device_attrs,
};
static int __init swpld1_probe(struct platform_device *pdev)
{
int ret;
ret = sysfs_create_group(&pdev->dev.kobj, &swpld1_device_attr_grp);
if (ret) {
printk(KERN_WARNING "Fail to create cpld attribute group");
return -ENODEV;
}
return 0;
}
static int __init swpld2_probe(struct platform_device *pdev)
{
int ret;
ret = sysfs_create_group(&pdev->dev.kobj, &swpld2_device_attr_grp);
if (ret) {
printk(KERN_WARNING "Fail to create cpld attribute group");
return -ENODEV;
}
return 0;
}
static int __init swpld3_probe(struct platform_device *pdev)
{
int ret;
ret = sysfs_create_group(&pdev->dev.kobj, &swpld3_device_attr_grp);
if (ret) {
printk(KERN_WARNING "Fail to create cpld attribute group");
return -ENODEV;
}
return 0;
}
static int __init swpld4_probe(struct platform_device *pdev)
{
int ret;
ret = sysfs_create_group(&pdev->dev.kobj, &swpld4_device_attr_grp);
if (ret) {
printk(KERN_WARNING "Fail to create cpld attribute group");
return -ENODEV;
}
return 0;
}
static int __exit swpld1_remove(struct platform_device *pdev)
{
sysfs_remove_group(&pdev->dev.kobj, &swpld1_device_attr_grp);
return 0;
}
static int __exit swpld2_remove(struct platform_device *pdev)
{
sysfs_remove_group(&pdev->dev.kobj, &swpld2_device_attr_grp);
return 0;
}
static int __exit swpld3_remove(struct platform_device *pdev)
{
sysfs_remove_group(&pdev->dev.kobj, &swpld3_device_attr_grp);
return 0;
}
static int __exit swpld4_remove(struct platform_device *pdev)
{
sysfs_remove_group(&pdev->dev.kobj, &swpld4_device_attr_grp);
return 0;
}
static struct platform_driver swpld1_driver = {
.probe = swpld1_probe,
.remove = __exit_p(swpld1_remove),
.driver = {
.owner = THIS_MODULE,
.name = "delta-ag9064-swpld1",
},
};
static struct platform_driver swpld2_driver = {
.probe = swpld2_probe,
.remove = __exit_p(swpld2_remove),
.driver = {
.owner = THIS_MODULE,
.name = "delta-ag9064-swpld2",
},
};
static struct platform_driver swpld3_driver = {
.probe = swpld3_probe,
.remove = __exit_p(swpld3_remove),
.driver = {
.owner = THIS_MODULE,
.name = "delta-ag9064-swpld3",
},
};
static struct platform_driver swpld4_driver = {
.probe = swpld4_probe,
.remove = __exit_p(swpld4_remove),
.driver = {
.owner = THIS_MODULE,
.name = "delta-ag9064-swpld4",
},
};
/*---------------- CPLD - end ------------- */
/*---------------- module initialization ------------- */
static void __init delta_ag9064_swpld_init(void)
{
int ret;
printk(KERN_WARNING "ag9064_platform_swpld module initialization\n");
ret = dni_create_user();
if (ret != 0){
printk(KERN_WARNING "Fail to create IPMI user\n");
}
// set the SWPLD prob and remove
ret = platform_driver_register(&swpld1_driver);
if (ret) {
printk(KERN_WARNING "Fail to register swpld driver\n");
goto error_swpld1_driver;
}
// register the SWPLD
ret = platform_device_register(&swpld1_device);
if (ret) {
printk(KERN_WARNING "Fail to create swpld device\n");
goto error_swpld1_device;
}
// set the SWPLD prob and remove
ret = platform_driver_register(&swpld2_driver);
if (ret) {
printk(KERN_WARNING "Fail to register swpld driver\n");
goto error_swpld2_driver;
}
// register the SWPLD
ret = platform_device_register(&swpld2_device);
if (ret) {
printk(KERN_WARNING "Fail to create swpld device\n");
goto error_swpld2_device;
}
// set the SWPLD prob and remove
ret = platform_driver_register(&swpld3_driver);
if (ret) {
printk(KERN_WARNING "Fail to register swpld driver\n");
goto error_swpld3_driver;
}
// register the SWPLD
ret = platform_device_register(&swpld3_device);
if (ret) {
printk(KERN_WARNING "Fail to create swpld device\n");
goto error_swpld3_device;
}
// set the SWPLD prob and remove
ret = platform_driver_register(&swpld4_driver);
if (ret) {
printk(KERN_WARNING "Fail to register swpld driver\n");
goto error_swpld4_driver;
}
// register the SWPLD
ret = platform_device_register(&swpld4_device);
if (ret) {
printk(KERN_WARNING "Fail to create swpld device\n");
goto error_swpld4_device;
}
return 0;
error_swpld4_device:
platform_driver_unregister(&swpld4_driver);
error_swpld4_driver:
platform_driver_unregister(&swpld3_device);
error_swpld3_device:
platform_driver_unregister(&swpld3_driver);
error_swpld3_driver:
platform_driver_unregister(&swpld2_device);
error_swpld2_device:
platform_driver_unregister(&swpld2_driver);
error_swpld2_driver:
platform_driver_unregister(&swpld1_device);
error_swpld1_device:
platform_driver_unregister(&swpld1_driver);
error_swpld1_driver:
return ret;
}
static void __exit delta_ag9064_swpld_exit(void)
{
platform_device_unregister(&swpld1_device);
platform_driver_unregister(&swpld1_driver);
platform_device_unregister(&swpld2_device);
platform_driver_unregister(&swpld2_driver);
platform_device_unregister(&swpld3_device);
platform_driver_unregister(&swpld3_driver);
platform_device_unregister(&swpld4_device);
platform_driver_unregister(&swpld4_driver);
}
module_init(delta_ag9064_swpld_init);
module_exit(delta_ag9064_swpld_exit);
MODULE_DESCRIPTION("DNI ag9064 CPLD Platform Support");
MODULE_AUTHOR("Stanley Chi <stanley.chi@deltaww.com>");
MODULE_LICENSE("GPL");

View File

@ -26,6 +26,8 @@ start)
modprobe ipmi_devintf
modprobe ipmi_si trydefaults=1
modprobe delta_ag9064_platform
modprobe delta_ag9064_cpld
modprobe delta_ag9064_swpld
/usr/local/bin/ag9064_platform_init.sh