[platform-celestica] - Implement FAN APIs based on the new platform API (#2739)

* [platform/cel] Implement FAN APIs based on the new platform API

* [platform/cel] Move platform api to under device platform

* [platform/cel] Remove rule to build platform api python wheel
This commit is contained in:
Wirut Getbamrung 2019-05-09 14:57:17 +07:00 committed by lguohan
parent b7235fc949
commit 38ad2a8dad
10 changed files with 788 additions and 21 deletions

View File

@ -0,0 +1,108 @@
#!/usr/bin/env python
#############################################################################
# Celestica
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Chassis information which are available in the platform
#
#############################################################################
import sys
import re
import os
import subprocess
import json
try:
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.fan import Fan
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
MMC_CPLD_ADDR = '0x100'
BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version"
CONFIG_DB_PATH = "/etc/sonic/config_db.json"
SMC_CPLD_PATH = "/sys/devices/platform/e1031.smc/version"
MMC_CPLD_PATH = "/sys/devices/platform/e1031.smc/getreg"
NUM_FAN = 3
class Chassis(ChassisBase):
"""Platform-specific Chassis class"""
def __init__(self):
self.config_data = {}
for index in range(0, NUM_FAN):
fan = Fan(index)
self._fan_list.append(fan)
ChassisBase.__init__(self)
def __get_register_value(self, path, register):
cmd = "echo {1} > {0}; cat {0}".format(path, register)
p = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
raw_data, err = p.communicate()
if err is not '':
return 'None'
else:
return raw_data.strip()
def __read_config_db(self):
try:
with open(CONFIG_DB_PATH, 'r') as fd:
data = json.load(fd)
return data
except IOError:
raise IOError("Unable to open config_db file !")
def get_base_mac(self):
"""
Retrieves the base MAC address for the chassis
Returns:
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
try:
self.config_data = self.__read_config_db()
base_mac = self.config_data["DEVICE_METADATA"]["localhost"]["mac"]
return str(base_mac)
except KeyError:
raise KeyError("Base MAC not found")
def get_component_versions(self):
"""
Retrieves platform-specific hardware/firmware versions for chassis
componenets such as BIOS, CPLD, FPGA, etc.
Returns:
A string containing platform-specific component versions
"""
component_versions = dict()
# Get BIOS version
try:
with open(BIOS_VERSION_PATH, 'r') as fd:
bios_version = fd.read()
except IOError:
raise IOError("Unable to open version file !")
# Get CPLD version
cpld_version = dict()
with open(SMC_CPLD_PATH, 'r') as fd:
smc_cpld_version = fd.read()
smc_cpld_version = 'None' if smc_cpld_version is 'None' else "{}.{}".format(
int(smc_cpld_version[2], 16), int(smc_cpld_version[3], 16))
mmc_cpld_version = self.__get_register_value(
MMC_CPLD_PATH, MMC_CPLD_ADDR)
mmc_cpld_version = 'None' if mmc_cpld_version is 'None' else "{}.{}".format(
int(mmc_cpld_version[2], 16), int(mmc_cpld_version[3], 16))
cpld_version["SMC"] = smc_cpld_version
cpld_version["MMC"] = mmc_cpld_version
component_versions["CPLD"] = cpld_version
component_versions["BIOS"] = bios_version.strip()
return str(component_versions)

View File

@ -0,0 +1,183 @@
#!/usr/bin/env python
#############################################################################
# Celestica
#
# Module contains an implementation of SONiC Platform Base API and
# provides the fan status which are available in the platform
#
#############################################################################
import json
import math
import os.path
try:
from sonic_platform_base.fan_base import FanBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
EMC2305_FAN_PATH = "/sys/bus/i2c/drivers/emc2305/"
FAN_PATH = "/sys/devices/platform/e1031.smc/"
SYS_GPIO_DIR = "/sys/class/gpio"
EMC2305_MAX_PWM = 255
EMC2305_FAN_PWM = "pwm{}"
EMC2305_FAN_TARGET = "fan{}_target"
EMC2305_FAN_INPUT = "pwm{}"
class Fan(FanBase):
"""Platform-specific Fan class"""
def __init__(self, fan_index):
self.index = fan_index
self.config_data = {}
self.fan_speed = 0
# e1031 fan attributes
# Single emc2305 chip located at i2c-23-4d
# to control a fan module
self.e1031_emc2305_chip = [
{
'device': "23-004d",
'index_map': [1, 2, 4]
}
]
# TODO: Add fan presence status in sysfs
self.fan_e1031_presence = "fan{}_prs"
self.fan_e1031_direction = "fan{}_dir"
self.fan_e1031_led = "fan{}_led"
self.fan_e1031_led_col_map = {
self.STATUS_LED_COLOR_GREEN: "green",
self.STATUS_LED_COLOR_RED: "amber",
self.STATUS_LED_COLOR_OFF: "off"
}
FanBase.__init__(self)
def get_direction(self):
direction = self.FAN_DIRECTION_INTAKE
try:
fan_direction_file = (FAN_PATH +
self.fan_e1031_direction.format(self.index+1))
with open(fan_direction_file, 'r') as file:
raw = file.read().strip('\r\n')
if str(raw).upper() == "F2B":
direction = self.FAN_DIRECTION_INTAKE
else:
direction = self.FAN_DIRECTION_EXHAUST
except IOError:
return False
return direction
def get_speed(self):
"""
E1031 platform specific data:
speed = pwm_in/255*100
"""
# TODO: Seperate PSU's fan and main fan class
if self.fan_speed != 0:
return self.fan_speed
else:
speed = 0
pwm = []
emc2305_chips = self.e1031_emc2305_chip
for chip in emc2305_chips:
device = chip['device']
fan_index = chip['index_map']
sysfs_path = "%s%s/%s" % (
EMC2305_FAN_PATH, device, EMC2305_FAN_INPUT)
sysfs_path = sysfs_path.format(fan_index[self.index])
try:
with open(sysfs_path, 'r') as file:
raw = file.read().strip('\r\n')
pwm.append(int(raw, 10))
except IOError:
raise IOError("Unable to open " + sysfs_path)
speed = math.ceil(
float(pwm[0]) * 100 / EMC2305_MAX_PWM)
return int(speed)
def get_target_speed(self):
"""
E1031 platform specific data:
speed_pc = pwm_target/255*100
0 : when PWM mode is use
pwm : when pwm mode is not use
"""
target = 0
pwm = []
emc2305_chips = self.e1031_emc2305_chip
for chip in emc2305_chips:
device = chip['device']
fan_index = chip['index_map']
sysfs_path = "%s%s/%s" % (
EMC2305_FAN_PATH, device, EMC2305_FAN_TARGET)
sysfs_path = sysfs_path.format(fan_index[self.index])
try:
with open(sysfs_path, 'r') as file:
raw = file.read().strip('\r\n')
pwm.append(int(raw, 10))
except IOError:
raise IOError("Unable to open " + sysfs_path)
target = pwm[0] * 100 / EMC2305_MAX_PWM
return target
def get_speed_tolerance(self):
"""
Retrieves the speed tolerance of the fan
Returns:
An integer, the percentage of variance from target speed which is
considered tolerable
"""
return 10
def set_speed(self, speed):
"""
Depends on pwm or target mode is selected:
1) pwm = speed_pc * 255 <-- Currently use this mode.
2) target_pwm = speed_pc * 100 / 255
2.1) set pwm{}_enable to 3
"""
pwm = speed * 255 / 100
emc2305_chips = self.e1031_emc2305_chip
for chip in emc2305_chips:
device = chip['device']
fan_index = chip['index_map']
sysfs_path = "%s%s/%s" % (
EMC2305_FAN_PATH, device, EMC2305_FAN_PWM)
sysfs_path = sysfs_path.format(fan_index[self.index])
try:
with open(sysfs_path, 'w') as file:
file.write(str(int(pwm)))
except IOError:
return False
return True
def set_status_led(self, color):
try:
fan_led_file = (FAN_PATH +
self.fan_e1031_led.format(self.index+1))
with open(fan_led_file, 'r') as file:
file.write(self.fan_e1031_led_col_map[color])
except IOError:
return False
return True

View File

@ -0,0 +1,23 @@
#!/usr/bin/env python
#############################################################################
# Celestica
#
# Module contains an implementation of SONiC Platform Base API and
# provides the platform information
#
#############################################################################
try:
from sonic_platform_base.platform_base import PlatformBase
from sonic_platform.chassis import Chassis
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Platform(PlatformBase):
"""Platform-specific Platform class"""
def __init__(self):
PlatformBase.__init__(self)
self._chassis = Chassis()

View File

@ -0,0 +1,109 @@
#!/usr/bin/env python
#############################################################################
# Celestica
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Chassis information which are available in the platform
#
#############################################################################
import sys
import re
import os
import subprocess
import json
try:
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.fan import Fan
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
BIOS_VERSION_PATH = "/sys/class/dmi/id/bios_version"
GETREG_PATH = "/sys/devices/platform/dx010_cpld/getreg"
CONFIG_DB_PATH = "/etc/sonic/config_db.json"
NUM_FAN = 5
CPLD_ADDR_MAPPING = {
"CPLD1": "0x100",
"CPLD2": "0x200",
"CPLD3": "0x280",
"CPLD4": "0x300",
"CPLD5": "0x380"
}
class Chassis(ChassisBase):
"""Platform-specific Chassis class"""
def __init__(self):
self.config_data = {}
for index in range(0, NUM_FAN):
fan = Fan(index)
self._fan_list.append(fan)
ChassisBase.__init__(self)
def __get_register_value(self, path, register):
cmd = "echo {1} > {0}; cat {0}".format(path, register)
p = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
raw_data, err = p.communicate()
if err is not '':
return 'None'
else:
return raw_data.strip()
def __read_config_db(self):
try:
with open(CONFIG_DB_PATH, 'r') as fd:
data = json.load(fd)
return data
except IOError:
raise IOError("Unable to open config_db file !")
def get_base_mac(self):
"""
Retrieves the base MAC address for the chassis
Returns:
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
try:
self.config_data = self.__read_config_db()
base_mac = self.config_data["DEVICE_METADATA"]["localhost"]["mac"]
return str(base_mac)
except KeyError:
raise KeyError("Base MAC not found")
def get_component_versions(self):
"""
Retrieves platform-specific hardware/firmware versions for chassis
componenets such as BIOS, CPLD, FPGA, etc.
Returns:
A string containing platform-specific component versions
"""
component_versions = dict()
# Get BIOS version
try:
with open(BIOS_VERSION_PATH, 'r') as fd:
bios_version = fd.read()
except IOError:
raise IOError("Unable to open version file !")
# Get CPLD version
cpld_version = dict()
for cpld_name in CPLD_ADDR_MAPPING:
try:
cpld_addr = CPLD_ADDR_MAPPING[cpld_name]
cpld_version_raw = self.__get_register_value(
GETREG_PATH, cpld_addr)
cpld_version_str = "{}.{}".format(int(cpld_version_raw[2], 16), int(
cpld_version_raw[3], 16)) if cpld_version_raw is not None else 'None'
cpld_version[cpld_name] = cpld_version_str
except Exception, e:
cpld_version[cpld_name] = 'None'
component_versions["CPLD"] = cpld_version
component_versions["BIOS"] = bios_version.strip()
return str(component_versions)

View File

@ -0,0 +1,228 @@
#!/usr/bin/env python
#############################################################################
# Celestica
#
# Module contains an implementation of SONiC Platform Base API and
# provides the fan status which are available in the platform
#
#############################################################################
import json
import math
import os.path
try:
from sonic_platform_base.fan_base import FanBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CONFIG_DB_PATH = "/etc/sonic/config_db.json"
EMC2305_PATH = "/sys/bus/i2c/drivers/emc2305/"
SYS_GPIO_DIR = "/sys/class/gpio"
EMC2305_MAX_PWM = 255
EMC2305_FAN_PWM = "pwm{}"
EMC2305_FAN_TARGET = "fan{}_target"
EMC2305_FAN_INPUT = "pwm{}"
class Fan(FanBase):
"""Platform-specific Fan class"""
def __init__(self, fan_index):
self.index = fan_index
self.config_data = {}
self.fan_speed = 0
FanBase.__init__(self)
# dx010 fan attributes
# Two EMC2305s located at i2c-13-4d and i2c-13-2e
# to control a dual-fan module.
self.dx010_emc2305_chip = [
{
'device': "13-002e",
'index_map': [2, 1, 4, 5, 3]
},
{
'device': "13-004d",
'index_map': [2, 4, 5, 3, 1]
}
]
self.dx010_fan_gpio = [
{'base': self.get_gpio_base()},
{'prs': 10, 'dir': 15, 'color': {'red': 31, 'green': 32}},
{'prs': 11, 'dir': 16, 'color': {'red': 29, 'green': 30}},
{'prs': 12, 'dir': 17, 'color': {'red': 35, 'green': 36}},
{'prs': 13, 'dir': 18, 'color': {'red': 37, 'green': 38}},
{'prs': 14, 'dir': 19, 'color': {'red': 33, 'green': 34}},
]
def get_gpio_base(self):
for r in os.listdir(SYS_GPIO_DIR):
if "gpiochip" in r:
return int(r[8:], 10)
return 216 # Reserve
def get_gpio_value(self, pinnum):
gpio_base = self.dx010_fan_gpio[0]['base']
gpio_dir = SYS_GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
gpio_file = gpio_dir + "/value"
try:
with open(gpio_file, 'r') as fd:
retval = fd.read()
except IOError:
raise IOError("Unable to open " + gpio_file + "file !")
retval = retval.rstrip('\r\n')
return retval
def set_gpio_value(self, pinnum, value=0):
gpio_base = self.dx010_fan_gpio[0]['base']
gpio_dir = SYS_GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
gpio_file = gpio_dir + "/value"
try:
with open(gpio_file, 'w') as fd:
retval = fd.write(str(value))
except IOError:
raise IOError("Unable to open " + gpio_file + "file !")
def get_direction(self):
direction = self.FAN_DIRECTION_INTAKE
raw = self.get_gpio_value(self.dx010_fan_gpio[self.index+1]['dir'])
if int(raw, 10) == 0:
direction = self.FAN_DIRECTION_INTAKE
else:
direction = self.FAN_DIRECTION_EXHAUST
return direction
def get_speed(self):
"""
DX010 platform specific data:
speed = pwm_in/255*100
"""
# TODO: Seperate PSU's fan and main fan class
if self.fan_speed != 0:
return self.fan_speed
else:
speed = 0
pwm = []
emc2305_chips = self.dx010_emc2305_chip
for chip in emc2305_chips:
device = chip['device']
fan_index = chip['index_map']
sysfs_path = "%s%s/%s" % (
EMC2305_PATH, device, EMC2305_FAN_INPUT)
sysfs_path = sysfs_path.format(fan_index[self.index])
try:
with open(sysfs_path, 'r') as file:
raw = file.read().strip('\r\n')
pwm.append(int(raw, 10))
except IOError:
raise IOError("Unable to open " + sysfs_path)
speed = math.ceil(
float(pwm[0]) * 100 / EMC2305_MAX_PWM)
return int(speed)
def get_target_speed(self):
"""
DX010 platform specific data:
speed_pc = pwm_target/255*100
0 : when PWM mode is use
pwm : when pwm mode is not use
"""
target = 0
pwm = []
emc2305_chips = self.dx010_emc2305_chip
for chip in emc2305_chips:
device = chip['device']
fan_index = chip['index_map']
sysfs_path = "%s%s/%s" % (
EMC2305_PATH, device, EMC2305_FAN_TARGET)
sysfs_path = sysfs_path.format(fan_index[self.index])
try:
with open(sysfs_path, 'r') as file:
raw = file.read().strip('\r\n')
pwm.append(int(raw, 10))
except IOError:
raise IOError("Unable to open " + sysfs_path)
target = pwm[0] * 100 / EMC2305_MAX_PWM
return target
def get_speed_tolerance(self):
"""
Retrieves the speed tolerance of the fan
Returns:
An integer, the percentage of variance from target speed which is
considered tolerable
"""
return 10
def set_speed(self, speed):
"""
Depends on pwm or target mode is selected:
1) pwm = speed_pc * 255 <-- Currently use this mode.
2) target_pwm = speed_pc * 100 / 255
2.1) set pwm{}_enable to 3
"""
pwm = speed * 255 / 100
emc2305_chips = self.dx010_emc2305_chip
for chip in emc2305_chips:
device = chip['device']
fan_index = chip['index_map']
sysfs_path = "%s%s/%s" % (
EMC2305_PATH, device, EMC2305_FAN_PWM)
sysfs_path = sysfs_path.format(fan_index[self.index])
try:
with open(sysfs_path, 'w') as file:
file.write(str(int(pwm)))
except IOError:
return False
return True
def set_status_led(self, color):
try:
if color == self.STATUS_LED_COLOR_GREEN:
self.set_gpio_value(
self.dx010_fan_gpio[self.index+1]['color']['red'], 1)
self.set_gpio_value(
self.dx010_fan_gpio[self.index+1]['color']['green'], 0)
elif color == self.STATUS_LED_COLOR_RED:
self.set_gpio_value(
self.dx010_fan_gpio[self.index+1]['color']['red'], 0)
self.set_gpio_value(
self.dx010_fan_gpio[self.index+1]['color']['green'], 1)
elif color == self.STATUS_LED_COLOR_OFF:
self.set_gpio_value(
self.dx010_fan_gpio[self.index+1]['color']['red'], 1)
self.set_gpio_value(
self.dx010_fan_gpio[self.index+1]['color']['green'], 1)
else:
return False
except IOError:
return False
return True

View File

@ -0,0 +1,23 @@
#!/usr/bin/env python
#############################################################################
# Celestica
#
# Module contains an implementation of SONiC Platform Base API and
# provides the platform information
#
#############################################################################
try:
from sonic_platform_base.platform_base import PlatformBase
from sonic_platform.chassis import Chassis
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Platform(PlatformBase):
"""Platform-specific Platform class"""
def __init__(self):
PlatformBase.__init__(self)
self._chassis = Chassis()

View File

@ -12,7 +12,8 @@
### END INIT INFO
function export_gpio {
label=$2
label=$3
gpio_dir=$2
gpio_num=$1
gpio_base=`( cat /sys/class/gpio/gpiochip*/base | head -1 ) 2>/dev/null`
gpio_label=`( cat /sys/class/gpio/gpiochip*/label | head -1 ) 2>/dev/null`
@ -27,6 +28,13 @@ if [ $? -ne 0 ]; then
echo "Platform driver error: Cannot export gpio$ionum!"
exit 1;
fi
if [[ "X$gpio_dir" != "X" ]]; then
echo $gpio_dir > /sys/class/gpio/gpio${ionum}/direction
if [ $? -ne 0 ]; then
echo "Platform driver error: Cannot set direction of gpio$ionum!"
exit 1;
fi
fi
}
case "$1" in
@ -95,27 +103,33 @@ start)
sleep 2
# Export platform gpio sysfs
export_gpio 10 # Fan 1 present
export_gpio 11 # Fan 2 present
export_gpio 12 # Fan 3 present
export_gpio 13 # Fan 4 present
export_gpio 14 # Fan 5 present
export_gpio 10 "in" # Fan 1 present
export_gpio 11 "in" # Fan 2 present
export_gpio 12 "in" # Fan 3 present
export_gpio 13 "in" # Fan 4 present
export_gpio 14 "in" # Fan 5 present
export_gpio 22 # PSU L PWOK
export_gpio 25 # PSU R PWOK
export_gpio 27 # PSU L ABS
export_gpio 28 # PSU R ABS
export_gpio 15 "in" # Fan 1 direction
export_gpio 16 "in" # Fan 2 direction
export_gpio 17 "in" # Fan 3 direction
export_gpio 18 "in" # Fan 4 direction
export_gpio 19 "in" # Fan 5 direction
export_gpio 29 # Fan 1 LED: Red
export_gpio 30 # Fan 1 LED: Yellow
export_gpio 31 # Fan 2 LED: Red
export_gpio 32 # Fan 2 LED: Yellow
export_gpio 33 # Fan 3 LED: Red
export_gpio 34 # Fan 3 LED: Yellow
export_gpio 35 # Fan 4 LED: Red
export_gpio 36 # Fan 4 LED: Yellow
export_gpio 37 # Fan 5 LED: Red
export_gpio 38 # Fan 5 LED: Yellow
export_gpio 22 "in" # PSU L PWOK
export_gpio 25 "in" # PSU R PWOK
export_gpio 27 "in" # PSU L ABS
export_gpio 28 "in" # PSU R ABS
export_gpio 29 "out" # Fan 1 LED: Red
export_gpio 30 "out" # Fan 1 LED: Yellow
export_gpio 31 "out" # Fan 2 LED: Red
export_gpio 32 "out" # Fan 2 LED: Yellow
export_gpio 33 "out" # Fan 3 LED: Red
export_gpio 34 "out" # Fan 3 LED: Yellow
export_gpio 35 "out" # Fan 4 LED: Red
export_gpio 36 "out" # Fan 4 LED: Yellow
export_gpio 37 "out" # Fan 5 LED: Red
export_gpio 38 "out" # Fan 5 LED: Yellow
# Turn off/down lpmod by defult (0 - Normal, 1 - Low Pow)
echo 0x00000000 > /sys/devices/platform/dx010_cpld/qsfp_lpmode

View File

@ -30,6 +30,13 @@
#define DRIVER_NAME "dx010_cpld"
#define CPLD1_VERSION_ADDR 0x100
#define CPLD2_VERSION_ADDR 0x200
#define CPLD3_VERSION_ADDR 0x280
#define CPLD4_VERSION_ADDR 0x300
#define CPLD5_VERSION_ADDR 0x380
#define RESET0108 0x250
#define RESET0910 0x251
#define RESET1118 0x2d0
@ -110,10 +117,36 @@ struct dx010_i2c_data {
struct dx010_cpld_data {
struct i2c_adapter *i2c_adapter[LENGTH_PORT_CPLD];
struct mutex cpld_lock;
uint16_t read_addr;
};
struct dx010_cpld_data *cpld_data;
static ssize_t getreg_store(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
uint16_t addr;
char *last;
addr = (uint16_t)strtoul(buf,&last,16);
if(addr == 0 && buf == last){
return -EINVAL;
}
cpld_data->read_addr = addr;
return count;
}
static ssize_t getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int len = 0;
mutex_lock(&cpld_data->cpld_lock);
len = sprintf(buf, "0x%2.2x\n",inb(cpld_data->read_addr));
mutex_unlock(&cpld_data->cpld_lock);
return len;
}
static ssize_t get_reset(struct device *dev, struct device_attribute *devattr,
char *buf)
{
@ -134,6 +167,47 @@ static ssize_t get_reset(struct device *dev, struct device_attribute *devattr,
return sprintf(buf,"0x%8.8lx\n", reset & 0xffffffff);
}
static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
uint16_t addr;
uint8_t value;
char *tok;
char clone[count];
char *pclone = clone;
char *last;
strcpy(clone, buf);
mutex_lock(&cpld_data->cpld_lock);
tok = strsep((char**)&pclone, " ");
if(tok == NULL){
mutex_unlock(&cpld_data->cpld_lock);
return -EINVAL;
}
addr = (uint16_t)strtoul(tok,&last,16);
if(addr == 0 && tok == last){
mutex_unlock(&cpld_data->cpld_lock);
return -EINVAL;
}
tok = strsep((char**)&pclone, " ");
if(tok == NULL){
mutex_unlock(&cpld_data->cpld_lock);
return -EINVAL;
}
value = (uint8_t)strtoul(tok,&last,16);
if(value == 0 && tok == last){
mutex_unlock(&cpld_data->cpld_lock);
return -EINVAL;
}
outb(value,addr);
mutex_unlock(&cpld_data->cpld_lock);
return count;
}
static ssize_t set_reset(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count)
{
@ -248,12 +322,16 @@ static ssize_t get_modirq(struct device *dev, struct device_attribute *devattr,
return sprintf(buf,"0x%8.8lx\n", irq & 0xffffffff);
}
static DEVICE_ATTR_RW(getreg);
static DEVICE_ATTR_WO(setreg);
static DEVICE_ATTR(qsfp_reset, S_IRUGO | S_IWUSR, get_reset, set_reset);
static DEVICE_ATTR(qsfp_lpmode, S_IRUGO | S_IWUSR, get_lpmode, set_lpmode);
static DEVICE_ATTR(qsfp_modprs, S_IRUGO, get_modprs, NULL);
static DEVICE_ATTR(qsfp_modirq, S_IRUGO, get_modirq, NULL);
static struct attribute *dx010_lpc_attrs[] = {
&dev_attr_getreg.attr,
&dev_attr_setreg.attr,
&dev_attr_qsfp_reset.attr,
&dev_attr_qsfp_lpmode.attr,
&dev_attr_qsfp_modprs.attr,
@ -499,6 +577,7 @@ static int cel_dx010_lpc_drv_probe(struct platform_device *pdev)
return -ENOMEM;
mutex_init(&cpld_data->cpld_lock);
cpld_data->read_addr = CPLD1_VERSION_ADDR;
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (unlikely(!res)) {
@ -558,4 +637,4 @@ module_exit(cel_dx010_lpc_exit);
MODULE_AUTHOR("Abhisit Sangjan <asang@celestica.com>");
MODULE_AUTHOR("Pariwat Leamsumran <pleamsum@celestica.com>");
MODULE_DESCRIPTION("Celestica SeaStone DX010 LPC Driver");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL");