Platform Driver Developement Framework (PDDF) (#4756)
This change introduces PDDF which is described here: https://github.com/Azure/SONiC/pull/536 Most of the platform bring up effort goes in developing the platform device drivers, SONiC platform APIs and validating them. Typically each platform vendor writes their own drivers and platform APIs which is very tailor made to that platform. This involves writing code, building, installing it on the target platform devices and testing. Many of the details of the platform are hard coded into these drivers, from the HW spec. They go through this cycle repetitively till everything works fine, and is validated before upstreaming the code. PDDF aims to make this platform driver and platform APIs development process much simpler by providing a data driven development framework. This is enabled by: JSON descriptor files for platform data Generic data-driven drivers for various devices Generic SONiC platform APIs Vendor specific extensions for customisation and extensibility Signed-off-by: Fuzail Khan <fuzail.khan@broadcom.com>
This commit is contained in:
parent
8d8ed89778
commit
a3dd3f55f9
@ -277,6 +277,7 @@ sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y in
|
||||
python \
|
||||
python-setuptools \
|
||||
python3-setuptools \
|
||||
python-jsonschema \
|
||||
python-apt \
|
||||
traceroute \
|
||||
iputils-ping \
|
||||
|
27
device/common/pddf/plugins/eeprom.py
Executable file
27
device/common/pddf/plugins/eeprom.py
Executable file
@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
try:
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
sys.path.append('/usr/share/sonic/platform/plugins')
|
||||
import pddfparse
|
||||
#from sonic_eeprom import eeprom_base
|
||||
from sonic_eeprom import eeprom_tlvinfo
|
||||
except ImportError, e:
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
|
||||
class board(eeprom_tlvinfo.TlvInfoDecoder):
|
||||
_TLV_INFO_MAX_LEN = 256
|
||||
def __init__(self, name, path, cpld_root, ro):
|
||||
global pddf_obj
|
||||
global plugin_data
|
||||
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd:
|
||||
plugin_data = json.load(pd)
|
||||
|
||||
pddf_obj = pddfparse.PddfParse()
|
||||
# system EEPROM always has device name EEPROM1
|
||||
self.eeprom_path = pddf_obj.get_path("EEPROM1", "eeprom")
|
||||
super(board, self).__init__(self.eeprom_path, 0, '', True)
|
||||
|
202
device/common/pddf/plugins/fanutil.py
Executable file
202
device/common/pddf/plugins/fanutil.py
Executable file
@ -0,0 +1,202 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
|
||||
# Sample pddf_fanutil file
|
||||
# All the supported FAN SysFS aattributes are
|
||||
#- fan<idx>_present
|
||||
#- fan<idx>_direction
|
||||
#- fan<idx>_input
|
||||
#- fan<idx>_pwm
|
||||
#- fan<idx>_fault
|
||||
# where idx is in the range [1-12]
|
||||
#
|
||||
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
sys.path.append('/usr/share/sonic/platform/plugins')
|
||||
import pddfparse
|
||||
import json
|
||||
|
||||
try:
|
||||
from sonic_fan.fan_base import FanBase
|
||||
except ImportError as e:
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
class FanUtil(FanBase):
|
||||
"""PDDF generic FAN util class"""
|
||||
|
||||
def __init__(self):
|
||||
FanBase.__init__(self)
|
||||
global pddf_obj
|
||||
global plugin_data
|
||||
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd:
|
||||
plugin_data = json.load(pd)
|
||||
|
||||
pddf_obj = pddfparse.PddfParse()
|
||||
self.platform = pddf_obj.get_platform()
|
||||
|
||||
self.num_fans = (self.platform['num_fantrays'] * self.platform['num_fans_pertray'] )
|
||||
|
||||
def get_num_fans(self):
|
||||
return self.num_fans
|
||||
|
||||
def get_presence(self, idx):
|
||||
# 1 based fan index
|
||||
if idx<1 or idx>self.num_fans:
|
||||
print "Invalid fan index %d\n"%idx
|
||||
return False
|
||||
|
||||
attr_name = "fan"+ str(idx) +"_present"
|
||||
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr_name)
|
||||
if not output:
|
||||
return False
|
||||
|
||||
mode = output['mode']
|
||||
presence = output['status'].rstrip()
|
||||
|
||||
vmap = plugin_data['FAN']['present'][mode]['valmap']
|
||||
|
||||
if presence in vmap:
|
||||
status = vmap[presence]
|
||||
else:
|
||||
status = False
|
||||
|
||||
return status
|
||||
|
||||
def get_status(self, idx):
|
||||
# 1 based fan index
|
||||
if idx<1 or idx>self.num_fans:
|
||||
print "Invalid fan index %d\n"%idx
|
||||
return False
|
||||
|
||||
speed = self.get_speed(idx)
|
||||
status = True if (speed != 0) else False
|
||||
return status
|
||||
|
||||
def get_direction(self, idx):
|
||||
# 1 based fan index
|
||||
if idx<1 or idx>self.num_fans:
|
||||
print "Invalid fan index %d\n"%idx
|
||||
return None
|
||||
|
||||
attr = "fan" + str(idx) + "_direction"
|
||||
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr)
|
||||
if not output:
|
||||
return None
|
||||
|
||||
mode = output['mode']
|
||||
val = output['status']
|
||||
|
||||
val = val.rstrip()
|
||||
vmap = plugin_data['FAN']['direction'][mode]['valmap']
|
||||
|
||||
|
||||
if val in vmap:
|
||||
direction = vmap[val]
|
||||
else:
|
||||
direction = val
|
||||
|
||||
return direction
|
||||
|
||||
def get_directions(self):
|
||||
num_fan = self.get_num_fan();
|
||||
|
||||
for i in range(1, num_fan+1):
|
||||
attr = "fan" + str(i) + "_direction"
|
||||
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr)
|
||||
if not output:
|
||||
return None
|
||||
|
||||
mode = output['mode']
|
||||
val = output['status']
|
||||
|
||||
val = val.rstrip()
|
||||
vmap = plugin_data['FAN']['direction'][mode]['valmap']
|
||||
|
||||
direction = vmap[str(val)]
|
||||
|
||||
print "FAN-%d direction is %s"%(i, direction)
|
||||
|
||||
return 0
|
||||
|
||||
def get_speed(self, idx):
|
||||
# 1 based fan index
|
||||
if idx<1 or idx>self.num_fans:
|
||||
print "Invalid fan index %d\n"%idx
|
||||
return 0
|
||||
|
||||
attr = "fan" + str(idx) + "_input"
|
||||
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr)
|
||||
if not output:
|
||||
return 0
|
||||
|
||||
#mode = output['mode']
|
||||
val = output['status'].rstrip()
|
||||
|
||||
if val.isalpha():
|
||||
return 0
|
||||
else:
|
||||
rpm_speed = int(float(val))
|
||||
|
||||
return rpm_speed
|
||||
|
||||
def get_speeds(self):
|
||||
num_fan = self.get_num_fan();
|
||||
ret = "FAN_INDEX\t\tRPM\n"
|
||||
|
||||
for i in range(1, num_fan+1):
|
||||
attr1 = "fan" + str(i) + "_input"
|
||||
output = pddf_obj.get_attr_name_output("FAN-CTRL", attr1)
|
||||
if not output:
|
||||
return ""
|
||||
|
||||
#mode = output['mode']
|
||||
val = output['status'].rstrip()
|
||||
|
||||
if val.isalpha():
|
||||
frpm = 0
|
||||
else:
|
||||
frpm = int(val)
|
||||
|
||||
ret += "FAN-%d\t\t\t%d\n"%(i, frpm)
|
||||
|
||||
return ret
|
||||
|
||||
def set_speed(self, val):
|
||||
if val<0 or val>100:
|
||||
print "Error: Invalid speed %d. Please provide a valid speed percentage"%val
|
||||
return False
|
||||
|
||||
num_fan = self.num_fans
|
||||
if 'duty_cycle_to_pwm' not in plugin_data['FAN']:
|
||||
print "Setting fan speed is not allowed !"
|
||||
return False
|
||||
else:
|
||||
duty_cycle_to_pwm = eval(plugin_data['FAN']['duty_cycle_to_pwm'])
|
||||
pwm = duty_cycle_to_pwm(val)
|
||||
print "New Speed: %d%% - PWM value to be set is %d\n"%(val,pwm)
|
||||
|
||||
for i in range(1, num_fan+1):
|
||||
attr = "fan" + str(i) + "_pwm"
|
||||
node = pddf_obj.get_path("FAN-CTRL", attr)
|
||||
if node is None:
|
||||
return False
|
||||
try:
|
||||
with open(node, 'w') as f:
|
||||
f.write(str(pwm))
|
||||
except IOError:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def dump_sysfs(self):
|
||||
return pddf_obj.cli_dump_dsysfs('fan')
|
||||
|
||||
def get_change_event(self):
|
||||
"""
|
||||
TODO: This function need to be implemented
|
||||
when decide to support monitoring FAN(fand)
|
||||
on this platform.
|
||||
"""
|
||||
raise NotImplementedError
|
58
device/common/pddf/plugins/ledutil.py
Executable file
58
device/common/pddf/plugins/ledutil.py
Executable file
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
sys.path.append('/usr/share/sonic/platform/plugins')
|
||||
import pddfparse
|
||||
|
||||
class LedUtil:
|
||||
color_map = {
|
||||
"STATUS_LED_COLOR_GREEN" : "on",
|
||||
"STATUS_LED_COLOR_RED" : "faulty",
|
||||
"STATUS_LED_COLOR_OFF" : "off"
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
global pddf_obj
|
||||
pddf_obj = pddfparse.PddfParse()
|
||||
self.path="pddf/devices/led"
|
||||
self.cur_state_path="pddf/devices/led/cur_state"
|
||||
|
||||
def set_status_led(self, led_device_name, color, color_state="SOLID"):
|
||||
if (not led_device_name in pddf_obj.data.keys()):
|
||||
status="ERROR: " + led_device_name + " is not configured"
|
||||
return (status)
|
||||
|
||||
if (not color in self.color_map.keys()):
|
||||
status="ERROR: Invalid color"
|
||||
return (status)
|
||||
|
||||
index=pddf_obj.data[led_device_name]['dev_attr']['index']
|
||||
pddf_obj.create_attr('device_name', led_device_name, self.path)
|
||||
pddf_obj.create_attr('index', index, self.path)
|
||||
pddf_obj.create_attr('color', self.color_map[color], self.cur_state_path)
|
||||
pddf_obj.create_attr('color_state', color_state, self.cur_state_path)
|
||||
pddf_obj.create_attr('dev_ops', 'set_status', self.path)
|
||||
return ("Executed")
|
||||
|
||||
def get_status_led(self, led_device_name):
|
||||
if (not led_device_name in pddf_obj.data.keys()):
|
||||
status="ERROR: " + led_device_name + " is not configured"
|
||||
return (status)
|
||||
|
||||
index=pddf_obj.data[led_device_name]['dev_attr']['index']
|
||||
pddf_obj.create_attr('device_name', led_device_name, self.path)
|
||||
pddf_obj.create_attr('index', index, self.path)
|
||||
pddf_obj.create_attr('dev_ops', 'get_status', self.path)
|
||||
color_f="/sys/kernel/" + self.cur_state_path +"/color"
|
||||
color_state_f="/sys/kernel/" + self.cur_state_path +"/color_state"
|
||||
|
||||
try:
|
||||
with open(color_f, 'r') as f:
|
||||
color = f.read().strip("\r\n")
|
||||
with open(color_state_f, 'r') as f:
|
||||
color_state = f.read().strip("\r\n")
|
||||
except IOError:
|
||||
status="ERROR :" + color_f + " open failed"
|
||||
return (status)
|
||||
status = "%s-%s:\t%s %s\n"%(led_device_name, index, color, color_state)
|
||||
return (status)
|
272
device/common/pddf/plugins/psuutil.py
Executable file
272
device/common/pddf/plugins/psuutil.py
Executable file
@ -0,0 +1,272 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Sample pddf_psuutil file
|
||||
#
|
||||
# All the supported PSU SysFS aattributes are
|
||||
#- psu_present
|
||||
#- psu_model_name
|
||||
#- psu_power_good
|
||||
#- psu_mfr_id
|
||||
#- psu_serial_num
|
||||
#- psu_fan_dir
|
||||
#- psu_v_out
|
||||
#- psu_i_out
|
||||
#- psu_p_out
|
||||
#- psu_fan1_speed_rpm
|
||||
#
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
sys.path.append('/usr/share/sonic/platform/plugins')
|
||||
import pddfparse
|
||||
import json
|
||||
|
||||
try:
|
||||
from sonic_psu.psu_base import PsuBase
|
||||
except ImportError as e:
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
|
||||
class PsuUtil(PsuBase):
|
||||
"""PDDF generic PSU util class"""
|
||||
|
||||
def __init__(self):
|
||||
PsuBase.__init__(self)
|
||||
global pddf_obj
|
||||
global plugin_data
|
||||
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd:
|
||||
plugin_data = json.load(pd)
|
||||
|
||||
pddf_obj = pddfparse.PddfParse()
|
||||
self.platform = pddf_obj.get_platform()
|
||||
|
||||
def get_num_psus(self):
|
||||
return int(self.platform['num_psus'])
|
||||
|
||||
def get_psu_status(self, index):
|
||||
if index is None:
|
||||
return False
|
||||
|
||||
device = "PSU" + "%d"%index
|
||||
output = pddf_obj.get_attr_name_output(device, "psu_power_good")
|
||||
if not output:
|
||||
return False
|
||||
|
||||
mode = output['mode']
|
||||
val = output['status']
|
||||
|
||||
val = val.rstrip()
|
||||
vmap = plugin_data['PSU']['psu_power_good'][mode]['valmap']
|
||||
|
||||
if val in vmap:
|
||||
return vmap[val]
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_psu_presence(self, index):
|
||||
if index is None:
|
||||
return False
|
||||
|
||||
status = 0
|
||||
device = "PSU" + "%d"%index
|
||||
output = pddf_obj.get_attr_name_output(device, "psu_present")
|
||||
if not output:
|
||||
return False
|
||||
|
||||
mode = output['mode']
|
||||
status = output['status']
|
||||
|
||||
vmap = plugin_data['PSU']['psu_present'][mode]['valmap']
|
||||
|
||||
if status.rstrip('\n') in vmap:
|
||||
return vmap[status.rstrip('\n')]
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_powergood_status(self, idx):
|
||||
if idx is None:
|
||||
return False
|
||||
|
||||
if idx<1 or idx>self.platform['num_psus']:
|
||||
print "Invalid index %d\n"%idx
|
||||
return False
|
||||
|
||||
device = "PSU"+"%d"%(idx)
|
||||
output = pddf_obj.get_attr_name_output(device, "psu_power_good")
|
||||
if not output:
|
||||
return False
|
||||
|
||||
mode = output['mode']
|
||||
status = output ['status']
|
||||
|
||||
vmap = plugin_data['PSU']['psu_power_good'][mode]['valmap']
|
||||
|
||||
if status.rstrip('\n') in vmap:
|
||||
return vmap[status.rstrip('\n')]
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_model(self, idx):
|
||||
if idx is None:
|
||||
return None
|
||||
|
||||
if idx<1 or idx>self.platform['num_psus']:
|
||||
print "Invalid index %d\n"%idx
|
||||
return None
|
||||
|
||||
device = "PSU"+"%d"%(idx)
|
||||
output = pddf_obj.get_attr_name_output(device, "psu_model_name")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
model = output['status']
|
||||
|
||||
# strip_non_ascii
|
||||
stripped = (c for c in model if 0 < ord(c) < 127)
|
||||
model = ''.join(stripped)
|
||||
|
||||
return model.rstrip('\n')
|
||||
|
||||
def get_mfr_id(self, idx):
|
||||
if idx is None:
|
||||
return None
|
||||
|
||||
if idx<1 or idx>self.platform['num_psus']:
|
||||
print "Invalid index %d\n"%idx
|
||||
return None
|
||||
|
||||
device = "PSU"+"%d"%(idx)
|
||||
output = pddf_obj.get_attr_name_output(device, "psu_mfr_id")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
mfr = output['status']
|
||||
|
||||
return mfr.rstrip('\n')
|
||||
|
||||
def get_serial(self, idx):
|
||||
if idx is None:
|
||||
return None
|
||||
|
||||
if idx<1 or idx>self.platform['num_psus']:
|
||||
print "Invalid index %d\n"%idx
|
||||
return None
|
||||
|
||||
device = "PSU"+"%d"%(idx)
|
||||
output = pddf_obj.get_attr_name_output(device, "psu_serial_num")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
serial = output['status']
|
||||
|
||||
return serial.rstrip('\n')
|
||||
|
||||
def get_direction(self, idx):
|
||||
if idx is None:
|
||||
return None
|
||||
|
||||
if idx<1 or idx>self.platform['num_psus']:
|
||||
print "Invalid index %d\n"%idx
|
||||
return None
|
||||
|
||||
device = "PSU"+"%d"%(idx)
|
||||
output = pddf_obj.get_attr_name_output(device, "psu_fan_dir")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
mode = output['mode']
|
||||
direction = output['status'].rstrip('\n')
|
||||
|
||||
vmap = plugin_data['PSU']['psu_fan_dir'][mode]['valmap']
|
||||
if direction in vmap:
|
||||
airflow_dir_real = vmap[direction]
|
||||
else:
|
||||
airflow_dir_real = direction
|
||||
|
||||
return airflow_dir_real
|
||||
|
||||
def get_output_voltage(self, idx):
|
||||
if idx is None:
|
||||
return 0.0
|
||||
|
||||
if idx<1 or idx>self.platform['num_psus']:
|
||||
print "Invalid index %d\n"%idx
|
||||
return 0.0
|
||||
|
||||
device = "PSU"+"%d"%(idx)
|
||||
output = pddf_obj.get_attr_name_output(device, "psu_v_out")
|
||||
if not output:
|
||||
return 0.0
|
||||
|
||||
v_out = output['status']
|
||||
|
||||
# value returned by the psu driver is in mV
|
||||
return float(v_out)/1000
|
||||
|
||||
def get_output_current(self, idx):
|
||||
if idx is None:
|
||||
return 0.0
|
||||
|
||||
if idx<1 or idx>self.platform['num_psus']:
|
||||
print "Invalid index %d\n"%idx
|
||||
return 0.0
|
||||
|
||||
device = "PSU"+"%d"%(idx)
|
||||
output = pddf_obj.get_attr_name_output(device, "psu_i_out")
|
||||
if not output:
|
||||
return 0.0
|
||||
|
||||
i_out = output['status']
|
||||
|
||||
# current in mA
|
||||
return float(i_out)/1000
|
||||
|
||||
def get_output_power(self, idx):
|
||||
if idx is None:
|
||||
return 0.0
|
||||
|
||||
if idx<1 or idx>self.platform['num_psus']:
|
||||
print "Invalid index %d\n"%idx
|
||||
return 0.0
|
||||
|
||||
device = "PSU"+"%d"%(idx)
|
||||
output = pddf_obj.get_attr_name_output(device, "psu_p_out")
|
||||
if not output:
|
||||
return 0.0
|
||||
|
||||
p_out = output['status']
|
||||
|
||||
# power is returned in micro watts
|
||||
return float(p_out)/1000000
|
||||
|
||||
def get_fan_rpm(self, idx, fan_idx):
|
||||
if idx is None or fan_idx is None:
|
||||
return 0
|
||||
|
||||
if idx<1 or idx>self.platform['num_psus']:
|
||||
print "Invalid index %d\n"%idx
|
||||
return 0
|
||||
|
||||
|
||||
device = "PSU"+"%d"%(idx)
|
||||
num_fans = pddf_obj.get_num_psu_fans(device)
|
||||
|
||||
if fan_idx<1 or fan_idx>num_fans:
|
||||
print "Invalid PSU-fan index %d\n"%fan_idx
|
||||
return 0
|
||||
|
||||
output = pddf_obj.get_attr_name_output(device, "psu_fan"+str(fan_idx)+"_speed_rpm")
|
||||
if not output:
|
||||
return 0
|
||||
|
||||
#mode = output['mode']
|
||||
output['status'] = output['status'].rstrip()
|
||||
if output['status'].isalpha():
|
||||
return 0
|
||||
else:
|
||||
speed = int(output['status'])
|
||||
|
||||
return speed
|
||||
|
||||
def dump_sysfs(self):
|
||||
return pddf_obj.cli_dump_dsysfs('psu')
|
237
device/common/pddf/plugins/sfputil.py
Executable file
237
device/common/pddf/plugins/sfputil.py
Executable file
@ -0,0 +1,237 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
sys.path.append('/usr/share/sonic/platform/plugins')
|
||||
import pddfparse
|
||||
import json
|
||||
|
||||
try:
|
||||
import time
|
||||
from ctypes import create_string_buffer
|
||||
from sonic_sfp.sfputilbase import SfpUtilBase
|
||||
except ImportError, e:
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
class SfpUtil(SfpUtilBase):
|
||||
"""Platform generic PDDF SfpUtil class"""
|
||||
|
||||
_port_to_eeprom_mapping = {}
|
||||
_port_start = 0
|
||||
_port_end = 0
|
||||
_port_to_type_mapping = {}
|
||||
_qsfp_ports = []
|
||||
_sfp_ports = []
|
||||
|
||||
def __init__(self):
|
||||
SfpUtilBase.__init__(self)
|
||||
global pddf_obj
|
||||
global plugin_data
|
||||
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd:
|
||||
plugin_data = json.load(pd)
|
||||
|
||||
pddf_obj = pddfparse.PddfParse()
|
||||
self.platform = pddf_obj.get_platform()
|
||||
self._port_start = 0
|
||||
self._port_end = self.get_num_ports()
|
||||
|
||||
for port_num in range(self._port_start, self._port_end):
|
||||
device = "PORT" + "%d"%(port_num+1)
|
||||
port_eeprom_path = pddf_obj.get_path(device,"eeprom")
|
||||
self._port_to_eeprom_mapping[port_num] = port_eeprom_path
|
||||
port_type = pddf_obj.get_device_type(device)
|
||||
self._port_to_type_mapping[port_num] = port_type
|
||||
self.populate_port_type(port_num)
|
||||
|
||||
def get_num_ports(self):
|
||||
return int(self.platform['num_ports'])
|
||||
|
||||
def is_valid_port(self, port_num):
|
||||
if port_num < self._port_start or port_num > self._port_end:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def get_presence(self, port_num):
|
||||
if port_num < self._port_start or port_num > self._port_end:
|
||||
return False
|
||||
|
||||
device = "PORT" + "%d"%(port_num+1)
|
||||
output = pddf_obj.get_attr_name_output(device, 'xcvr_present')
|
||||
if not output:
|
||||
return False
|
||||
|
||||
#mode = output['mode']
|
||||
modpres = output['status'].rstrip()
|
||||
if 'XCVR' in plugin_data:
|
||||
if 'xcvr_present' in plugin_data['XCVR']:
|
||||
ptype = self._port_to_type_mapping[port_num]
|
||||
vtype = 'valmap-'+ptype
|
||||
if vtype in plugin_data['XCVR']['xcvr_present']:
|
||||
vmap = plugin_data['XCVR']['xcvr_present'][vtype]
|
||||
if modpres in vmap:
|
||||
return vmap[modpres]
|
||||
else:
|
||||
return False
|
||||
# if plugin_data doesn't specify anything regarding Transceivers
|
||||
if modpres == '1':
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def populate_port_type(self, port):
|
||||
if self._port_to_type_mapping[port] == 'QSFP' or self._port_to_type_mapping[port] == 'QSFP28':
|
||||
self._qsfp_ports.append(port)
|
||||
elif self._port_to_type_mapping[port] == 'SFP' or self._port_to_type_mapping[port] == 'SFP28':
|
||||
self._sfp_ports.append(port)
|
||||
|
||||
@property
|
||||
def port_start(self):
|
||||
return self._port_start
|
||||
|
||||
@property
|
||||
def port_end(self):
|
||||
return (self._port_end - 1)
|
||||
|
||||
@property
|
||||
def port_to_eeprom_mapping(self):
|
||||
return self._port_to_eeprom_mapping
|
||||
|
||||
@property
|
||||
def qsfp_ports(self):
|
||||
return self._qsfp_ports
|
||||
|
||||
def reset(self, port_num):
|
||||
if port_num < self._port_start or port_num > self._port_end:
|
||||
return False
|
||||
|
||||
device = "PORT" + "%d"%(port_num+1)
|
||||
port_ps = pddf_obj.get_path(device,"xcvr_reset")
|
||||
if port_ps is None:
|
||||
return False
|
||||
|
||||
try:
|
||||
reg_file = open(port_ps, 'w')
|
||||
except IOError as e:
|
||||
print "Error: unable to open file: %s" % str(e)
|
||||
return False
|
||||
|
||||
try:
|
||||
reg_file.seek(0)
|
||||
reg_file.write('1')
|
||||
time.sleep(1)
|
||||
reg_file.seek(0)
|
||||
reg_file.write('0')
|
||||
reg_file.close()
|
||||
return True
|
||||
except IOError as e:
|
||||
return False
|
||||
|
||||
def get_low_power_mode(self, port_num):
|
||||
# Check for invalid port_num
|
||||
if port_num < self._port_start or port_num > self._port_end:
|
||||
return False
|
||||
|
||||
if not self.get_presence(port_num):
|
||||
return False
|
||||
|
||||
device = "PORT" + "%d"%(port_num+1)
|
||||
output = pddf_obj.get_attr_name_output(device, 'xcvr_lpmode')
|
||||
if not output:
|
||||
if port_num not in self.qsfp_ports:
|
||||
return False # Read from eeprom only for QSFP ports
|
||||
try:
|
||||
eeprom = None
|
||||
eeprom = open(self.port_to_eeprom_mapping[port_num], "rb")
|
||||
# check for valid connector type
|
||||
eeprom.seek(2)
|
||||
ctype = eeprom.read(1)
|
||||
if ctype in ['21','23']:
|
||||
return False
|
||||
|
||||
eeprom.seek(93)
|
||||
lpmode = ord(eeprom.read(1))
|
||||
|
||||
if ((lpmode & 0x3) == 0x3):
|
||||
return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1
|
||||
else:
|
||||
return False # High Power Mode if one of the following conditions is matched:
|
||||
# 1. "Power override" bit is 0
|
||||
# 2. "Power override" bit is 1 and "Power set" bit is 0
|
||||
except IOError as e:
|
||||
print "Error: unable to open file: %s" % str(e)
|
||||
return False
|
||||
finally:
|
||||
if eeprom is not None:
|
||||
eeprom.close()
|
||||
time.sleep(0.01)
|
||||
else:
|
||||
#mode = output['mode']
|
||||
status = int(output['status'].rstrip())
|
||||
|
||||
if status == 1:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def set_low_power_mode(self, port_num, lpmode):
|
||||
# Check for invalid port_num
|
||||
if port_num < self._port_start or port_num > self._port_end:
|
||||
return False
|
||||
|
||||
if not self.get_presence(port_num):
|
||||
return False # Port is not present, unable to set the eeprom
|
||||
|
||||
device = "PORT" + "%d"%(port_num+1)
|
||||
port_ps = pddf_obj.get_path(device,"xcvr_lpmode")
|
||||
if port_ps is None:
|
||||
if port_num not in self.qsfp_ports:
|
||||
return False # Write to eeprom only for QSFP ports
|
||||
try:
|
||||
eeprom = None
|
||||
eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b")
|
||||
# check for valid connector type
|
||||
eeprom.seek(2)
|
||||
ctype = eeprom.read(1)
|
||||
if ctype in ['21','23']:
|
||||
return False
|
||||
|
||||
# Fill in write buffer
|
||||
regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode
|
||||
buffer = create_string_buffer(1)
|
||||
buffer[0] = chr(regval)
|
||||
|
||||
# Write to eeprom
|
||||
eeprom.seek(93)
|
||||
eeprom.write(buffer[0])
|
||||
return True
|
||||
except IOError as e:
|
||||
print "Error: unable to open file: %s" % str(e)
|
||||
return False
|
||||
finally:
|
||||
if eeprom is not None:
|
||||
eeprom.close()
|
||||
time.sleep(0.01)
|
||||
else:
|
||||
try:
|
||||
f = open(port_ps, 'w')
|
||||
if lpmode:
|
||||
f.write('1')
|
||||
else:
|
||||
f.write('0')
|
||||
f.close()
|
||||
return True
|
||||
except IOError as e:
|
||||
return False
|
||||
|
||||
def get_transceiver_change_event(self):
|
||||
"""
|
||||
TODO: This function need to be implemented
|
||||
when decide to support monitoring SFP(Xcvrd)
|
||||
on this platform.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def dump_sysfs(self):
|
||||
return pddf_obj.cli_dump_dsysfs('xcvr')
|
85
device/common/pddf/plugins/sysstatutil.py
Executable file
85
device/common/pddf/plugins/sysstatutil.py
Executable file
@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
sys.path.append('/usr/share/sonic/platform/plugins')
|
||||
import pddfparse
|
||||
import json
|
||||
|
||||
class SYSStatusUtil():
|
||||
"""Platform-specific SYSStatus class"""
|
||||
def __init__(self):
|
||||
global pddf_obj
|
||||
global plugin_data
|
||||
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd:
|
||||
plugin_data = json.load(pd)
|
||||
|
||||
pddf_obj = pddfparse.PddfParse()
|
||||
|
||||
def get_board_info(self):
|
||||
device = "SYSSTATUS"
|
||||
node = pddf_obj.get_path(device,"board_info")
|
||||
if node is None:
|
||||
return False
|
||||
try:
|
||||
with open(node, 'r') as f:
|
||||
status = f.read()
|
||||
print "board_info : %s" %status
|
||||
except IOError:
|
||||
return False
|
||||
|
||||
def get_cpld_versio(self):
|
||||
device = "SYSSTATUS"
|
||||
node = pddf_obj.get_path(device,"cpld1_version")
|
||||
if node is None:
|
||||
return False
|
||||
try:
|
||||
with open(node, 'r') as f:
|
||||
status = f.read()
|
||||
print "cpld1_version : %s" %status
|
||||
except IOError:
|
||||
return False
|
||||
|
||||
def get_power_module_status(self):
|
||||
device = "SYSSTATUS"
|
||||
node = pddf_obj.get_path(device,"power_module_status")
|
||||
if node is None:
|
||||
return False
|
||||
try:
|
||||
with open(node, 'r') as f:
|
||||
status = f.read()
|
||||
print "power_module_status : %s" %status
|
||||
except IOError:
|
||||
return False
|
||||
|
||||
|
||||
def get_system_reset_status(self):
|
||||
device = "SYSSTATUS"
|
||||
for i in range(1,8):
|
||||
node = pddf_obj.get_path(device,"system_reset"+str(i))
|
||||
if node is None:
|
||||
return False
|
||||
try:
|
||||
with open(node, 'r') as f:
|
||||
status = f.read()
|
||||
print "system_reset%s : %s" %(i, status)
|
||||
except IOError:
|
||||
print "system_reset%s not supported" %i
|
||||
|
||||
|
||||
def get_misc_status(self):
|
||||
device = "SYSSTATUS"
|
||||
for i in range(1,3):
|
||||
node = pddf_obj.get_path(device,"misc"+str(i))
|
||||
if node is None:
|
||||
return False
|
||||
try:
|
||||
with open(node, 'r') as f:
|
||||
status = f.read()
|
||||
print "misc%s : %s" %(i, status)
|
||||
except IOError:
|
||||
print "system_reset%s not supported" %i
|
||||
|
||||
|
||||
def dump_sysfs(self):
|
||||
return pddf_obj.cli_dump_dsysfs('sys-status')
|
74
device/common/pddf/plugins/thermalutil.py
Executable file
74
device/common/pddf/plugins/thermalutil.py
Executable file
@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
import json
|
||||
sys.path.append('/usr/share/sonic/platform/plugins')
|
||||
import pddfparse
|
||||
|
||||
class ThermalUtil:
|
||||
def __init__(self):
|
||||
global pddf_obj
|
||||
global plugin_data
|
||||
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)) + '/../pddf/pd-plugin.json')) as pd:
|
||||
plugin_data = json.load(pd)
|
||||
|
||||
pddf_obj = pddfparse.PddfParse()
|
||||
self.platform = pddf_obj.get_platform()
|
||||
self.num_thermals = self.platform['num_temps']
|
||||
self.info=[]
|
||||
|
||||
def get_num_thermals(self):
|
||||
return (self.num_thermals)
|
||||
|
||||
def get_thermal_info(self):
|
||||
list=[]
|
||||
pddf_obj.get_device_list(list, "TEMP_SENSOR")
|
||||
list.sort()
|
||||
for dev in list:
|
||||
data={}
|
||||
device_name = dev['dev_info']['device_name']
|
||||
topo_info = dev['i2c']['topo_info']
|
||||
label="%s-i2c-%d-%x" % (topo_info['dev_type'], int(topo_info['parent_bus'], 0), int(topo_info['dev_addr'], 0))
|
||||
attr_list = dev['i2c']['attr_list']
|
||||
data['device_name']=device_name
|
||||
data['label']=label
|
||||
for attr in attr_list:
|
||||
attr_name = attr['attr_name']
|
||||
node = pddf_obj.get_path(device_name, attr_name)
|
||||
if node is None:
|
||||
return False
|
||||
try:
|
||||
with open(node, 'r') as f:
|
||||
attr_value = int(f.read())
|
||||
except IOError:
|
||||
return False
|
||||
data[attr_name] = attr_value/float(1000)
|
||||
self.info.append(data)
|
||||
|
||||
def show_thermal_temp_values(self, idx):
|
||||
if idx<1 or idx>self.num_thermals:
|
||||
print "Invalid temperature sensor idx %d"%idx
|
||||
return None
|
||||
self.get_thermal_info()
|
||||
thermal_name = "TEMP"+"%d"%idx
|
||||
label=""
|
||||
value=""
|
||||
for temp in self.info:
|
||||
if thermal_name==temp['device_name']:
|
||||
label = temp['label']
|
||||
value = "temp1\t %+.1f C (high = %+.1f C, hyst = %+.1f C)" % (temp['temp1_input'], temp['temp1_max'], temp['temp1_max_hyst'])
|
||||
else:
|
||||
continue
|
||||
|
||||
return (label, value)
|
||||
|
||||
def show_temp_values(self):
|
||||
self.get_thermal_info()
|
||||
for temp in self.info:
|
||||
print temp['label']
|
||||
print "temp1\t %+.1f C (high = %+.1f C, hyst = %+.1f C)" % (temp['temp1_input'], temp['temp1_max'], temp['temp1_max_hyst'])
|
||||
|
||||
|
||||
def dump_sysfs(self):
|
||||
return pddf_obj.cli_dump_dsysfs('temp-sensors')
|
@ -19,7 +19,8 @@ RUN apt-get update && \
|
||||
python-smbus \
|
||||
ethtool \
|
||||
dmidecode \
|
||||
i2c-tools
|
||||
i2c-tools \
|
||||
python-jsonschema
|
||||
|
||||
# On Arista devices, the sonic_platform wheel is not installed in the container.
|
||||
# Instead, the installation directory is mounted from the host OS. However, this method
|
||||
|
@ -178,6 +178,14 @@ sudo cp {{platform_common_py2_wheel_path}} $FILESYSTEM_ROOT/$PLATFORM_COMMON_PY2
|
||||
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip2 install $PLATFORM_COMMON_PY2_WHEEL_NAME
|
||||
sudo rm -rf $FILESYSTEM_ROOT/$PLATFORM_COMMON_PY2_WHEEL_NAME
|
||||
|
||||
{% if pddf_support == "y" %}
|
||||
# Install pddf-platform-api-base Python 2 package
|
||||
PLATFORM_PDDF_COMMON_PY2_WHEEL_NAME=$(basename {{pddf_platform_api_base_py2_wheel_path}})
|
||||
sudo cp {{pddf_platform_api_base_py2_wheel_path}} $FILESYSTEM_ROOT/$PLATFORM_PDDF_COMMON_PY2_WHEEL_NAME
|
||||
sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install $PLATFORM_PDDF_COMMON_PY2_WHEEL_NAME
|
||||
sudo rm -rf $FILESYSTEM_ROOT/$PLATFORM_PDDF_COMMON_PY2_WHEEL_NAME
|
||||
{% endif %}
|
||||
|
||||
# Install system-health Python 2 package
|
||||
SYSTEM_HEALTH_PY2_WHEEL_NAME=$(basename {{system_health_py2_wheel_path}})
|
||||
sudo cp {{system_health_py2_wheel_path}} $FILESYSTEM_ROOT/$SYSTEM_HEALTH_PY2_WHEEL_NAME
|
||||
|
@ -4,6 +4,7 @@ SONIC_ONE_IMAGE = sonic-broadcom.bin
|
||||
$(SONIC_ONE_IMAGE)_MACHINE = broadcom
|
||||
$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie
|
||||
$(SONIC_ONE_IMAGE)_INSTALLS += $(BRCM_OPENNSL_KERNEL)
|
||||
$(SONIC_ONE_IMAGE)_INSTALLS += $(PDDF_PLATFORM_MODULE)
|
||||
$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR)
|
||||
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
|
||||
$(DELL_Z9264F_PLATFORM_MODULE) \
|
||||
|
19
platform/pddf/README.md
Normal file
19
platform/pddf/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
Platform Driver Development Framework (PDDF) is part of SONiC Platform Development Kit (PDK) which optimizes the platform developement.
|
||||
|
||||
SONiC PDDF (Platform driver development framework) supports the following HW devices on a given platform:
|
||||
|
||||
- Fan
|
||||
- PSU
|
||||
- System EEPROM
|
||||
- CPLD
|
||||
- CPLDMUX
|
||||
- GPIO
|
||||
- Optic Transceivers
|
||||
- System LED control via CPLD
|
||||
- System Status Registers in CPLD
|
||||
- Temp Sensors
|
||||
|
||||
This folder for the PDDF consists of the following:
|
||||
|
||||
- PDDF python utility scripts
|
||||
- Generic PDDF HW device drivers in kernel space
|
1
platform/pddf/i2c/Makefile
Normal file
1
platform/pddf/i2c/Makefile
Normal file
@ -0,0 +1 @@
|
||||
subdir-m := modules
|
12
platform/pddf/i2c/debian/changelog
Executable file
12
platform/pddf/i2c/debian/changelog
Executable file
@ -0,0 +1,12 @@
|
||||
sonic-pddf-platform-modules (1.1) unstable; urgency=low
|
||||
|
||||
* Enhancing PDDF: Added support for cpldmux, gpio and some extra attributes
|
||||
|
||||
-- Broadcom <fuzail.khan@broadcom.com> Wed, 10 Jun 2020 10:10:10 -0800
|
||||
|
||||
sonic-pddf-platform-modules (1.0) unstable; urgency=low
|
||||
|
||||
* Basic tempelate for PDDF
|
||||
* Initial release
|
||||
|
||||
-- Broadcom <satish-k.kumar@broadcom.com> Wed, 26 Jun 2019 10:10:10 -0800
|
1
platform/pddf/i2c/debian/compat
Normal file
1
platform/pddf/i2c/debian/compat
Normal file
@ -0,0 +1 @@
|
||||
9
|
12
platform/pddf/i2c/debian/control
Executable file
12
platform/pddf/i2c/debian/control
Executable file
@ -0,0 +1,12 @@
|
||||
Source: sonic-pddf-platform-modules
|
||||
Section: main
|
||||
Priority: extra
|
||||
Maintainer: Broadcom <sk@broadcom.com>
|
||||
Build-Depends: debhelper (>= 9), bzip2
|
||||
Standards-Version: 3.9.3
|
||||
|
||||
Package: sonic-platform-pddf
|
||||
Architecture: amd64
|
||||
Description: kernel modules for platform devices such as psu, fan, sfp, led
|
||||
|
||||
|
75
platform/pddf/i2c/debian/rules
Executable file
75
platform/pddf/i2c/debian/rules
Executable file
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
# Sample debian/rules that uses debhelper.
|
||||
# This file was originally written by Joey Hess and Craig Small.
|
||||
# As a special exception, when this file is copied by dh-make into a
|
||||
# dh-make output file, you may use that output file without restriction.
|
||||
# This special exception was added by Craig Small in version 0.37 of dh-make.
|
||||
include /usr/share/dpkg/pkg-info.mk
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
export INSTALL_MOD_DIR:=extra
|
||||
|
||||
PYTHON ?= python2
|
||||
|
||||
PACKAGE_PRE_NAME := sonic-platform-pddf
|
||||
KVERSION ?= $(shell uname -r)
|
||||
KERNEL_SRC := /lib/modules/$(KVERSION)
|
||||
MOD_SRC_DIR:= $(shell pwd)
|
||||
MODULE_DIRS:= client cpld cpld/driver cpldmux cpldmux/driver fan fan/driver fan/vendor_api mux gpio led psu psu/driver sysstatus xcvr xcvr/driver
|
||||
MODULE_DIR:= modules
|
||||
UTILS_DIR := utils
|
||||
SERVICE_DIR := service
|
||||
|
||||
%:
|
||||
echo =================RUNNING $@=============
|
||||
dh $@ --with systemd,python2,python3 --buildsystem=pybuild
|
||||
|
||||
clean:
|
||||
echo ============CLEANING=================
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_clean
|
||||
make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR) clean
|
||||
|
||||
build:
|
||||
make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR); \
|
||||
$(PYTHON) $(MOD_SRC_DIR)/setup.py build; \
|
||||
|
||||
binary: binary-arch binary-indep
|
||||
# Nothing to do
|
||||
|
||||
binary-arch:
|
||||
# Nothing to do
|
||||
|
||||
binary-indep:
|
||||
dh_testdir
|
||||
dh_installdirs
|
||||
dh_installdirs -p$(PACKAGE_PRE_NAME) $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
|
||||
dh_installdirs -p$(PACKAGE_PRE_NAME) usr/local/bin; \
|
||||
# Custom package commands
|
||||
(for mod in $(MODULE_DIRS); do \
|
||||
cp $(MOD_SRC_DIR)/$(MODULE_DIR)/$${mod}/*.ko debian/$(PACKAGE_PRE_NAME)/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
|
||||
done) ; \
|
||||
cp -r $(MOD_SRC_DIR)/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)/usr/local/bin/; \
|
||||
$(PYTHON) $(MOD_SRC_DIR)/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME) --install-layout=deb;
|
||||
|
||||
# Resuming debhelper scripts
|
||||
dh_testroot
|
||||
dh_install
|
||||
dh_installchangelogs
|
||||
dh_installdocs
|
||||
dh_systemd_enable
|
||||
dh_installinit
|
||||
dh_systemd_start
|
||||
dh_link
|
||||
dh_fixperms
|
||||
dh_compress
|
||||
dh_strip
|
||||
dh_installdeb
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
.PHONY: build binary binary-arch binary-indep clean
|
1
platform/pddf/i2c/modules/Makefile
Normal file
1
platform/pddf/i2c/modules/Makefile
Normal file
@ -0,0 +1 @@
|
||||
subdir-m := client cpld cpldmux xcvr mux gpio psu fan led sysstatus
|
3
platform/pddf/i2c/modules/client/Makefile
Normal file
3
platform/pddf/i2c/modules/client/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
obj-m:= pddf_client_module.o
|
||||
|
||||
ccflags-y := -I$(M)/modules/include
|
330
platform/pddf/i2c/modules/client/pddf_client_module.c
Normal file
330
platform/pddf/i2c/modules/client/pddf_client_module.c
Normal file
@ -0,0 +1,330 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* A pddf kernel module to create access-data attributes for client creation
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/hashtable.h>
|
||||
#include "pddf_client_defs.h"
|
||||
|
||||
|
||||
|
||||
NEW_DEV_ATTR pddf_data={0};
|
||||
EXPORT_SYMBOL(pddf_data);
|
||||
int showall = 0;
|
||||
|
||||
|
||||
/* CLIENT CREATION DATA ATTR LIST */
|
||||
PDDF_DATA_ATTR(i2c_type, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, (void*)&pddf_data.i2c_type, NULL);
|
||||
PDDF_DATA_ATTR(i2c_name, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, (void*)&pddf_data.i2c_name, NULL);
|
||||
PDDF_DATA_ATTR(parent_bus, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&pddf_data.parent_bus, NULL);
|
||||
PDDF_DATA_ATTR(dev_type, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, (void*)&pddf_data.dev_type, NULL);
|
||||
PDDF_DATA_ATTR(dev_id, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&pddf_data.dev_id, NULL);
|
||||
PDDF_DATA_ATTR(dev_addr, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&pddf_data.dev_addr, NULL);
|
||||
PDDF_DATA_ATTR(error, S_IRUGO, show_error_code, NULL, PDDF_INT_DEC, sizeof(int), (void*)&pddf_data.error, (void*)&pddf_data.errstr);
|
||||
|
||||
|
||||
|
||||
static struct attribute *pddf_clients_data_attributes[] = {
|
||||
&attr_i2c_type.dev_attr.attr,
|
||||
&attr_i2c_name.dev_attr.attr,
|
||||
&attr_parent_bus.dev_attr.attr,
|
||||
&attr_dev_type.dev_attr.attr,
|
||||
&attr_dev_id.dev_attr.attr,
|
||||
&attr_dev_addr.dev_attr.attr,
|
||||
&attr_error.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
struct attribute_group pddf_clients_data_group = {
|
||||
.attrs = pddf_clients_data_attributes,
|
||||
};
|
||||
EXPORT_SYMBOL(pddf_clients_data_group);
|
||||
|
||||
|
||||
|
||||
PDDF_DATA_ATTR(showall, S_IRUGO, show_all_devices, NULL, PDDF_INT_DEC, sizeof(int), (void *)&showall, NULL);
|
||||
|
||||
static struct attribute *pddf_allclients_data_attributes[] = {
|
||||
&attr_showall.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
struct attribute_group pddf_allclients_data_group = {
|
||||
.attrs = pddf_allclients_data_attributes,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void set_attr_data(void * ptr)
|
||||
{
|
||||
pddf_data.data=ptr;
|
||||
}
|
||||
|
||||
ssize_t show_all_devices(struct device *dev, struct device_attribute *da, char *buf)
|
||||
{
|
||||
int ret = 0;
|
||||
PDDF_ATTR *pptr = (PDDF_ATTR *)da;
|
||||
int *ptr = (int *)pptr->addr;
|
||||
|
||||
traverse_device_table();
|
||||
ret = sprintf(buf, "Total Devices: %d\n", *ptr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t show_error_code(struct device *dev, struct device_attribute *da, char *buf)
|
||||
{
|
||||
int ret = 0;
|
||||
PDDF_ATTR *pptr = (PDDF_ATTR *)da;
|
||||
NEW_DEV_ATTR *ptr = ( NEW_DEV_ATTR *)pptr->addr;
|
||||
|
||||
ret = sprintf(buf, "0x%x:%s\n", (ptr->error), ptr->errstr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void set_error_code(int ecode, char *estr)
|
||||
{
|
||||
pddf_data.error = ecode;
|
||||
strcpy(pddf_data.errstr, estr);
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(set_error_code);
|
||||
|
||||
ssize_t show_pddf_data(struct device *dev, struct device_attribute *da, char *buf)
|
||||
{
|
||||
int ret = 0;
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
/*pddf_dbg(KERN_ERR "[ READ ] DATA ATTR PTR TYPE:%d, ADDR=%p\n", ptr->type, ptr->addr);*/
|
||||
switch(ptr->type)
|
||||
{
|
||||
case PDDF_CHAR:
|
||||
ret = sprintf(buf, "%s\n", ptr->addr);
|
||||
break;
|
||||
case PDDF_UCHAR:
|
||||
ret = sprintf(buf, "%d\n", *(unsigned char*)(ptr->addr));
|
||||
break;
|
||||
case PDDF_INT_DEC:
|
||||
ret = sprintf(buf, "%d\n", *(int*)(ptr->addr));
|
||||
break;
|
||||
case PDDF_INT_HEX:
|
||||
ret = sprintf(buf, "0x%x\n", *(int*)(ptr->addr));
|
||||
break;
|
||||
case PDDF_USHORT:
|
||||
ret = sprintf(buf, "0x%x\n", *(unsigned short *)(ptr->addr));
|
||||
break;
|
||||
case PDDF_UINT32:
|
||||
ret = sprintf(buf, "0x%x\n", *(uint32_t *)(ptr->addr));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(show_pddf_data);
|
||||
|
||||
ssize_t store_pddf_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
int ret = 0, num = 0;
|
||||
|
||||
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
|
||||
switch(ptr->type)
|
||||
{
|
||||
case PDDF_CHAR:
|
||||
strncpy(ptr->addr, buf, strlen(buf)-1); // to discard newline char form buf
|
||||
ptr->addr[strlen(buf)-1] = '\0';
|
||||
break;
|
||||
case PDDF_UCHAR:
|
||||
ret = kstrtoint(buf,10,&num);
|
||||
if (ret==0)
|
||||
*(unsigned char *)(ptr->addr) = (unsigned char)num;
|
||||
break;
|
||||
case PDDF_INT_DEC:
|
||||
ret = kstrtoint(buf,10,&num);
|
||||
if (ret==0)
|
||||
*(int *)(ptr->addr) = num;
|
||||
break;
|
||||
case PDDF_INT_HEX:
|
||||
ret = kstrtoint(buf,16,&num);
|
||||
if (ret==0)
|
||||
*(int *)(ptr->addr) = num;
|
||||
break;
|
||||
case PDDF_USHORT:
|
||||
ret = kstrtoint(buf,16,&num);
|
||||
if (ret==0)
|
||||
*(unsigned short *)(ptr->addr) = (unsigned short)num;
|
||||
break;
|
||||
case PDDF_UINT32:
|
||||
ret = kstrtoint(buf,16,&num);
|
||||
if (ret==0)
|
||||
*(uint32_t *)(ptr->addr) = (uint32_t)num;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
EXPORT_SYMBOL(store_pddf_data);
|
||||
|
||||
|
||||
|
||||
DEFINE_HASHTABLE(htable, 8);
|
||||
|
||||
int get_hash(char *name)
|
||||
{
|
||||
int i=0;
|
||||
int hash=0;
|
||||
for(i=0; i<strlen(name); i++)
|
||||
{
|
||||
hash+=name[i];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
void init_device_table(void)
|
||||
{
|
||||
hash_init(htable);
|
||||
}
|
||||
|
||||
void add_device_table(char *name, void *ptr)
|
||||
{
|
||||
PDEVICE *hdev=kmalloc(sizeof(PDEVICE), GFP_KERNEL );
|
||||
if(!hdev)return;
|
||||
strcpy(hdev->name, name);
|
||||
hdev->data = ptr;
|
||||
pddf_dbg(CLIENT, KERN_ERR "%s: Adding ptr 0x%p to the hash table\n", __FUNCTION__, ptr);
|
||||
hash_add(htable, &hdev->node, get_hash(hdev->name));
|
||||
}
|
||||
EXPORT_SYMBOL(add_device_table);
|
||||
|
||||
void* get_device_table(char *name)
|
||||
{
|
||||
PDEVICE *dev=NULL;
|
||||
int i=0;
|
||||
|
||||
hash_for_each(htable, i, dev, node) {
|
||||
if(strcmp(dev->name, name)==0) {
|
||||
return (void *)dev->data;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(get_device_table);
|
||||
|
||||
void delete_device_table(char *name)
|
||||
{
|
||||
PDEVICE *dev=NULL;
|
||||
int i=0;
|
||||
|
||||
hash_for_each(htable, i, dev, node) {
|
||||
if(strcmp(dev->name, name)==0) {
|
||||
pddf_dbg(CLIENT, KERN_ERR "found entry to delete: %s 0x%p\n", dev->name, dev->data);
|
||||
hash_del(&(dev->node));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(delete_device_table);
|
||||
|
||||
void traverse_device_table(void )
|
||||
{
|
||||
PDEVICE *dev=NULL;
|
||||
int i=0;
|
||||
hash_for_each(htable, i, dev, node) {
|
||||
pddf_dbg(CLIENT, KERN_ERR "Entry[%d]: %s : 0x%p\n", i, dev->name, dev->data);
|
||||
}
|
||||
showall = i;
|
||||
}
|
||||
EXPORT_SYMBOL(traverse_device_table);
|
||||
|
||||
struct kobject *device_kobj;
|
||||
static struct kobject *pddf_kobj;
|
||||
|
||||
struct kobject *get_device_i2c_kobj(void)
|
||||
{
|
||||
return device_kobj;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(get_device_i2c_kobj);
|
||||
|
||||
int __init pddf_data_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
||||
pddf_dbg(CLIENT, "PDDF_DATA MODULE.. init\n");
|
||||
|
||||
pddf_kobj = kobject_create_and_add("pddf", kernel_kobj);
|
||||
if(!pddf_kobj) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
device_kobj = kobject_create_and_add("devices", pddf_kobj);
|
||||
if(!device_kobj) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
init_device_table();
|
||||
|
||||
ret = sysfs_create_group(device_kobj, &pddf_allclients_data_group);
|
||||
if (ret)
|
||||
{
|
||||
kobject_put(device_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(CLIENT, "CREATED PDDF ALLCLIENTS CREATION SYSFS GROUP\n");
|
||||
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit pddf_data_exit(void)
|
||||
{
|
||||
|
||||
pddf_dbg(CLIENT, "PDDF_DATA MODULE.. exit\n");
|
||||
sysfs_remove_group(device_kobj, &pddf_allclients_data_group);
|
||||
|
||||
kobject_put(device_kobj);
|
||||
kobject_put(pddf_kobj);
|
||||
pddf_dbg(CLIENT, KERN_ERR "%s: Removed the kernle object for 'pddf' and 'device' \n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(pddf_data_init);
|
||||
module_exit(pddf_data_exit);
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("pddf data");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
4
platform/pddf/i2c/modules/cpld/Makefile
Normal file
4
platform/pddf/i2c/modules/cpld/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
subdir-m := driver
|
||||
obj-m := pddf_cpld_module.o
|
||||
|
||||
CFLAGS_$(obj-m):= -I$(M)/modules/include
|
5
platform/pddf/i2c/modules/cpld/driver/Makefile
Normal file
5
platform/pddf/i2c/modules/cpld/driver/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
TARGET = pddf_cpld_driver
|
||||
obj-m := $(TARGET).o
|
||||
|
||||
|
||||
ccflags-y := -I$(M)/modules/include
|
230
platform/pddf/i2c/modules/cpld/driver/pddf_cpld_driver.c
Executable file
230
platform/pddf/i2c/modules/cpld/driver/pddf_cpld_driver.c
Executable file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* A pddf kernel driver module for CPLD
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/dmi.h>
|
||||
#include "pddf_cpld_defs.h"
|
||||
|
||||
extern PDDF_CPLD_DATA pddf_cpld_data;
|
||||
|
||||
|
||||
static LIST_HEAD(cpld_client_list);
|
||||
static struct mutex list_lock;
|
||||
|
||||
struct cpld_client_node {
|
||||
struct i2c_client *client;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg)
|
||||
{
|
||||
struct list_head *list_node = NULL;
|
||||
struct cpld_client_node *cpld_node = NULL;
|
||||
int ret = -EPERM;
|
||||
|
||||
//hw_preaccess_func_cpld_mux_default((uint32_t)cpld_addr, NULL);
|
||||
|
||||
mutex_lock(&list_lock);
|
||||
|
||||
list_for_each(list_node, &cpld_client_list)
|
||||
{
|
||||
cpld_node = list_entry(list_node, struct cpld_client_node, list);
|
||||
|
||||
if (cpld_node->client->addr == cpld_addr) {
|
||||
ret = i2c_smbus_read_byte_data(cpld_node->client, reg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&list_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(board_i2c_cpld_read);
|
||||
|
||||
int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value)
|
||||
{
|
||||
struct list_head *list_node = NULL;
|
||||
struct cpld_client_node *cpld_node = NULL;
|
||||
int ret = -EIO;
|
||||
|
||||
|
||||
mutex_lock(&list_lock);
|
||||
|
||||
list_for_each(list_node, &cpld_client_list)
|
||||
{
|
||||
cpld_node = list_entry(list_node, struct cpld_client_node, list);
|
||||
|
||||
if (cpld_node->client->addr == cpld_addr) {
|
||||
ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&list_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(board_i2c_cpld_write);
|
||||
|
||||
ssize_t regval_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int len = 0;
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
|
||||
mutex_lock(&pddf_cpld_data.cpld_lock);
|
||||
// Put code here to read the register value and print it
|
||||
if (pddf_cpld_data.reg_addr!=0)
|
||||
len = sprintf(buf, "0x%2.2x\n", board_i2c_cpld_read(client->addr, pddf_cpld_data.reg_addr));
|
||||
else
|
||||
len = sprintf(buf, "xx\n");
|
||||
|
||||
mutex_unlock(&pddf_cpld_data.cpld_lock);
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(regval);
|
||||
|
||||
static struct attribute *cpld_attrs[] = {
|
||||
&dev_attr_regval.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group cpld_attribute_group = {
|
||||
.attrs = cpld_attrs,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/* Addresses scanned for board_i2c_cpld
|
||||
*/
|
||||
static const unsigned short normal_i2c[] = { 0x31, 0x32, 0x33, 0x35, 0x60, 0x61, 0x62, 0x64, I2C_CLIENT_END };
|
||||
|
||||
static void board_i2c_cpld_add_client(struct i2c_client *client)
|
||||
{
|
||||
struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL);
|
||||
|
||||
if (!node) {
|
||||
dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr);
|
||||
return;
|
||||
}
|
||||
|
||||
node->client = client;
|
||||
|
||||
mutex_lock(&list_lock);
|
||||
list_add(&node->list, &cpld_client_list);
|
||||
mutex_unlock(&list_lock);
|
||||
}
|
||||
|
||||
static void board_i2c_cpld_remove_client(struct i2c_client *client)
|
||||
{
|
||||
struct list_head *list_node = NULL;
|
||||
struct cpld_client_node *cpld_node = NULL;
|
||||
int found = 0;
|
||||
|
||||
mutex_lock(&list_lock);
|
||||
|
||||
list_for_each(list_node, &cpld_client_list)
|
||||
{
|
||||
cpld_node = list_entry(list_node, struct cpld_client_node, list);
|
||||
|
||||
if (cpld_node->client == client) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
list_del(list_node);
|
||||
kfree(cpld_node);
|
||||
}
|
||||
|
||||
mutex_unlock(&list_lock);
|
||||
}
|
||||
|
||||
static int board_i2c_cpld_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *dev_id)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
|
||||
dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr);
|
||||
status = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Register sysfs hooks */
|
||||
status = sysfs_create_group(&client->dev.kobj, &cpld_attribute_group);
|
||||
if (status) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
dev_dbg(&client->dev, "chip found\n");
|
||||
board_i2c_cpld_add_client(client);
|
||||
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
static int board_i2c_cpld_remove(struct i2c_client *client)
|
||||
{
|
||||
sysfs_remove_group(&client->dev.kobj, &cpld_attribute_group);
|
||||
board_i2c_cpld_remove_client(client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id board_i2c_cpld_id[] = {
|
||||
{ "i2c_cpld", 0 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, board_i2c_cpld_id);
|
||||
|
||||
static struct i2c_driver board_i2c_cpld_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "i2c_cpld",
|
||||
},
|
||||
.probe = board_i2c_cpld_probe,
|
||||
.remove = board_i2c_cpld_remove,
|
||||
.id_table = board_i2c_cpld_id,
|
||||
.address_list = normal_i2c,
|
||||
};
|
||||
|
||||
static int __init board_i2c_cpld_init(void)
|
||||
{
|
||||
mutex_init(&list_lock);
|
||||
return i2c_add_driver(&board_i2c_cpld_driver);
|
||||
}
|
||||
|
||||
static void __exit board_i2c_cpld_exit(void)
|
||||
{
|
||||
i2c_del_driver(&board_i2c_cpld_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("board_i2c_cpld driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(board_i2c_cpld_init);
|
||||
module_exit(board_i2c_cpld_exit);
|
219
platform/pddf/i2c/modules/cpld/pddf_cpld_module.c
Normal file
219
platform/pddf/i2c/modules/cpld/pddf_cpld_module.c
Normal file
@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* A pddf kernel module to create I2C client for a CPLD
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/kobject.h>
|
||||
#include "pddf_client_defs.h"
|
||||
#include "pddf_cpld_defs.h"
|
||||
|
||||
PDDF_CPLD_DATA pddf_cpld_data={0};
|
||||
EXPORT_SYMBOL(pddf_cpld_data);
|
||||
|
||||
static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
static ssize_t store_pddf_cpld_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
ssize_t show_pddf_cpld_data(struct device *dev, struct device_attribute *da, char *buf);
|
||||
|
||||
extern void *get_device_table(char *name);
|
||||
extern void delete_device_table(char *name);
|
||||
|
||||
|
||||
/* MUX CLIENT DATA */
|
||||
PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, NULL, (void*)&pddf_data);
|
||||
PDDF_DATA_ATTR(reg_addr, S_IWUSR|S_IRUGO, show_pddf_cpld_data, store_pddf_cpld_data, PDDF_USHORT, sizeof(unsigned short), (void*)&pddf_cpld_data.reg_addr, NULL);
|
||||
|
||||
|
||||
|
||||
static struct attribute *cpld_attributes[] = {
|
||||
&attr_dev_ops.dev_attr.attr,
|
||||
&attr_reg_addr.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group pddf_cpld_client_data_group = {
|
||||
.attrs = cpld_attributes,
|
||||
};
|
||||
|
||||
|
||||
static ssize_t store_pddf_cpld_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
int ret = 0;
|
||||
int num = 0;
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
|
||||
ret = kstrtoint(buf,16,&num);
|
||||
if (ret==0)
|
||||
{
|
||||
mutex_lock(&pddf_cpld_data.cpld_lock);
|
||||
*(unsigned short *)(ptr->addr) = (unsigned short)num;
|
||||
mutex_unlock(&pddf_cpld_data.cpld_lock);
|
||||
pddf_dbg(CPLD, KERN_ERR "Stored value: 0x%x, num: 0x%x\n", *(int*)(ptr->addr), num);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
EXPORT_SYMBOL(store_pddf_cpld_data);
|
||||
|
||||
ssize_t show_pddf_cpld_data(struct device *dev, struct device_attribute *da, char *buf)
|
||||
{
|
||||
int ret = 0;
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
pddf_dbg(CPLD, KERN_ERR "[ READ ] DATA ATTR PTR TYPE:%d, ADDR=%p\n", ptr->type, ptr->addr);
|
||||
|
||||
mutex_lock(&pddf_cpld_data.cpld_lock);
|
||||
ret = sprintf(buf, "0x%x\n", *(unsigned short *)(ptr->addr));
|
||||
mutex_unlock(&pddf_cpld_data.cpld_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(show_pddf_cpld_data);
|
||||
|
||||
static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
NEW_DEV_ATTR *device_ptr = (NEW_DEV_ATTR *)(ptr->data);
|
||||
struct i2c_adapter *adapter;
|
||||
static struct i2c_board_info board_info;
|
||||
struct i2c_client *client_ptr;
|
||||
|
||||
if (strncmp(buf, "add", strlen(buf)-1)==0)
|
||||
{
|
||||
adapter = i2c_get_adapter(device_ptr->parent_bus);
|
||||
|
||||
if (strncmp(device_ptr->dev_type, "i2c_cpld", strlen("i2c_cpld"))==0)
|
||||
{
|
||||
board_info = (struct i2c_board_info) {
|
||||
.platform_data = (void *)NULL,
|
||||
};
|
||||
|
||||
board_info.addr = device_ptr->dev_addr;
|
||||
strcpy(board_info.type, device_ptr->dev_type);
|
||||
|
||||
/*pddf_dbg(KERN_ERR "Creating a client %s on 0x%x, platform_data 0x%x\n", board_info.type, board_info.addr, board_info.platform_data);*/
|
||||
client_ptr = i2c_new_device(adapter, &board_info);
|
||||
|
||||
if (client_ptr != NULL) {
|
||||
i2c_put_adapter(adapter);
|
||||
pddf_dbg(CPLD, KERN_ERR "Created %s client: 0x%p\n", device_ptr->i2c_name, (void *)client_ptr);
|
||||
add_device_table(device_ptr->i2c_name, (void*)client_ptr);
|
||||
}
|
||||
else {
|
||||
i2c_put_adapter(adapter);
|
||||
goto free_data;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "%s: Unsupported type of cpld - unable to add i2c client\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
else if (strncmp(buf, "delete", strlen(buf)-1)==0)
|
||||
{
|
||||
/*Get the i2c_client handle for the created client*/
|
||||
client_ptr = (struct i2c_client *)get_device_table(device_ptr->i2c_name);
|
||||
if (client_ptr)
|
||||
{
|
||||
pddf_dbg(CPLD, KERN_ERR "Removing %s client: 0x%p\n", device_ptr->i2c_name, (void *)client_ptr);
|
||||
i2c_unregister_device(client_ptr);
|
||||
delete_device_table(device_ptr->i2c_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "Unable to get the client handle for %s\n", device_ptr->i2c_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s", __FUNCTION__, buf);
|
||||
}
|
||||
|
||||
free_data:
|
||||
/*TODO: free the device_ptr->data is dynamically allocated*/
|
||||
memset(device_ptr, 0 , sizeof(NEW_DEV_ATTR));
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static struct kobject *cpld_kobj;
|
||||
|
||||
int __init cpld_data_init(void)
|
||||
{
|
||||
struct kobject *device_kobj;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
pddf_dbg(CPLD, "CPLD_DATA MODULE.. init\n");
|
||||
|
||||
device_kobj = get_device_i2c_kobj();
|
||||
if(!device_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
cpld_kobj = kobject_create_and_add("cpld", device_kobj);
|
||||
if(!cpld_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
ret = sysfs_create_group(cpld_kobj, &pddf_clients_data_group);
|
||||
if (ret)
|
||||
{
|
||||
kobject_put(cpld_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(CPLD, "CREATED PDDF I2C CLIENTS CREATION SYSFS GROUP\n");
|
||||
|
||||
mutex_init(&pddf_cpld_data.cpld_lock);
|
||||
|
||||
ret = sysfs_create_group(cpld_kobj, &pddf_cpld_client_data_group);
|
||||
if (ret)
|
||||
{
|
||||
sysfs_remove_group(cpld_kobj, &pddf_clients_data_group);
|
||||
kobject_put(cpld_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(CPLD, "CREATED PDDF I2C CLIENTS CREATION SYSFS GROUP\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit cpld_data_exit(void)
|
||||
{
|
||||
pddf_dbg(CPLD, "CPLD_DATA MODULE.. exit\n");
|
||||
sysfs_remove_group(cpld_kobj, &pddf_cpld_client_data_group);
|
||||
sysfs_remove_group(cpld_kobj, &pddf_clients_data_group);
|
||||
kobject_put(cpld_kobj);
|
||||
pddf_dbg(CPLD, KERN_ERR "%s: Removed the kobjects for 'cpld'\n",__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(cpld_data_init);
|
||||
module_exit(cpld_data_exit);
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("cpld platform data");
|
||||
MODULE_LICENSE("GPL");
|
4
platform/pddf/i2c/modules/cpldmux/Makefile
Normal file
4
platform/pddf/i2c/modules/cpldmux/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
subdir-m := driver
|
||||
obj-m := pddf_cpldmux_module.o
|
||||
|
||||
CFLAGS_$(obj-m):= -I$(M)/modules/include
|
4
platform/pddf/i2c/modules/cpldmux/driver/Makefile
Normal file
4
platform/pddf/i2c/modules/cpldmux/driver/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
TARGET = pddf_cpldmux_driver
|
||||
obj-m := $(TARGET).o
|
||||
|
||||
ccflags-y := -I$(M)/modules/include
|
209
platform/pddf/i2c/modules/cpldmux/driver/pddf_cpldmux_driver.c
Executable file
209
platform/pddf/i2c/modules/cpldmux/driver/pddf_cpldmux_driver.c
Executable file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* A pddf kernel driver module for CPLDMUX
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/platform_data/pca954x.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "pddf_client_defs.h"
|
||||
#include "pddf_cpldmux_defs.h"
|
||||
|
||||
extern PDDF_CPLDMUX_DATA pddf_cpldmux_data;
|
||||
|
||||
/* Users may overwrite these select and delsect functions as per their requirements
|
||||
* by overwriting them in custom driver
|
||||
*/
|
||||
PDDF_CPLDMUX_OPS pddf_cpldmux_ops = {
|
||||
.select = pddf_cpldmux_select_default,
|
||||
.deselect = NULL, /* pddf_cpldmux_deselct_default */
|
||||
};
|
||||
EXPORT_SYMBOL(pddf_cpldmux_ops);
|
||||
|
||||
|
||||
/* NOTE: Never use i2c_smbus_write_byte_data() or i2c_smbus_xfer() since these operations
|
||||
* locks the parent bus which might lead to mutex deadlock.
|
||||
*/
|
||||
static int cpldmux_byte_write(struct i2c_client *client, u8 regaddr, u8 val)
|
||||
{
|
||||
union i2c_smbus_data data;
|
||||
|
||||
data.byte = val;
|
||||
return client->adapter->algo->smbus_xfer(client->adapter, client->addr,
|
||||
client->flags,
|
||||
I2C_SMBUS_WRITE,
|
||||
regaddr, I2C_SMBUS_BYTE_DATA, &data);
|
||||
}
|
||||
|
||||
int pddf_cpldmux_select_default(struct i2c_mux_core *muxc, uint32_t chan)
|
||||
{
|
||||
PDDF_CPLDMUX_PRIV_DATA *private = i2c_mux_priv(muxc);
|
||||
PDDF_CPLDMUX_PDATA *pdata = NULL;
|
||||
PDDF_CPLDMUX_CHAN_DATA *sdata = NULL;
|
||||
int ret = 0;
|
||||
|
||||
/* Select the chan_data based upon the chan */
|
||||
pdata = &private->data;
|
||||
if (chan>=pdata->num_chan)
|
||||
{
|
||||
printk(KERN_ERR "%s: wrong channel number %d, supported channels %d\n",__FUNCTION__, chan, pdata->num_chan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( (pdata->chan_cache!=1) || (private->last_chan!=chan) )
|
||||
{
|
||||
sdata = &pdata->chan_data[chan];
|
||||
pddf_dbg(CPLDMUX, KERN_ERR "%s: Writing 0x%x at 0x%x offset of cpld 0x%x to enable chan %d\n", __FUNCTION__, sdata->cpld_sel, sdata->cpld_offset, sdata->cpld_devaddr, chan);
|
||||
ret = cpldmux_byte_write(pdata->cpld, sdata->cpld_offset, (uint8_t)(sdata->cpld_sel & 0xff));
|
||||
private->last_chan = chan;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pddf_cpldmux_deselect_default(struct i2c_mux_core *muxc, uint32_t chan)
|
||||
{
|
||||
PDDF_CPLDMUX_PRIV_DATA *private = i2c_mux_priv(muxc);
|
||||
PDDF_CPLDMUX_PDATA *pdata = NULL;
|
||||
PDDF_CPLDMUX_CHAN_DATA *sdata = NULL;
|
||||
int ret = 0;
|
||||
|
||||
/* Select the chan_data based upon the chan */
|
||||
pdata = &private->data;
|
||||
if (chan>=pdata->num_chan)
|
||||
{
|
||||
printk(KERN_ERR "%s: wrong channel number %d, supported channels %d\n",__FUNCTION__, chan, pdata->num_chan);
|
||||
return 0;
|
||||
}
|
||||
sdata = &pdata->chan_data[chan];
|
||||
|
||||
pddf_dbg(CPLDMUX, KERN_ERR "%s: Writing 0x%x at 0x%x offset of cpld 0x%x to disable chan %d", __FUNCTION__, sdata->cpld_desel, sdata->cpld_offset, sdata->cpld_devaddr, chan);
|
||||
ret = cpldmux_byte_write(pdata->cpld, sdata->cpld_offset, (uint8_t)(sdata->cpld_desel));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cpld_mux_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct i2c_mux_core *muxc;
|
||||
PDDF_CPLDMUX_PRIV_DATA *private;
|
||||
PDDF_CPLDMUX_PDATA *pdata;
|
||||
struct i2c_adapter *adap;
|
||||
int i, ret, ndev;
|
||||
|
||||
pdata = pdev->dev.platform_data;
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "CPLDMUX platform data not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
private = (PDDF_CPLDMUX_PRIV_DATA *)kzalloc(sizeof(PDDF_CPLDMUX_PRIV_DATA) , GFP_KERNEL);
|
||||
if (!private) {
|
||||
printk(KERN_ERR "Failed to allocate memory for priv data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
private->last_chan = 0xff; /*Giving imaginary high value so that proper channel is selected at first iteration*/
|
||||
memcpy(&private->data, pdata, sizeof(PDDF_CPLDMUX_PDATA));
|
||||
|
||||
adap = i2c_get_adapter(pdata->parent_bus);
|
||||
if (!adap) {
|
||||
kfree(private);
|
||||
dev_err(&pdev->dev, "Parent adapter (%d) not found\n", pdata->parent_bus);
|
||||
return -ENODEV;
|
||||
}
|
||||
ndev = pdata->num_chan;
|
||||
|
||||
muxc = i2c_mux_alloc(adap, &pdev->dev, ndev, 0, 0, pddf_cpldmux_ops.select, pddf_cpldmux_ops.deselect);
|
||||
if (!muxc) {
|
||||
ret = -ENOMEM;
|
||||
goto alloc_failed;
|
||||
}
|
||||
muxc->priv = private;
|
||||
platform_set_drvdata(pdev, muxc);
|
||||
|
||||
for (i = 0; i < ndev; i++)
|
||||
{
|
||||
int nr = pdata->base_chan + i;
|
||||
unsigned int class = 0;
|
||||
ret = i2c_mux_add_adapter(muxc, nr, i, class);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
|
||||
goto add_adapter_failed;
|
||||
}
|
||||
}
|
||||
dev_info(&pdev->dev, "%d port mux on %s adapter\n", ndev, adap->name);
|
||||
return 0;
|
||||
|
||||
add_adapter_failed:
|
||||
i2c_mux_del_adapters(muxc);
|
||||
alloc_failed:
|
||||
kfree(private);
|
||||
i2c_put_adapter(adap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cpld_mux_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct i2c_mux_core *muxc = platform_get_drvdata(pdev);
|
||||
struct i2c_adapter *adap = muxc->parent;
|
||||
PDDF_CPLDMUX_PDATA *cpldmux_pdata = pdev->dev.platform_data;
|
||||
|
||||
i2c_mux_del_adapters(muxc);
|
||||
if (muxc->priv)
|
||||
kfree(muxc->priv);
|
||||
i2c_put_adapter(adap);
|
||||
|
||||
if (cpldmux_pdata) {
|
||||
pddf_dbg(CPLDMUX, KERN_DEBUG "%s: Freeing cpldmux platform data\n", __FUNCTION__);
|
||||
kfree(cpldmux_pdata);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver cpld_mux_driver = {
|
||||
.probe = cpld_mux_probe,
|
||||
.remove = cpld_mux_remove, /* TODO */
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "cpld_mux",
|
||||
},
|
||||
};
|
||||
|
||||
static int __init board_i2c_cpldmux_init(void)
|
||||
{
|
||||
int ret;
|
||||
ret = platform_driver_register(&cpld_mux_driver);
|
||||
if (ret) {
|
||||
printk(KERN_WARNING "Fail to register swpld mux driver\n");
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void __exit board_i2c_cpldmux_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&cpld_mux_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("board_i2c_cpldmux driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(board_i2c_cpldmux_init);
|
||||
module_exit(board_i2c_cpldmux_exit);
|
254
platform/pddf/i2c/modules/cpldmux/pddf_cpldmux_module.c
Normal file
254
platform/pddf/i2c/modules/cpldmux/pddf_cpldmux_module.c
Normal file
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* PDDF generic module for cpldmux device
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/kobject.h>
|
||||
#include "pddf_client_defs.h"
|
||||
#include "pddf_cpldmux_defs.h"
|
||||
|
||||
PDDF_CPLDMUX_DATA pddf_cpldmux_data={0};
|
||||
PDDF_CPLDMUX_CHAN_DATA pddf_cpldmux_chan_data={0};
|
||||
EXPORT_SYMBOL(pddf_cpldmux_data);
|
||||
|
||||
static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
static ssize_t do_chan_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
|
||||
extern void *get_device_table(char *name);
|
||||
extern void delete_device_table(char *name);
|
||||
|
||||
|
||||
/* CPLDMUX CLIENT DATA */
|
||||
PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, (void*)&pddf_cpldmux_data, (void*)&pddf_data);
|
||||
PDDF_DATA_ATTR(chan_ops, S_IWUSR, NULL, do_chan_operation, PDDF_CHAR, 8, (void*)&pddf_cpldmux_data, NULL);
|
||||
PDDF_DATA_ATTR(base_chan, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&pddf_cpldmux_data.base_chan, NULL);
|
||||
PDDF_DATA_ATTR(num_chan, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&pddf_cpldmux_data.num_chan, NULL);
|
||||
PDDF_DATA_ATTR(chan_cache, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&pddf_cpldmux_data.chan_cache, NULL);
|
||||
PDDF_DATA_ATTR(cpld_name, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, (void*)&pddf_cpldmux_data.cpld_name, NULL);
|
||||
PDDF_DATA_ATTR(chan, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&pddf_cpldmux_chan_data.chan_num, NULL);
|
||||
PDDF_DATA_ATTR(dev, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 128, (void*)&pddf_cpldmux_chan_data.chan_device, NULL);
|
||||
PDDF_DATA_ATTR(cpld_devaddr, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&pddf_cpldmux_chan_data.cpld_devaddr, NULL);
|
||||
PDDF_DATA_ATTR(cpld_offset, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&pddf_cpldmux_chan_data.cpld_offset, NULL);
|
||||
PDDF_DATA_ATTR(cpld_sel, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&pddf_cpldmux_chan_data.cpld_sel, NULL);
|
||||
PDDF_DATA_ATTR(cpld_desel, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&pddf_cpldmux_chan_data.cpld_desel, NULL);
|
||||
|
||||
|
||||
static struct attribute *cpldmux_attributes[] = {
|
||||
&attr_dev_ops.dev_attr.attr,
|
||||
&attr_chan_ops.dev_attr.attr,
|
||||
&attr_base_chan.dev_attr.attr,
|
||||
&attr_num_chan.dev_attr.attr,
|
||||
&attr_chan_cache.dev_attr.attr,
|
||||
&attr_cpld_name.dev_attr.attr,
|
||||
&attr_chan.dev_attr.attr,
|
||||
&attr_dev.dev_attr.attr,
|
||||
&attr_cpld_devaddr.dev_attr.attr,
|
||||
&attr_cpld_offset.dev_attr.attr,
|
||||
&attr_cpld_sel.dev_attr.attr,
|
||||
&attr_cpld_desel.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group pddf_cpldmux_client_data_group = {
|
||||
.attrs = cpldmux_attributes,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static ssize_t do_chan_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
PDDF_CPLDMUX_DATA *cpldmux_data = (PDDF_CPLDMUX_DATA *)(ptr->addr);
|
||||
int index;
|
||||
|
||||
pddf_dbg(CPLDMUX, KERN_ERR "%s: Adding channel %d\n", __FUNCTION__, pddf_cpldmux_chan_data.chan_num);
|
||||
index = pddf_cpldmux_chan_data.chan_num;
|
||||
cpldmux_data->chan_data[index] = pddf_cpldmux_chan_data;
|
||||
|
||||
memset(&pddf_cpldmux_chan_data, 0, sizeof(pddf_cpldmux_chan_data));
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
NEW_DEV_ATTR *device_ptr = (NEW_DEV_ATTR *)(ptr->data);
|
||||
PDDF_CPLDMUX_DATA *cpldmux_data = (PDDF_CPLDMUX_DATA *)(ptr->addr);
|
||||
PDDF_CPLDMUX_PDATA *cpldmux_platform_data = NULL;
|
||||
struct platform_device *plat_dev = NULL;
|
||||
struct i2c_client *client_ptr = NULL;
|
||||
int ret=0, i=0;
|
||||
|
||||
if (strncmp(buf, "add", strlen(buf)-1)==0)
|
||||
{
|
||||
if (strncmp(device_ptr->dev_type, "cpld_mux", strlen("cpld_mux"))==0)
|
||||
{
|
||||
/*Get the i2c_client handle for the CPLD which drives this cpldmux*/
|
||||
client_ptr = (struct i2c_client *)get_device_table(cpldmux_data->cpld_name);
|
||||
if (client_ptr==NULL)
|
||||
{
|
||||
pddf_dbg(CPLDMUX, KERN_ERR "Unable to get the CPLD client %s for %s cpldmux\n", cpldmux_data->cpld_name, device_ptr->i2c_name);
|
||||
printk(KERN_ERR "Unable to get the CPLD client %s for %s cpldmux\n", cpldmux_data->cpld_name, device_ptr->i2c_name);
|
||||
goto clear_data;
|
||||
}
|
||||
|
||||
/* Allocate the cpldmux_platform_data */
|
||||
cpldmux_platform_data = (PDDF_CPLDMUX_PDATA *)kzalloc( sizeof(PDDF_CPLDMUX_PDATA) + cpldmux_data->num_chan*sizeof(PDDF_CPLDMUX_CHAN_DATA), GFP_KERNEL );
|
||||
cpldmux_platform_data->chan_data = (PDDF_CPLDMUX_CHAN_DATA *)(cpldmux_platform_data+1);
|
||||
|
||||
cpldmux_platform_data->parent_bus = device_ptr->parent_bus;
|
||||
cpldmux_platform_data->base_chan = cpldmux_data->base_chan;
|
||||
cpldmux_platform_data->num_chan = cpldmux_data->num_chan;
|
||||
cpldmux_platform_data->chan_cache = cpldmux_data->chan_cache;
|
||||
cpldmux_platform_data->cpld = client_ptr;
|
||||
for (i=0; i<cpldmux_data->num_chan; i++)
|
||||
{
|
||||
cpldmux_platform_data->chan_data[i] = cpldmux_data->chan_data[i];
|
||||
}
|
||||
|
||||
plat_dev = platform_device_alloc(device_ptr->dev_type, device_ptr->dev_id);
|
||||
|
||||
plat_dev->dev.platform_data = cpldmux_platform_data;
|
||||
|
||||
pddf_dbg(CPLDMUX, KERN_ERR "Creating a %s platform_device 0x%p, platform_data 0x%p\n", plat_dev->name, (void *)plat_dev, (void *)cpldmux_platform_data);
|
||||
ret = platform_device_add(plat_dev);
|
||||
if (ret)
|
||||
{
|
||||
pddf_dbg(CPLDMUX, KERN_ERR "Unable to create cpld_mux (%s) device: Error %d\n", device_ptr->i2c_name, ret);
|
||||
goto free_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
add_device_table(device_ptr->i2c_name, (void *)plat_dev);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "%s: Unsupported type of cpldmux - unable to add i2c client\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
else if (strncmp(buf, "delete", strlen(buf)-1)==0)
|
||||
{
|
||||
/*Get the i2c_client handle for the created client*/
|
||||
plat_dev = (struct platform_device *)get_device_table(device_ptr->i2c_name);
|
||||
if (plat_dev)
|
||||
{
|
||||
pddf_dbg(CPLDMUX, KERN_ERR "Removing %s device: 0x%p\n", device_ptr->i2c_name, (void *)plat_dev);
|
||||
pddf_dbg(CPLDMUX, KERN_ERR "Freeing the memory held by device: 0x%p\n", (void *)plat_dev);
|
||||
platform_device_del(plat_dev);
|
||||
delete_device_table(device_ptr->i2c_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "Unable to get the client handle for %s\n", device_ptr->i2c_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s", __FUNCTION__, buf);
|
||||
}
|
||||
goto clear_data;
|
||||
|
||||
free_data:
|
||||
/* Free the allocated memory for platform and channel data */
|
||||
cpldmux_platform_data = plat_dev->dev.platform_data;
|
||||
if (cpldmux_platform_data)
|
||||
{
|
||||
printk(KERN_ERR "%s: Unable to register a cpldmux device. Freeing the platform data\n", __FUNCTION__);
|
||||
kfree(cpldmux_platform_data);
|
||||
}
|
||||
|
||||
/* Put the platform device structure */
|
||||
platform_device_put(plat_dev);
|
||||
clear_data:
|
||||
memset(cpldmux_data, 0, sizeof(PDDF_CPLDMUX_DATA));
|
||||
/*TODO: free the data device_ptr->data if data is dynamically allocated*/
|
||||
memset(device_ptr, 0, sizeof(NEW_DEV_ATTR));
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static struct kobject *cpldmux_kobj;
|
||||
|
||||
int __init cpldmux_data_init(void)
|
||||
{
|
||||
struct kobject *device_kobj;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
pddf_dbg(CPLDMUX, "CPLDMUX_DATA MODULE.. init\n");
|
||||
|
||||
device_kobj = get_device_i2c_kobj();
|
||||
if(!device_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
cpldmux_kobj = kobject_create_and_add("cpldmux", device_kobj);
|
||||
if(!cpldmux_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
ret = sysfs_create_group(cpldmux_kobj, &pddf_clients_data_group);
|
||||
if (ret)
|
||||
{
|
||||
kobject_put(cpldmux_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(CPLDMUX, "CREATED PDDF I2C CLIENTS CREATION SYSFS GROUP\n");
|
||||
|
||||
|
||||
ret = sysfs_create_group(cpldmux_kobj, &pddf_cpldmux_client_data_group);
|
||||
if (ret)
|
||||
{
|
||||
sysfs_remove_group(cpldmux_kobj, &pddf_clients_data_group);
|
||||
kobject_put(cpldmux_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(CPLDMUX, "CREATED PDDF I2C CLIENTS CREATION SYSFS GROUP\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit cpldmux_data_exit(void)
|
||||
{
|
||||
pddf_dbg(CPLDMUX, "CPLDMUX_DATA MODULE.. exit\n");
|
||||
sysfs_remove_group(cpldmux_kobj, &pddf_cpldmux_client_data_group);
|
||||
sysfs_remove_group(cpldmux_kobj, &pddf_clients_data_group);
|
||||
kobject_put(cpldmux_kobj);
|
||||
pddf_dbg(CPLDMUX, KERN_ERR "%s: Removed the kobjects for 'cpldmux'\n",__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(cpldmux_data_init);
|
||||
module_exit(cpldmux_data_exit);
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("cpldmux platform data");
|
||||
MODULE_LICENSE("GPL");
|
4
platform/pddf/i2c/modules/fan/Makefile
Normal file
4
platform/pddf/i2c/modules/fan/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
subdir-m := driver
|
||||
obj-m := pddf_fan_module.o
|
||||
|
||||
CFLAGS_$(obj-m):= -I$(M)/modules/include
|
6
platform/pddf/i2c/modules/fan/driver/Makefile
Normal file
6
platform/pddf/i2c/modules/fan/driver/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
TARGET := pddf_fan_driver_module
|
||||
obj-m := $(TARGET).o
|
||||
|
||||
$(TARGET)-objs := pddf_fan_api.o pddf_fan_driver.o
|
||||
|
||||
ccflags-y := -I$(M)/modules/include
|
526
platform/pddf/i2c/modules/fan/driver/pddf_fan_api.c
Normal file
526
platform/pddf/i2c/modules/fan/driver/pddf_fan_api.c
Normal file
@ -0,0 +1,526 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description of various APIs related to FAN component
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/dmi.h>
|
||||
#include "pddf_fan_defs.h"
|
||||
#include "pddf_fan_driver.h"
|
||||
|
||||
/*#define FAN_DEBUG*/
|
||||
#ifdef FAN_DEBUG
|
||||
#define fan_dbg(...) printk(__VA_ARGS__)
|
||||
#else
|
||||
#define fan_dbg(...)
|
||||
#endif
|
||||
|
||||
extern void *get_device_table(char *name);
|
||||
|
||||
void get_fan_duplicate_sysfs(int idx, char *str)
|
||||
{
|
||||
switch (idx)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int fan_update_hw(struct device *dev, struct fan_attr_info *info, FAN_DATA_ATTR *udata)
|
||||
{
|
||||
int status = 0;
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
FAN_SYSFS_ATTR_DATA *sysfs_attr_data = NULL;
|
||||
|
||||
|
||||
mutex_lock(&info->update_lock);
|
||||
|
||||
sysfs_attr_data = udata->access_data;
|
||||
if (sysfs_attr_data->pre_set != NULL)
|
||||
{
|
||||
status = (sysfs_attr_data->pre_set)(client, udata, info);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: pre_set function fails for %s attribute\n", __FUNCTION__, udata->aname);
|
||||
}
|
||||
if (sysfs_attr_data->do_set != NULL)
|
||||
{
|
||||
status = (sysfs_attr_data->do_set)(client, udata, info);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: do_set function fails for %s attribute\n", __FUNCTION__, udata->aname);
|
||||
|
||||
}
|
||||
if (sysfs_attr_data->post_set != NULL)
|
||||
{
|
||||
status = (sysfs_attr_data->post_set)(client, udata, info);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: post_set function fails for %s attribute\n", __FUNCTION__, udata->aname);
|
||||
}
|
||||
|
||||
mutex_unlock(&info->update_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fan_update_attr(struct device *dev, struct fan_attr_info *info, FAN_DATA_ATTR *udata)
|
||||
{
|
||||
int status = 0;
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
FAN_SYSFS_ATTR_DATA *sysfs_attr_data = NULL;
|
||||
|
||||
|
||||
mutex_lock(&info->update_lock);
|
||||
|
||||
if (time_after(jiffies, info->last_updated + HZ + HZ / 2) || !info->valid)
|
||||
{
|
||||
dev_dbg(&client->dev, "Starting pddf_fan update\n");
|
||||
info->valid = 0;
|
||||
|
||||
sysfs_attr_data = udata->access_data;
|
||||
if (sysfs_attr_data->pre_get != NULL)
|
||||
{
|
||||
status = (sysfs_attr_data->pre_get)(client, udata, info);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, udata->aname);
|
||||
}
|
||||
if (sysfs_attr_data->do_get != NULL)
|
||||
{
|
||||
status = (sysfs_attr_data->do_get)(client, udata, info);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, udata->aname);
|
||||
|
||||
}
|
||||
if (sysfs_attr_data->post_get != NULL)
|
||||
{
|
||||
status = (sysfs_attr_data->post_get)(client, udata, info);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, udata->aname);
|
||||
}
|
||||
|
||||
|
||||
info->last_updated = jiffies;
|
||||
info->valid = 1;
|
||||
}
|
||||
|
||||
mutex_unlock(&info->update_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t fan_show_default(struct device *dev, struct device_attribute *da, char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct fan_data *data = i2c_get_clientdata(client);
|
||||
FAN_PDATA *pdata = (FAN_PDATA *)(client->dev.platform_data);
|
||||
FAN_DATA_ATTR *usr_data = NULL;
|
||||
struct fan_attr_info *attr_info = NULL;
|
||||
int i, status=0;
|
||||
char new_str[ATTR_NAME_LEN] = "";
|
||||
FAN_SYSFS_ATTR_DATA *ptr = NULL;
|
||||
|
||||
for (i=0;i<data->num_attr;i++)
|
||||
{
|
||||
ptr = (FAN_SYSFS_ATTR_DATA *)pdata->fan_attrs[i].access_data;
|
||||
get_fan_duplicate_sysfs(ptr->index , new_str);
|
||||
if (strcmp(attr->dev_attr.attr.name, pdata->fan_attrs[i].aname) == 0 || strcmp(attr->dev_attr.attr.name, new_str) == 0)
|
||||
{
|
||||
attr_info = &data->attr_info[i];
|
||||
usr_data = &pdata->fan_attrs[i];
|
||||
strcpy(new_str, "");
|
||||
}
|
||||
}
|
||||
|
||||
if (attr_info==NULL || usr_data==NULL)
|
||||
{
|
||||
printk(KERN_ERR "%s is not supported attribute for this client\n", usr_data->aname);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
fan_update_attr(dev, attr_info, usr_data);
|
||||
|
||||
/*Decide the o/p based on attribute type */
|
||||
switch(attr->index)
|
||||
{
|
||||
case FAN1_PRESENT:
|
||||
case FAN2_PRESENT:
|
||||
case FAN3_PRESENT:
|
||||
case FAN4_PRESENT:
|
||||
case FAN5_PRESENT:
|
||||
case FAN6_PRESENT:
|
||||
case FAN7_PRESENT:
|
||||
case FAN8_PRESENT:
|
||||
case FAN9_PRESENT:
|
||||
case FAN10_PRESENT:
|
||||
case FAN11_PRESENT:
|
||||
case FAN12_PRESENT:
|
||||
case FAN1_DIRECTION:
|
||||
case FAN2_DIRECTION:
|
||||
case FAN3_DIRECTION:
|
||||
case FAN4_DIRECTION:
|
||||
case FAN5_DIRECTION:
|
||||
case FAN6_DIRECTION:
|
||||
case FAN7_DIRECTION:
|
||||
case FAN8_DIRECTION:
|
||||
case FAN9_DIRECTION:
|
||||
case FAN10_DIRECTION:
|
||||
case FAN11_DIRECTION:
|
||||
case FAN12_DIRECTION:
|
||||
case FAN1_INPUT:
|
||||
case FAN2_INPUT:
|
||||
case FAN3_INPUT:
|
||||
case FAN4_INPUT:
|
||||
case FAN5_INPUT:
|
||||
case FAN6_INPUT:
|
||||
case FAN7_INPUT:
|
||||
case FAN8_INPUT:
|
||||
case FAN9_INPUT:
|
||||
case FAN10_INPUT:
|
||||
case FAN11_INPUT:
|
||||
case FAN12_INPUT:
|
||||
case FAN1_PWM:
|
||||
case FAN2_PWM:
|
||||
case FAN3_PWM:
|
||||
case FAN4_PWM:
|
||||
case FAN5_PWM:
|
||||
case FAN6_PWM:
|
||||
case FAN7_PWM:
|
||||
case FAN8_PWM:
|
||||
case FAN9_PWM:
|
||||
case FAN10_PWM:
|
||||
case FAN11_PWM:
|
||||
case FAN12_PWM:
|
||||
case FAN1_FAULT:
|
||||
case FAN2_FAULT:
|
||||
case FAN3_FAULT:
|
||||
case FAN4_FAULT:
|
||||
case FAN5_FAULT:
|
||||
case FAN6_FAULT:
|
||||
case FAN7_FAULT:
|
||||
case FAN8_FAULT:
|
||||
case FAN9_FAULT:
|
||||
case FAN10_FAULT:
|
||||
case FAN11_FAULT:
|
||||
case FAN12_FAULT:
|
||||
status = attr_info->val.intval;
|
||||
break;
|
||||
default:
|
||||
fan_dbg(KERN_ERR "%s: Unable to find the attribute index for %s\n", __FUNCTION__, usr_data->aname);
|
||||
status = 0;
|
||||
}
|
||||
|
||||
exit:
|
||||
return sprintf(buf, "%d\n", status);
|
||||
}
|
||||
|
||||
|
||||
ssize_t fan_store_default(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct fan_data *data = i2c_get_clientdata(client);
|
||||
FAN_PDATA *pdata = (FAN_PDATA *)(client->dev.platform_data);
|
||||
FAN_DATA_ATTR *usr_data = NULL;
|
||||
struct fan_attr_info *attr_info = NULL;
|
||||
int i, ret ;
|
||||
uint32_t val;
|
||||
|
||||
for (i=0;i<data->num_attr;i++)
|
||||
{
|
||||
if (strcmp(data->attr_info[i].name, attr->dev_attr.attr.name) == 0 && strcmp(pdata->fan_attrs[i].aname, attr->dev_attr.attr.name) == 0)
|
||||
{
|
||||
attr_info = &data->attr_info[i];
|
||||
usr_data = &pdata->fan_attrs[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (attr_info==NULL || usr_data==NULL) {
|
||||
printk(KERN_ERR "%s is not supported attribute for this client\n", attr->dev_attr.attr.name);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch(attr->index)
|
||||
{
|
||||
case FAN1_PWM:
|
||||
case FAN2_PWM:
|
||||
case FAN3_PWM:
|
||||
case FAN4_PWM:
|
||||
case FAN5_PWM:
|
||||
case FAN6_PWM:
|
||||
case FAN7_PWM:
|
||||
case FAN8_PWM:
|
||||
case FAN9_PWM:
|
||||
case FAN10_PWM:
|
||||
case FAN11_PWM:
|
||||
case FAN12_PWM:
|
||||
ret = kstrtoint(buf, 10, &val);
|
||||
if (ret)
|
||||
{
|
||||
printk(KERN_ERR "%s: Unable to convert string into value for %s\n", __FUNCTION__, usr_data->aname);
|
||||
return ret;
|
||||
}
|
||||
/*Update the value of attr_info here, and use it to update the HW values*/
|
||||
attr_info->val.intval = val;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "%s: Unable to find the attr index for %s\n", __FUNCTION__, usr_data->aname);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
fan_dbg(KERN_ERR "%s: pwm to be set is %d\n", __FUNCTION__, val);
|
||||
fan_update_hw(dev, attr_info, usr_data);
|
||||
|
||||
exit:
|
||||
return count;
|
||||
}
|
||||
|
||||
int fan_cpld_client_read(FAN_DATA_ATTR *udata)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
if (udata!=NULL)
|
||||
{
|
||||
if (udata->len==1)
|
||||
{
|
||||
status = board_i2c_cpld_read(udata->devaddr , udata->offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the I2C client for the CPLD */
|
||||
struct i2c_client *client_ptr=NULL;
|
||||
client_ptr = (struct i2c_client *)get_device_table(udata->devname);
|
||||
if (client_ptr)
|
||||
{
|
||||
if (udata->len==2)
|
||||
{
|
||||
status = i2c_smbus_read_word_swapped(client_ptr, udata->offset);
|
||||
}
|
||||
else
|
||||
printk(KERN_ERR "PDDF_FAN: Doesn't support block CPLD read yet");
|
||||
}
|
||||
else
|
||||
printk(KERN_ERR "Unable to get the client handle for %s\n", udata->devname);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int sonic_i2c_get_fan_present_default(void *client, FAN_DATA_ATTR *udata, void *info)
|
||||
{
|
||||
int status = 0;
|
||||
int val = 0;
|
||||
struct fan_attr_info *painfo = (struct fan_attr_info *)info;
|
||||
|
||||
if (strcmp(udata->devtype, "cpld") == 0)
|
||||
{
|
||||
val = fan_cpld_client_read(udata);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset);
|
||||
}
|
||||
|
||||
painfo->val.intval = ((val & udata->mask) == udata->cmpval);
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_fan_rpm_default(void *client, FAN_DATA_ATTR *udata, void *info)
|
||||
{
|
||||
int status = 0;
|
||||
uint32_t val = 0;
|
||||
struct fan_attr_info *painfo = (struct fan_attr_info *)info;
|
||||
|
||||
if (strcmp(udata->devtype, "cpld") == 0)
|
||||
{
|
||||
val = fan_cpld_client_read(udata);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (udata->len == 1)
|
||||
{
|
||||
val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset);
|
||||
}
|
||||
else if (udata->len ==2)
|
||||
{
|
||||
val = i2c_smbus_read_word_swapped((struct i2c_client *)client, udata->offset);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (udata->is_divisor)
|
||||
painfo->val.intval = udata->mult / (val >> 3);
|
||||
else
|
||||
painfo->val.intval = udata->mult * val;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int sonic_i2c_get_fan_direction_default(void *client, FAN_DATA_ATTR *udata, void *info)
|
||||
{
|
||||
int status = 0;
|
||||
uint32_t val = 0;
|
||||
struct fan_attr_info *painfo = (struct fan_attr_info *)info;
|
||||
|
||||
if (strcmp(udata->devtype, "cpld") == 0)
|
||||
{
|
||||
val = fan_cpld_client_read(udata);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset);
|
||||
}
|
||||
painfo->val.intval = ((val & udata->mask) == udata->cmpval);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int sonic_i2c_set_fan_pwm_default(struct i2c_client *client, FAN_DATA_ATTR *udata, void *info)
|
||||
{
|
||||
int status = 0;
|
||||
uint32_t val = 0;
|
||||
struct fan_attr_info *painfo = (struct fan_attr_info *)info;
|
||||
|
||||
val = painfo->val.intval & udata->mask;
|
||||
|
||||
if (val > 255)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (strcmp(udata->devtype, "cpld") == 0)
|
||||
{
|
||||
if (udata->len==1)
|
||||
{
|
||||
status = board_i2c_cpld_write(udata->devaddr , udata->offset, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the I2C client for the CPLD */
|
||||
struct i2c_client *client_ptr=NULL;
|
||||
client_ptr = (struct i2c_client *)get_device_table(udata->devname);
|
||||
if (client_ptr)
|
||||
{
|
||||
if (udata->len==2)
|
||||
{
|
||||
uint8_t val_lsb = val & 0xFF;
|
||||
uint8_t val_hsb = (val >> 8) & 0xFF;
|
||||
/* TODO: Check this logic for LE and BE */
|
||||
i2c_smbus_write_byte_data(client, udata->offset, val_lsb);
|
||||
i2c_smbus_write_byte_data(client, udata->offset+1, val_hsb);
|
||||
}
|
||||
else
|
||||
printk(KERN_ERR "PDDF_FAN: Doesn't support block CPLD write yet");
|
||||
}
|
||||
else
|
||||
printk(KERN_ERR "Unable to get the client handle for %s\n", udata->devname);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (udata->len == 1)
|
||||
i2c_smbus_write_byte_data(client, udata->offset, val);
|
||||
else if (udata->len == 2)
|
||||
{
|
||||
uint8_t val_lsb = val & 0xFF;
|
||||
uint8_t val_hsb = (val >> 8) & 0xFF;
|
||||
/* TODO: Check this logic for LE and BE */
|
||||
i2c_smbus_write_byte_data(client, udata->offset, val_lsb);
|
||||
i2c_smbus_write_byte_data(client, udata->offset+1, val_hsb);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_DEBUG "%s: pwm should be of len 1/2 bytes. Not setting the pwm as the length is %d\n", __FUNCTION__, udata->len);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int sonic_i2c_get_fan_pwm_default(void *client, FAN_DATA_ATTR *udata, void *info)
|
||||
{
|
||||
int status = 0;
|
||||
uint32_t val = 0;
|
||||
struct fan_attr_info *painfo = (struct fan_attr_info *)info;
|
||||
|
||||
if (strcmp(udata->devtype, "cpld") == 0)
|
||||
{
|
||||
val = fan_cpld_client_read(udata);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (udata->len == 1)
|
||||
{
|
||||
val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset);
|
||||
}
|
||||
else if (udata->len ==2)
|
||||
{
|
||||
val = i2c_smbus_read_word_swapped((struct i2c_client *)client, udata->offset);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
val = val & udata->mask;
|
||||
painfo->val.intval = val;
|
||||
return status;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_fan_fault_default(void *client, FAN_DATA_ATTR *udata, void *info)
|
||||
{
|
||||
int status = 0;
|
||||
uint32_t val = 0;
|
||||
struct fan_attr_info *painfo = (struct fan_attr_info *)info;
|
||||
|
||||
/*Assuming fan fault to be denoted by 1 byte only*/
|
||||
if (strcmp(udata->devtype, "cpld") == 0)
|
||||
{
|
||||
val = fan_cpld_client_read(udata);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset);
|
||||
}
|
||||
|
||||
val = val & udata->mask;
|
||||
painfo->val.intval = val;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int pddf_fan_post_probe_default(struct i2c_client *client, const struct i2c_device_id *dev_id)
|
||||
{
|
||||
|
||||
/*Dummy func for now - check the respective platform modules*/
|
||||
return 0;
|
||||
}
|
496
platform/pddf/i2c/modules/fan/driver/pddf_fan_driver.c
Normal file
496
platform/pddf/i2c/modules/fan/driver/pddf_fan_driver.c
Normal file
@ -0,0 +1,496 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* A pddf kernel driver module for a FAN controller
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/kobject.h>
|
||||
#include "pddf_client_defs.h"
|
||||
#include "pddf_fan_defs.h"
|
||||
#include "pddf_fan_driver.h"
|
||||
#include "pddf_fan_api.h"
|
||||
|
||||
#define DRVNAME "pddf_fan"
|
||||
|
||||
struct pddf_ops_t pddf_fan_ops = {
|
||||
.pre_init = NULL,
|
||||
.post_init = NULL,
|
||||
|
||||
.pre_probe = NULL,
|
||||
.post_probe = pddf_fan_post_probe_default,
|
||||
|
||||
.pre_remove = NULL,
|
||||
.post_remove = NULL,
|
||||
|
||||
.pre_exit = NULL,
|
||||
.post_exit = NULL,
|
||||
};
|
||||
EXPORT_SYMBOL(pddf_fan_ops);
|
||||
|
||||
|
||||
|
||||
FAN_SYSFS_ATTR_DATA data_fan1_present = {FAN1_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan1_present);
|
||||
FAN_SYSFS_ATTR_DATA data_fan2_present = {FAN2_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan2_present);
|
||||
FAN_SYSFS_ATTR_DATA data_fan3_present = {FAN3_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan3_present);
|
||||
FAN_SYSFS_ATTR_DATA data_fan4_present = {FAN4_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan4_present);
|
||||
FAN_SYSFS_ATTR_DATA data_fan5_present = {FAN5_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan5_present);
|
||||
FAN_SYSFS_ATTR_DATA data_fan6_present = {FAN6_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan6_present);
|
||||
FAN_SYSFS_ATTR_DATA data_fan7_present = {FAN7_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan7_present);
|
||||
FAN_SYSFS_ATTR_DATA data_fan8_present = {FAN8_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan8_present);
|
||||
FAN_SYSFS_ATTR_DATA data_fan9_present = {FAN9_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan9_present);
|
||||
FAN_SYSFS_ATTR_DATA data_fan10_present = {FAN10_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan10_present);
|
||||
FAN_SYSFS_ATTR_DATA data_fan11_present = {FAN11_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan11_present);
|
||||
FAN_SYSFS_ATTR_DATA data_fan12_present = {FAN12_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan12_present);
|
||||
|
||||
|
||||
FAN_SYSFS_ATTR_DATA data_fan1_direction = {FAN1_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan1_direction);
|
||||
FAN_SYSFS_ATTR_DATA data_fan2_direction = {FAN2_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan2_direction);
|
||||
FAN_SYSFS_ATTR_DATA data_fan3_direction = {FAN3_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan3_direction);
|
||||
FAN_SYSFS_ATTR_DATA data_fan4_direction = {FAN4_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan4_direction);
|
||||
FAN_SYSFS_ATTR_DATA data_fan5_direction = {FAN5_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan5_direction);
|
||||
FAN_SYSFS_ATTR_DATA data_fan6_direction = {FAN6_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan6_direction);
|
||||
FAN_SYSFS_ATTR_DATA data_fan7_direction = {FAN7_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan7_direction);
|
||||
FAN_SYSFS_ATTR_DATA data_fan8_direction = {FAN8_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan8_direction);
|
||||
FAN_SYSFS_ATTR_DATA data_fan9_direction = {FAN9_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan9_direction);
|
||||
FAN_SYSFS_ATTR_DATA data_fan10_direction = {FAN10_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan10_direction);
|
||||
FAN_SYSFS_ATTR_DATA data_fan11_direction = {FAN11_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan11_direction);
|
||||
FAN_SYSFS_ATTR_DATA data_fan12_direction = {FAN12_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan12_direction);
|
||||
|
||||
|
||||
FAN_SYSFS_ATTR_DATA data_fan1_input = {FAN1_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan1_input);
|
||||
FAN_SYSFS_ATTR_DATA data_fan2_input = {FAN2_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan2_input);
|
||||
FAN_SYSFS_ATTR_DATA data_fan3_input = {FAN3_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan3_input);
|
||||
FAN_SYSFS_ATTR_DATA data_fan4_input = {FAN4_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan4_input);
|
||||
FAN_SYSFS_ATTR_DATA data_fan5_input = {FAN5_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan5_input);
|
||||
FAN_SYSFS_ATTR_DATA data_fan6_input = {FAN6_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan6_input);
|
||||
FAN_SYSFS_ATTR_DATA data_fan7_input = {FAN7_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan7_input);
|
||||
FAN_SYSFS_ATTR_DATA data_fan8_input = {FAN8_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan8_input);
|
||||
FAN_SYSFS_ATTR_DATA data_fan9_input = {FAN9_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan9_input);
|
||||
FAN_SYSFS_ATTR_DATA data_fan10_input = {FAN10_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan10_input);
|
||||
FAN_SYSFS_ATTR_DATA data_fan11_input = {FAN11_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan11_input);
|
||||
FAN_SYSFS_ATTR_DATA data_fan12_input = {FAN12_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan12_input);
|
||||
|
||||
|
||||
FAN_SYSFS_ATTR_DATA data_fan1_pwm = {FAN1_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan1_pwm);
|
||||
FAN_SYSFS_ATTR_DATA data_fan2_pwm = {FAN2_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan2_pwm);
|
||||
FAN_SYSFS_ATTR_DATA data_fan3_pwm = {FAN3_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan3_pwm);
|
||||
FAN_SYSFS_ATTR_DATA data_fan4_pwm = {FAN4_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan4_pwm);
|
||||
FAN_SYSFS_ATTR_DATA data_fan5_pwm = {FAN5_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan5_pwm);
|
||||
FAN_SYSFS_ATTR_DATA data_fan6_pwm = {FAN6_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan6_pwm);
|
||||
FAN_SYSFS_ATTR_DATA data_fan7_pwm = {FAN7_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan7_pwm);
|
||||
FAN_SYSFS_ATTR_DATA data_fan8_pwm = {FAN8_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan8_pwm);
|
||||
FAN_SYSFS_ATTR_DATA data_fan9_pwm = {FAN9_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan9_pwm);
|
||||
FAN_SYSFS_ATTR_DATA data_fan10_pwm = {FAN10_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan10_pwm);
|
||||
FAN_SYSFS_ATTR_DATA data_fan11_pwm = {FAN11_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan11_pwm);
|
||||
FAN_SYSFS_ATTR_DATA data_fan12_pwm = {FAN12_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan12_pwm);
|
||||
|
||||
|
||||
FAN_SYSFS_ATTR_DATA data_fan1_fault = {FAN1_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan1_fault);
|
||||
FAN_SYSFS_ATTR_DATA data_fan2_fault = {FAN2_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan2_fault);
|
||||
FAN_SYSFS_ATTR_DATA data_fan3_fault = {FAN3_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan3_fault);
|
||||
FAN_SYSFS_ATTR_DATA data_fan4_fault = {FAN4_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan4_fault);
|
||||
FAN_SYSFS_ATTR_DATA data_fan5_fault = {FAN5_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan5_fault);
|
||||
FAN_SYSFS_ATTR_DATA data_fan6_fault = {FAN6_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan6_fault);
|
||||
FAN_SYSFS_ATTR_DATA data_fan7_fault = {FAN7_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan7_fault);
|
||||
FAN_SYSFS_ATTR_DATA data_fan8_fault = {FAN8_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan8_fault);
|
||||
FAN_SYSFS_ATTR_DATA data_fan9_fault = {FAN9_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan9_fault);
|
||||
FAN_SYSFS_ATTR_DATA data_fan10_fault = {FAN10_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan10_fault);
|
||||
FAN_SYSFS_ATTR_DATA data_fan11_fault = {FAN11_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan11_fault);
|
||||
FAN_SYSFS_ATTR_DATA data_fan12_fault = {FAN12_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan12_fault);
|
||||
|
||||
|
||||
FAN_SYSFS_ATTR_DATA_ENTRY fan_sysfs_attr_data_tbl[]=
|
||||
{
|
||||
{ "fan1_present", &data_fan1_present},
|
||||
{ "fan2_present", &data_fan2_present},
|
||||
{ "fan3_present", &data_fan3_present},
|
||||
{ "fan4_present", &data_fan4_present},
|
||||
{ "fan5_present", &data_fan5_present},
|
||||
{ "fan6_present", &data_fan6_present},
|
||||
{ "fan7_present", &data_fan7_present},
|
||||
{ "fan8_present", &data_fan8_present},
|
||||
{ "fan9_present", &data_fan9_present},
|
||||
{ "fan10_present", &data_fan10_present},
|
||||
{ "fan11_present", &data_fan11_present},
|
||||
{ "fan12_present", &data_fan12_present},
|
||||
{ "fan1_direction", &data_fan1_direction},
|
||||
{ "fan2_direction", &data_fan2_direction},
|
||||
{ "fan3_direction", &data_fan3_direction},
|
||||
{ "fan4_direction", &data_fan4_direction},
|
||||
{ "fan5_direction", &data_fan5_direction},
|
||||
{ "fan6_direction", &data_fan6_direction},
|
||||
{ "fan7_direction", &data_fan7_direction},
|
||||
{ "fan8_direction", &data_fan8_direction},
|
||||
{ "fan9_direction", &data_fan9_direction},
|
||||
{ "fan10_direction", &data_fan10_direction},
|
||||
{ "fan11_direction", &data_fan11_direction},
|
||||
{ "fan12_direction", &data_fan12_direction},
|
||||
{ "fan1_input", &data_fan1_input},
|
||||
{ "fan2_input", &data_fan2_input},
|
||||
{ "fan3_input", &data_fan3_input},
|
||||
{ "fan4_input", &data_fan4_input},
|
||||
{ "fan5_input", &data_fan5_input},
|
||||
{ "fan6_input", &data_fan6_input},
|
||||
{ "fan7_input", &data_fan7_input},
|
||||
{ "fan8_input", &data_fan8_input},
|
||||
{ "fan9_input", &data_fan9_input},
|
||||
{ "fan10_input", &data_fan10_input},
|
||||
{ "fan11_input", &data_fan11_input},
|
||||
{ "fan12_input", &data_fan12_input},
|
||||
{ "fan1_pwm", &data_fan1_pwm},
|
||||
{ "fan2_pwm", &data_fan2_pwm},
|
||||
{ "fan3_pwm", &data_fan3_pwm},
|
||||
{ "fan4_pwm", &data_fan4_pwm},
|
||||
{ "fan5_pwm", &data_fan5_pwm},
|
||||
{ "fan6_pwm", &data_fan6_pwm},
|
||||
{ "fan7_pwm", &data_fan7_pwm},
|
||||
{ "fan8_pwm", &data_fan8_pwm},
|
||||
{ "fan9_pwm", &data_fan9_pwm},
|
||||
{ "fan10_pwm", &data_fan10_pwm},
|
||||
{ "fan11_pwm", &data_fan11_pwm},
|
||||
{ "fan12_pwm", &data_fan12_pwm},
|
||||
{ "fan1_fault", &data_fan1_fault},
|
||||
{ "fan2_fault", &data_fan2_fault},
|
||||
{ "fan3_fault", &data_fan3_fault},
|
||||
{ "fan4_fault", &data_fan4_fault},
|
||||
{ "fan5_fault", &data_fan5_fault},
|
||||
{ "fan6_fault", &data_fan6_fault},
|
||||
{ "fan7_fault", &data_fan7_fault},
|
||||
{ "fan8_fault", &data_fan8_fault},
|
||||
{ "fan9_fault", &data_fan9_fault},
|
||||
{ "fan10_fault", &data_fan10_fault},
|
||||
{ "fan11_fault", &data_fan11_fault},
|
||||
{ "fan12_fault", &data_fan12_fault},
|
||||
};
|
||||
|
||||
void *get_fan_access_data(char *name)
|
||||
{
|
||||
int i=0;
|
||||
for(i=0; i<(sizeof(fan_sysfs_attr_data_tbl)/sizeof(fan_sysfs_attr_data_tbl[0])); i++)
|
||||
{
|
||||
if(strcmp(name, fan_sysfs_attr_data_tbl[i].name) ==0)
|
||||
{
|
||||
return &fan_sysfs_attr_data_tbl[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(get_fan_access_data);
|
||||
|
||||
|
||||
|
||||
static int pddf_fan_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *dev_id)
|
||||
{
|
||||
struct fan_data *data;
|
||||
int status=0,i,num, j=0;
|
||||
FAN_PDATA *fan_platform_data;
|
||||
FAN_DATA_ATTR *data_attr;
|
||||
FAN_SYSFS_ATTR_DATA_ENTRY *sysfs_data_entry;
|
||||
char new_str[ATTR_NAME_LEN] = "";
|
||||
|
||||
if (client == NULL) {
|
||||
printk("NULL Client.. \n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (pddf_fan_ops.pre_probe)
|
||||
{
|
||||
status = (pddf_fan_ops.pre_probe)(client, dev_id);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
|
||||
status = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Add support for a pre probe function */
|
||||
data = kzalloc(sizeof(struct fan_data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
status = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
dev_info(&client->dev, "chip found\n");
|
||||
|
||||
|
||||
/*Take control of the platform data*/
|
||||
fan_platform_data = (FAN_PDATA *)(client->dev.platform_data);
|
||||
num = fan_platform_data->len;
|
||||
data->num_attr = num;
|
||||
|
||||
for (i=0;i<num;i++)
|
||||
{
|
||||
/*struct attribute *aptr = NULL;*/
|
||||
struct sensor_device_attribute *dy_ptr = NULL;
|
||||
data_attr = fan_platform_data->fan_attrs + i;
|
||||
sysfs_data_entry = get_fan_access_data(data_attr->aname);
|
||||
if (sysfs_data_entry == NULL)
|
||||
{
|
||||
printk(KERN_ERR "%s: Wrong attribute name provided by user '%s'\n", __FUNCTION__, data_attr->aname);
|
||||
continue;
|
||||
}
|
||||
|
||||
dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL);
|
||||
dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1];
|
||||
strcpy((char *)dy_ptr->dev_attr.attr.name, data_attr->aname);
|
||||
dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode;
|
||||
dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show;
|
||||
dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store;
|
||||
dy_ptr->index = sysfs_data_entry->a_ptr->index;
|
||||
|
||||
data->fan_attribute_list[i] = &dy_ptr->dev_attr.attr;
|
||||
strcpy(data->attr_info[i].name, data_attr->aname);
|
||||
data->attr_info[i].valid = 0;
|
||||
mutex_init(&data->attr_info[i].update_lock);
|
||||
|
||||
/*Create a duplicate entry*/
|
||||
get_fan_duplicate_sysfs(dy_ptr->index, new_str);
|
||||
if (strcmp(new_str,""))
|
||||
{
|
||||
dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL);
|
||||
dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1];
|
||||
strcpy((char *)dy_ptr->dev_attr.attr.name, new_str);
|
||||
dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode;
|
||||
dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show;
|
||||
dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store;
|
||||
dy_ptr->index = sysfs_data_entry->a_ptr->index;
|
||||
|
||||
data->fan_attribute_list[num+j] = &dy_ptr->dev_attr.attr;
|
||||
j++;
|
||||
strcpy(new_str, "");
|
||||
}
|
||||
}
|
||||
data->fan_attribute_list[i+j] = NULL;
|
||||
data->fan_attribute_group.attrs = data->fan_attribute_list;
|
||||
|
||||
/* Register sysfs hooks */
|
||||
status = sysfs_create_group(&client->dev.kobj, &data->fan_attribute_group);
|
||||
if (status) {
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
status = PTR_ERR(data->hwmon_dev);
|
||||
goto exit_remove;
|
||||
}
|
||||
|
||||
dev_info(&client->dev, "%s: fan '%s'\n",
|
||||
dev_name(data->hwmon_dev), client->name);
|
||||
|
||||
/* Add a support for post probe function */
|
||||
if (pddf_fan_ops.post_probe)
|
||||
{
|
||||
status = (pddf_fan_ops.post_probe)(client, dev_id);
|
||||
if (status != 0)
|
||||
goto exit_remove;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
exit_remove:
|
||||
sysfs_remove_group(&client->dev.kobj, &data->fan_attribute_group);
|
||||
exit_free:
|
||||
/* Free all the allocated attributes */
|
||||
for (i=0; data->fan_attribute_list[i]!=NULL; i++)
|
||||
{
|
||||
struct sensor_device_attribute *ptr = (struct sensor_device_attribute *)data->fan_attribute_list[i];
|
||||
kfree(ptr);
|
||||
}
|
||||
pddf_dbg(FAN, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__);
|
||||
kfree(data);
|
||||
exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
static int pddf_fan_remove(struct i2c_client *client)
|
||||
{
|
||||
int i = 0, ret = 0;
|
||||
struct sensor_device_attribute *ptr = NULL;
|
||||
struct fan_data *data = i2c_get_clientdata(client);
|
||||
FAN_PDATA *platdata = (FAN_PDATA *)client->dev.platform_data;
|
||||
FAN_DATA_ATTR *platdata_sub = platdata->fan_attrs;
|
||||
|
||||
if (pddf_fan_ops.pre_remove)
|
||||
{
|
||||
ret = (pddf_fan_ops.pre_remove)(client);
|
||||
if (ret!=0)
|
||||
printk(KERN_ERR "FAN pre_remove function failed\n");
|
||||
}
|
||||
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &data->fan_attribute_group);
|
||||
for (i=0; data->fan_attribute_list[i]!=NULL; i++)
|
||||
{
|
||||
ptr = (struct sensor_device_attribute *)data->fan_attribute_list[i];
|
||||
kfree(ptr);
|
||||
}
|
||||
pddf_dbg(FAN, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__);
|
||||
kfree(data);
|
||||
|
||||
if (platdata_sub) {
|
||||
printk(KERN_DEBUG "%s: Freeing platform subdata\n", __FUNCTION__);
|
||||
kfree(platdata_sub);
|
||||
}
|
||||
if (platdata) {
|
||||
printk(KERN_DEBUG "%s: Freeing platform data\n", __FUNCTION__);
|
||||
kfree(platdata);
|
||||
}
|
||||
|
||||
if (pddf_fan_ops.post_remove)
|
||||
{
|
||||
ret = (pddf_fan_ops.post_remove)(client);
|
||||
if (ret!=0)
|
||||
printk(KERN_ERR "FAN post_remove function failed\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Addresses to scan */
|
||||
static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
|
||||
|
||||
static const struct i2c_device_id pddf_fan_id[] = {
|
||||
{ "fan_ctrl", 0 },
|
||||
{ "fan_cpld", 1 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pddf_fan_id);
|
||||
|
||||
static struct i2c_driver pddf_fan_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = DRVNAME,
|
||||
},
|
||||
.probe = pddf_fan_probe,
|
||||
.remove = pddf_fan_remove,
|
||||
.id_table = pddf_fan_id,
|
||||
.address_list = normal_i2c,
|
||||
};
|
||||
|
||||
static int __init pddf_fan_init(void)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
if (pddf_fan_ops.pre_init)
|
||||
{
|
||||
status = (pddf_fan_ops.pre_init)();
|
||||
if (status!=0)
|
||||
return status;
|
||||
}
|
||||
|
||||
status = i2c_add_driver(&pddf_fan_driver);
|
||||
if (status!=0)
|
||||
return status;
|
||||
|
||||
if (pddf_fan_ops.post_init)
|
||||
{
|
||||
status = (pddf_fan_ops.post_init)();
|
||||
if (status!=0)
|
||||
return status;
|
||||
}
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
static void __exit pddf_fan_exit(void)
|
||||
{
|
||||
if (pddf_fan_ops.pre_exit) (pddf_fan_ops.pre_exit)();
|
||||
i2c_del_driver(&pddf_fan_driver);
|
||||
if (pddf_fan_ops.post_exit) (pddf_fan_ops.post_exit)();
|
||||
}
|
||||
|
||||
module_init(pddf_fan_init);
|
||||
module_exit(pddf_fan_exit);
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("pddf_fan driver");
|
||||
MODULE_LICENSE("GPL");
|
280
platform/pddf/i2c/modules/fan/pddf_fan_module.c
Normal file
280
platform/pddf/i2c/modules/fan/pddf_fan_module.c
Normal file
@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* A pddf kernel module to create I2C client for FAN controller
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/kobject.h>
|
||||
#include "pddf_client_defs.h"
|
||||
#include "pddf_fan_defs.h"
|
||||
|
||||
|
||||
static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
extern void *get_fan_access_data(char *);
|
||||
extern void* get_device_table(char *name);
|
||||
extern void delete_device_table(char *name);
|
||||
|
||||
FAN_DATA fan_data = {0};
|
||||
|
||||
|
||||
|
||||
/* FAN CLIENT DATA */
|
||||
PDDF_DATA_ATTR(num_fantrays, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&fan_data.num_fantrays, NULL);
|
||||
|
||||
PDDF_DATA_ATTR(attr_name, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, (void*)&fan_data.fan_attr.aname, NULL);
|
||||
PDDF_DATA_ATTR(attr_devtype, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 8, (void*)&fan_data.fan_attr.devtype, NULL);
|
||||
PDDF_DATA_ATTR(attr_devname, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 8, (void*)&fan_data.fan_attr.devname, NULL);
|
||||
PDDF_DATA_ATTR(attr_devaddr, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&fan_data.fan_attr.devaddr, NULL);
|
||||
PDDF_DATA_ATTR(attr_offset, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&fan_data.fan_attr.offset, NULL);
|
||||
PDDF_DATA_ATTR(attr_mask, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&fan_data.fan_attr.mask, NULL);
|
||||
PDDF_DATA_ATTR(attr_cmpval, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&fan_data.fan_attr.cmpval, NULL);
|
||||
PDDF_DATA_ATTR(attr_len, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&fan_data.fan_attr.len, NULL);
|
||||
PDDF_DATA_ATTR(attr_mult, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&fan_data.fan_attr.mult, NULL);
|
||||
PDDF_DATA_ATTR(attr_is_divisor, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UCHAR, sizeof(unsigned char), (void*)&fan_data.fan_attr.is_divisor, NULL);
|
||||
PDDF_DATA_ATTR(attr_ops, S_IWUSR, NULL, do_attr_operation, PDDF_CHAR, 8, (void*)&fan_data, NULL);
|
||||
PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, (void*)&fan_data, (void*)&pddf_data);
|
||||
|
||||
|
||||
|
||||
static struct attribute *fan_attributes[] = {
|
||||
&attr_num_fantrays.dev_attr.attr,
|
||||
&attr_attr_name.dev_attr.attr,
|
||||
&attr_attr_devtype.dev_attr.attr,
|
||||
&attr_attr_devname.dev_attr.attr,
|
||||
&attr_attr_devaddr.dev_attr.attr,
|
||||
&attr_attr_offset.dev_attr.attr,
|
||||
&attr_attr_mask.dev_attr.attr,
|
||||
&attr_attr_cmpval.dev_attr.attr,
|
||||
&attr_attr_len.dev_attr.attr,
|
||||
&attr_attr_mult.dev_attr.attr,
|
||||
&attr_attr_is_divisor.dev_attr.attr,
|
||||
&attr_attr_ops.dev_attr.attr,
|
||||
&attr_dev_ops.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group pddf_fan_client_data_group = {
|
||||
.attrs = fan_attributes,
|
||||
};
|
||||
|
||||
|
||||
static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
FAN_DATA *fdata = (FAN_DATA *)(ptr->addr);
|
||||
FAN_SYSFS_ATTR_DATA_ENTRY *entry_ptr;
|
||||
|
||||
|
||||
fdata->fan_attrs[fdata->len] = fdata->fan_attr;
|
||||
entry_ptr = get_fan_access_data(fdata->fan_attrs[fdata->len].aname);
|
||||
if (entry_ptr != NULL && entry_ptr->a_ptr != NULL)
|
||||
{
|
||||
fdata->fan_attrs[fdata->len].access_data = entry_ptr->a_ptr ;
|
||||
}
|
||||
|
||||
fdata->len++;
|
||||
memset(&fdata->fan_attr, 0, sizeof(fdata->fan_attr));
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
struct i2c_board_info *i2c_get_fan_board_info(FAN_DATA *fdata, NEW_DEV_ATTR *cdata)
|
||||
{
|
||||
int num = fdata->len;
|
||||
int i = 0;
|
||||
static struct i2c_board_info board_info;
|
||||
FAN_PDATA *fan_platform_data;
|
||||
|
||||
if (strcmp(cdata->dev_type, "fan_ctrl")==0 ||
|
||||
strcmp(cdata->dev_type, "fan_eeprom")==0 ||
|
||||
strcmp(cdata->dev_type, "fan_cpld")==0 )
|
||||
{
|
||||
/* Allocate the fan_platform_data */
|
||||
fan_platform_data = (FAN_PDATA *)kzalloc(sizeof(FAN_PDATA), GFP_KERNEL);
|
||||
fan_platform_data->fan_attrs = (FAN_DATA_ATTR *)kzalloc(num*sizeof(FAN_DATA_ATTR), GFP_KERNEL);
|
||||
|
||||
|
||||
fan_platform_data->num_fantrays = fdata->num_fantrays;
|
||||
fan_platform_data->len = fdata->len;
|
||||
|
||||
for (i=0;i<num;i++)
|
||||
{
|
||||
fan_platform_data->fan_attrs[i] = fdata->fan_attrs[i];
|
||||
}
|
||||
|
||||
board_info = (struct i2c_board_info) {
|
||||
.platform_data = fan_platform_data,
|
||||
};
|
||||
|
||||
board_info.addr = cdata->dev_addr;
|
||||
strcpy(board_info.type, cdata->dev_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "%s:Unknown type of device %s. Unable to create I2C client for it\n",__FUNCTION__, cdata->dev_type);
|
||||
}
|
||||
|
||||
return &board_info;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
FAN_DATA *fdata = (FAN_DATA *)(ptr->addr);
|
||||
NEW_DEV_ATTR *cdata = (NEW_DEV_ATTR *)(ptr->data);
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_board_info *board_info;
|
||||
struct i2c_client *client_ptr;
|
||||
|
||||
if (strncmp(buf, "add", strlen(buf)-1)==0)
|
||||
{
|
||||
adapter = i2c_get_adapter(cdata->parent_bus);
|
||||
board_info = i2c_get_fan_board_info(fdata, cdata);
|
||||
|
||||
/* Populate the platform data for fan */
|
||||
client_ptr = i2c_new_device(adapter, board_info);
|
||||
|
||||
if(client_ptr != NULL)
|
||||
{
|
||||
i2c_put_adapter(adapter);
|
||||
pddf_dbg(FAN, KERN_ERR "Created a %s client: 0x%p\n", cdata->i2c_name, (void *)client_ptr);
|
||||
add_device_table(cdata->i2c_name, (void*)client_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
i2c_put_adapter(adapter);
|
||||
goto free_data;
|
||||
}
|
||||
}
|
||||
else if (strncmp(buf, "delete", strlen(buf)-1)==0)
|
||||
{
|
||||
/*Get the i2c_client handle for the created client*/
|
||||
client_ptr = (struct i2c_client *)get_device_table(cdata->i2c_name);
|
||||
if (client_ptr)
|
||||
{
|
||||
pddf_dbg(FAN, KERN_ERR "Removing %s client: 0x%p\n", cdata->i2c_name, (void *)client_ptr);
|
||||
i2c_unregister_device(client_ptr);
|
||||
delete_device_table(cdata->i2c_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "Unable to get the client handle for %s\n", cdata->i2c_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s", __FUNCTION__, buf);
|
||||
}
|
||||
|
||||
goto clear_data;
|
||||
|
||||
free_data:
|
||||
if (board_info->platform_data)
|
||||
{
|
||||
FAN_PDATA *fan_platform_data = board_info->platform_data;
|
||||
if (fan_platform_data->fan_attrs)
|
||||
{
|
||||
printk(KERN_ERR "%s: Unable to create i2c client. Freeing the platform subdata\n", __FUNCTION__);
|
||||
kfree(fan_platform_data->fan_attrs);
|
||||
}
|
||||
printk(KERN_ERR "%s: Unable to create i2c client. Freeing the platform data\n", __FUNCTION__);
|
||||
kfree(fan_platform_data);
|
||||
}
|
||||
clear_data:
|
||||
memset(fdata, 0, sizeof(FAN_DATA));
|
||||
/*TODO: free the data cdata->data if data is dynal=mically allocated*/
|
||||
memset(cdata, 0, sizeof(NEW_DEV_ATTR));
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static struct kobject *fan_kobj;
|
||||
static struct kobject *i2c_kobj;
|
||||
|
||||
int __init pddf_data_init(void)
|
||||
{
|
||||
struct kobject *device_kobj;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
pddf_dbg(FAN, "PDDF FAN MODULE.. init\n");
|
||||
|
||||
device_kobj = get_device_i2c_kobj();
|
||||
if(!device_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
fan_kobj = kobject_create_and_add("fan", device_kobj);
|
||||
if(!fan_kobj)
|
||||
return -ENOMEM;
|
||||
i2c_kobj = kobject_create_and_add("i2c", fan_kobj);
|
||||
if(!i2c_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = sysfs_create_group(i2c_kobj, &pddf_clients_data_group);
|
||||
if (ret)
|
||||
{
|
||||
kobject_put(i2c_kobj);
|
||||
kobject_put(fan_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(FAN, "CREATED FAN I2C CLIENTS CREATION SYSFS GROUP\n");
|
||||
|
||||
ret = sysfs_create_group(i2c_kobj, &pddf_fan_client_data_group);
|
||||
if (ret)
|
||||
{
|
||||
sysfs_remove_group(i2c_kobj, &pddf_clients_data_group);
|
||||
kobject_put(i2c_kobj);
|
||||
kobject_put(fan_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(FAN, "CREATED PDDF FAN DATA SYSFS GROUP\n");
|
||||
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit pddf_data_exit(void)
|
||||
{
|
||||
pddf_dbg(FAN, "PDDF FAN MODULE.. exit\n");
|
||||
sysfs_remove_group(i2c_kobj, &pddf_fan_client_data_group);
|
||||
sysfs_remove_group(i2c_kobj, &pddf_clients_data_group);
|
||||
kobject_put(i2c_kobj);
|
||||
kobject_put(fan_kobj);
|
||||
pddf_dbg(FAN, KERN_ERR "%s: Removed the kobjects for 'i2c' and 'fan'\n",__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(pddf_data_init);
|
||||
module_exit(pddf_data_exit);
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("fan platform data");
|
||||
MODULE_LICENSE("GPL");
|
4
platform/pddf/i2c/modules/gpio/Makefile
Normal file
4
platform/pddf/i2c/modules/gpio/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
obj-m := pddf_gpio_module.o
|
||||
|
||||
CFLAGS_$(obj-m):= -I$(M)/modules/include
|
223
platform/pddf/i2c/modules/gpio/pddf_gpio_module.c
Normal file
223
platform/pddf/i2c/modules/gpio/pddf_gpio_module.c
Normal file
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* PDDF generic kernle module to create the I2C client for pca955x type of GPIO module
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/kobject.h>
|
||||
#include "pddf_client_defs.h"
|
||||
#include "pddf_gpio_defs.h"
|
||||
|
||||
|
||||
static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
extern void* get_device_table(char *name);
|
||||
extern void delete_device_table(char *name);
|
||||
|
||||
static int base_gpio_num = 0xf0;
|
||||
GPIO_DATA gpio_data = {0};
|
||||
|
||||
/* GPIO CLIENT DATA */
|
||||
PDDF_DATA_ATTR(gpio_base, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&gpio_data.gpio_base, NULL);
|
||||
PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, (void*)&gpio_data, (void*)&pddf_data);
|
||||
|
||||
|
||||
|
||||
static struct attribute *gpio_attributes[] = {
|
||||
&attr_gpio_base.dev_attr.attr,
|
||||
&attr_dev_ops.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group pddf_gpio_client_data_group = {
|
||||
.attrs = gpio_attributes,
|
||||
};
|
||||
|
||||
|
||||
struct i2c_board_info *i2c_get_gpio_board_info(GPIO_DATA* mdata, NEW_DEV_ATTR *device_data)
|
||||
{
|
||||
static struct i2c_board_info board_info;
|
||||
struct pca953x_platform_data *gpio_platform_data=NULL;
|
||||
int def_num_gpios, base;
|
||||
|
||||
gpio_platform_data = (struct pca953x_platform_data *)kzalloc(sizeof (struct pca953x_platform_data), GFP_KERNEL);
|
||||
|
||||
if (strncmp(device_data->dev_type, "pca9554", strlen("pca9554")) == 0 ||
|
||||
strncmp(device_data->dev_type, "pca9534", strlen("pca9534")) == 0 ||
|
||||
strncmp(device_data->dev_type, "pca9538", strlen("pca9538")) == 0)
|
||||
def_num_gpios = 0x8;
|
||||
else if (strncmp(device_data->dev_type, "pca9555", strlen("pca9555")) == 0 ||
|
||||
strncmp(device_data->dev_type, "pca9535", strlen("pca9535")) == 0 ||
|
||||
strncmp(device_data->dev_type, "pca9539", strlen("pca9539")) == 0 ||
|
||||
strncmp(device_data->dev_type, "pca9575", strlen("pca9575")) == 0)
|
||||
def_num_gpios = 0x10;
|
||||
else if (strncmp(device_data->dev_type, "pca9698", strlen("pca9698")) == 0 ||
|
||||
strncmp(device_data->dev_type, "pca9505", strlen("pca9505")) == 0)
|
||||
def_num_gpios = 0x28;
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "%s: Unknown type of gpio device\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(mdata->gpio_base == 0) {
|
||||
base = base_gpio_num;
|
||||
base_gpio_num += def_num_gpios;
|
||||
}
|
||||
else {
|
||||
base = mdata->gpio_base;
|
||||
}
|
||||
|
||||
gpio_platform_data->gpio_base = base;
|
||||
|
||||
board_info = (struct i2c_board_info) {
|
||||
.platform_data = gpio_platform_data,
|
||||
};
|
||||
|
||||
board_info.addr = device_data->dev_addr;
|
||||
strcpy(board_info.type, device_data->dev_type);
|
||||
|
||||
return &board_info;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
GPIO_DATA *gpio_ptr = (GPIO_DATA *)(ptr->addr);
|
||||
NEW_DEV_ATTR *device_ptr = (NEW_DEV_ATTR *)(ptr->data);
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_board_info *board_info;
|
||||
struct i2c_client *client_ptr;
|
||||
|
||||
if (strncmp(buf, "add", strlen(buf)-1)==0)
|
||||
{
|
||||
adapter = i2c_get_adapter(device_ptr->parent_bus);
|
||||
board_info = i2c_get_gpio_board_info(gpio_ptr, device_ptr);
|
||||
|
||||
/*pddf_dbg(KERN_ERR "Creating a client %s on 0x%x, platform_data 0x%x\n", board_info->type, board_info->addr, board_info->platform_data);*/
|
||||
client_ptr = i2c_new_device(adapter, board_info);
|
||||
|
||||
i2c_put_adapter(adapter);
|
||||
if (client_ptr != NULL)
|
||||
{
|
||||
pddf_dbg(GPIO, KERN_ERR "Created %s client: 0x%p\n", device_ptr->i2c_name, (void *)client_ptr);
|
||||
add_device_table(device_ptr->i2c_name, (void*)client_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
kfree(board_info);
|
||||
goto free_data;
|
||||
}
|
||||
}
|
||||
else if (strncmp(buf, "delete", strlen(buf)-1)==0)
|
||||
{
|
||||
/*Get the i2c_client handle for the created client*/
|
||||
client_ptr = (struct i2c_client *)get_device_table(device_ptr->i2c_name);
|
||||
if (client_ptr)
|
||||
{
|
||||
struct pca953x_platform_data *gpio_platform_data = (struct pca953x_platform_data *)client_ptr->dev.platform_data;
|
||||
pddf_dbg(GPIO, KERN_ERR "Removing %s client: 0x%p\n", device_ptr->i2c_name, (void *)client_ptr);
|
||||
i2c_unregister_device(client_ptr);
|
||||
/*TODO: Nullyfy the platform data*/
|
||||
if (gpio_platform_data)
|
||||
kfree(gpio_platform_data);
|
||||
delete_device_table(device_ptr->i2c_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "Unable to get the client handle for %s\n", device_ptr->i2c_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s", __FUNCTION__, buf);
|
||||
}
|
||||
|
||||
free_data:
|
||||
memset(gpio_ptr, 0, sizeof(GPIO_DATA));
|
||||
/*TODO: free the device_ptr->data is dynamically allocated*/
|
||||
memset(device_ptr, 0 , sizeof(NEW_DEV_ATTR));
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static struct kobject *gpio_kobj;
|
||||
|
||||
int __init gpio_data_init(void)
|
||||
{
|
||||
struct kobject *device_kobj;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
pddf_dbg(GPIO, "GPIO_DATA MODULE.. init\n");
|
||||
|
||||
device_kobj = get_device_i2c_kobj();
|
||||
if(!device_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
gpio_kobj = kobject_create_and_add("gpio", device_kobj);
|
||||
if(!gpio_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
ret = sysfs_create_group(gpio_kobj, &pddf_clients_data_group);
|
||||
if (ret)
|
||||
{
|
||||
kobject_put(gpio_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(GPIO, "CREATED PDDF I2C CLIENTS CREATION SYSFS GROUP\n");
|
||||
|
||||
ret = sysfs_create_group(gpio_kobj, &pddf_gpio_client_data_group);
|
||||
if (ret)
|
||||
{
|
||||
sysfs_remove_group(gpio_kobj, &pddf_clients_data_group);
|
||||
kobject_put(gpio_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(GPIO, "CREATED GPIO DATA SYSFS GROUP\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit gpio_data_exit(void)
|
||||
{
|
||||
pddf_dbg(GPIO, "GPIO_DATA MODULE.. exit\n");
|
||||
sysfs_remove_group(gpio_kobj, &pddf_gpio_client_data_group);
|
||||
sysfs_remove_group(gpio_kobj, &pddf_clients_data_group);
|
||||
kobject_put(gpio_kobj);
|
||||
pddf_dbg(GPIO, KERN_ERR "%s: Removed the kobjects for 'gpio'\n",__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(gpio_data_init);
|
||||
module_exit(gpio_data_exit);
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("gpio platform data");
|
||||
MODULE_LICENSE("GPL");
|
135
platform/pddf/i2c/modules/include/pddf_client_defs.h
Normal file
135
platform/pddf/i2c/modules/include/pddf_client_defs.h
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description:
|
||||
* Platform I2C client defines/structures header file
|
||||
*/
|
||||
|
||||
#ifndef __PDDF_CLIENT_DEFS_H__
|
||||
#define __PDDF_CLIENT_DEFS_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#define PSU "PDDF_PSU"
|
||||
#define LED "PDDF_LED"
|
||||
#define FAN "PDDF_FAN"
|
||||
#define CLIENT "PDDF_CLIENT"
|
||||
#define CPLD "PDDF_CPLD"
|
||||
#define CPLDMUX "PDDF_CPLDMUX"
|
||||
#define MUX "PDDF_MUX"
|
||||
#define GPIO "PDDF_GPIO"
|
||||
#define SYSSTATUS "PDDF_SYSSTATUS"
|
||||
#define XCVR "PDDF_XCVR"
|
||||
|
||||
#define PDDF_DEBUG
|
||||
#ifdef PDDF_DEBUG
|
||||
#define pddf_dbg(filter,...) printk("%s\t", filter); printk(KERN_CONT __VA_ARGS__)
|
||||
#else
|
||||
#define pddf_dbg(...)
|
||||
#endif
|
||||
|
||||
|
||||
#define GEN_NAME_SIZE 32
|
||||
#define ERR_STR_SIZE 128
|
||||
|
||||
|
||||
typedef struct pddf_data_attribute{
|
||||
struct device_attribute dev_attr;
|
||||
int type;
|
||||
int len;
|
||||
char *addr;
|
||||
char *data;
|
||||
}PDDF_ATTR;
|
||||
|
||||
#define PDDF_DATA_ATTR(_name, _mode, _show, _store, _type, _len, _addr, _data) \
|
||||
struct pddf_data_attribute attr_##_name = { .dev_attr = __ATTR(_name, _mode, _show, _store), \
|
||||
.type = _type , \
|
||||
.len = _len , \
|
||||
.addr = _addr, \
|
||||
.data = _data }
|
||||
|
||||
|
||||
enum attribute_data_type {
|
||||
PDDF_CHAR,
|
||||
PDDF_UCHAR,
|
||||
PDDF_INT_HEX, // integer represented in HEX
|
||||
PDDF_INT_DEC, // integer represented in DECIMAL
|
||||
PDDF_USHORT, // HEX
|
||||
PDDF_UINT32 // HEX
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// PSU Specific details
|
||||
|
||||
typedef struct NEW_DEV_ATTR
|
||||
{
|
||||
char i2c_type[GEN_NAME_SIZE];
|
||||
char i2c_name[GEN_NAME_SIZE];
|
||||
int parent_bus;
|
||||
char dev_type[GEN_NAME_SIZE];
|
||||
int dev_id;
|
||||
int dev_addr;
|
||||
char *data;
|
||||
int error;
|
||||
char errstr[ERR_STR_SIZE];
|
||||
|
||||
}NEW_DEV_ATTR;
|
||||
extern NEW_DEV_ATTR pddf_data;
|
||||
|
||||
extern struct attribute_group pddf_clients_data_group;
|
||||
extern ssize_t store_pddf_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
extern ssize_t show_pddf_data(struct device *dev, struct device_attribute *da, char *buf);
|
||||
struct kobject* get_device_i2c_kobj(void);
|
||||
void set_attr_data(void * ptr);
|
||||
void set_error_code(int, char *);
|
||||
ssize_t show_error_code(struct device *dev, struct device_attribute *da, char *buf);
|
||||
ssize_t show_all_devices(struct device *dev, struct device_attribute *da, char *buf);
|
||||
void traverse_device_table(void );
|
||||
|
||||
|
||||
|
||||
/*Various Ops hook which can be used by vendors to provide some deviation from usual pddf functionality*/
|
||||
struct pddf_ops_t
|
||||
{
|
||||
/*Module init ops*/
|
||||
int (*pre_init)(void);
|
||||
int (*post_init)(void);
|
||||
/*probe ops*/
|
||||
int (*pre_probe)(struct i2c_client *, const struct i2c_device_id *);
|
||||
int (*post_probe)(struct i2c_client *, const struct i2c_device_id *);
|
||||
/*remove ops*/
|
||||
int (*pre_remove)(struct i2c_client *);
|
||||
int (*post_remove)(struct i2c_client *);
|
||||
/*Module exit ops*/
|
||||
void (*pre_exit)(void);
|
||||
void (*post_exit)(void);
|
||||
};
|
||||
|
||||
|
||||
typedef struct PDEVICE
|
||||
{
|
||||
struct hlist_node node;
|
||||
char name[GEN_NAME_SIZE];
|
||||
void *data;
|
||||
|
||||
}PDEVICE;
|
||||
|
||||
void add_device_table(char *name, void *ptr);
|
||||
|
||||
|
||||
#endif
|
31
platform/pddf/i2c/modules/include/pddf_cpld_defs.h
Normal file
31
platform/pddf/i2c/modules/include/pddf_cpld_defs.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description:
|
||||
* Platform CPLD defines/structures header file
|
||||
*/
|
||||
|
||||
#ifndef __PDDF_CPLD_DEFS_H__
|
||||
#define __PDDF_CPLD_DEFS_H__
|
||||
|
||||
/* CPLD DATA - DATA FOR CPLD CLIENT READ/WRITE*/
|
||||
typedef struct CPLD_DATA
|
||||
{
|
||||
struct mutex cpld_lock;
|
||||
uint16_t reg_addr;
|
||||
}PDDF_CPLD_DATA;
|
||||
|
||||
|
||||
#endif
|
76
platform/pddf/i2c/modules/include/pddf_cpldmux_defs.h
Normal file
76
platform/pddf/i2c/modules/include/pddf_cpldmux_defs.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description:
|
||||
* Platform CPLDMUX defines/structures header file
|
||||
*/
|
||||
|
||||
#ifndef __PDDF_CPLDMUX_DEFS_H__
|
||||
#define __PDDF_CPLDMUX_DEFS_H__
|
||||
|
||||
#include <linux/i2c-mux.h>
|
||||
|
||||
#define MAX_CPLDMUX_CHAN 64
|
||||
|
||||
typedef struct CPLDMUX_CHAN_DATA
|
||||
{
|
||||
int chan_num;
|
||||
char chan_device[128]; /* Could be multiple devices, mentioned as " " seperated array */
|
||||
int cpld_devaddr;
|
||||
int cpld_offset;
|
||||
int cpld_sel;
|
||||
int cpld_desel;
|
||||
}PDDF_CPLDMUX_CHAN_DATA;
|
||||
|
||||
/* CPLDMUX DATA - DATA FOR CPLDMUX CLIENT*/
|
||||
typedef struct CPLDMUX_DATA
|
||||
{
|
||||
int base_chan;
|
||||
int num_chan;
|
||||
int chan_cache;
|
||||
uint32_t cpld_addr;
|
||||
char cpld_name[32];
|
||||
PDDF_CPLDMUX_CHAN_DATA chan_data[MAX_CPLDMUX_CHAN];
|
||||
}PDDF_CPLDMUX_DATA;
|
||||
|
||||
typedef struct CPLDMUX_PDATA
|
||||
{
|
||||
int parent_bus;
|
||||
int base_chan;
|
||||
int num_chan;
|
||||
int chan_cache;
|
||||
struct i2c_client *cpld;
|
||||
PDDF_CPLDMUX_CHAN_DATA *chan_data;
|
||||
}PDDF_CPLDMUX_PDATA;
|
||||
|
||||
typedef struct CPLDMUX_PRIV_DATA{
|
||||
struct i2c_adapter *parent;
|
||||
uint32_t last_chan; /* Will be used in case channel caching is enabled */
|
||||
PDDF_CPLDMUX_PDATA data;
|
||||
}PDDF_CPLDMUX_PRIV_DATA;
|
||||
|
||||
typedef struct pldmux_ops_t
|
||||
{
|
||||
int (*select)(struct i2c_mux_core *muxc, uint32_t chan);
|
||||
int (*deselect)(struct i2c_mux_core *muxc, uint32_t chan);
|
||||
}PDDF_CPLDMUX_OPS;
|
||||
|
||||
int pddf_cpldmux_select_default(struct i2c_mux_core *muxc, uint32_t chan);
|
||||
int pddf_cpldmux_deselect_default(struct i2c_mux_core *muxc, uint32_t chan);
|
||||
|
||||
extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||
extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
||||
|
||||
#endif
|
37
platform/pddf/i2c/modules/include/pddf_fan_api.h
Normal file
37
platform/pddf/i2c/modules/include/pddf_fan_api.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Description
|
||||
* FAN driver api declarations
|
||||
*/
|
||||
|
||||
#ifndef __PDDF_FAN_API_H__
|
||||
#define __PDDF_FAN_API_H__
|
||||
|
||||
extern int pddf_fan_post_probe_default(struct i2c_client *client, const struct i2c_device_id *dev_id);
|
||||
|
||||
extern void get_fan_duplicate_sysfs(int idx, char *str);
|
||||
extern ssize_t fan_show_default(struct device *dev, struct device_attribute *da, char *buf);
|
||||
extern ssize_t fan_store_default(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
|
||||
|
||||
extern int sonic_i2c_get_fan_present_default(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_fan_rpm_default(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_fan_direction_default(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_fan_pwm_default(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_fan_fault_default(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_set_fan_pwm_default(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
|
||||
#endif
|
91
platform/pddf/i2c/modules/include/pddf_fan_defs.h
Normal file
91
platform/pddf/i2c/modules/include/pddf_fan_defs.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description:
|
||||
* Platform FAN defines/structures header file
|
||||
*/
|
||||
|
||||
#ifndef __PDDF_FAN_DEFS_H__
|
||||
#define __PDDF_FAN_DEFS_H__
|
||||
|
||||
|
||||
#define MAX_NUM_FAN 6
|
||||
#define MAX_FAN_ATTRS 128
|
||||
#define ATTR_NAME_LEN 32
|
||||
#define STR_ATTR_SIZE 32
|
||||
#define DEV_TYPE_LEN 32
|
||||
|
||||
/* Each client has this additional data
|
||||
*/
|
||||
|
||||
typedef struct FAN_DATA_ATTR
|
||||
{
|
||||
char aname[ATTR_NAME_LEN]; // attr name, taken from enum fan_sysfs_attributes
|
||||
char devtype[DEV_TYPE_LEN]; // Type of FAN controller, i.e EMC2305, EMC2302, or FAN-CPLD etc
|
||||
char devname[DEV_TYPE_LEN]; // Name of the device from where this informatin is to be read
|
||||
uint32_t devaddr;
|
||||
uint32_t offset;
|
||||
uint32_t mask;
|
||||
uint32_t cmpval;
|
||||
uint32_t len;
|
||||
int mult; // Multiplication factor to get the actual data
|
||||
uint8_t is_divisor; // Check if the value is a divisor and mult is dividend
|
||||
void *access_data;
|
||||
|
||||
}FAN_DATA_ATTR;
|
||||
|
||||
|
||||
typedef struct FAN_SYSFS_ATTR_DATA
|
||||
{
|
||||
int index;
|
||||
unsigned short mode;
|
||||
ssize_t (*show)(struct device *dev, struct device_attribute *da, char *buf);
|
||||
int (*pre_get)(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
int (*do_get)(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
int (*post_get)(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
ssize_t (*store)(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
int (*pre_set)(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
int (*do_set)(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
int (*post_set)(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
void *data;
|
||||
} FAN_SYSFS_ATTR_DATA;
|
||||
|
||||
typedef struct FAN_SYSFS_ATTR_DATA_ENTRY
|
||||
{
|
||||
char name[ATTR_NAME_LEN];
|
||||
FAN_SYSFS_ATTR_DATA *a_ptr;
|
||||
} FAN_SYSFS_ATTR_DATA_ENTRY;
|
||||
|
||||
|
||||
/* FAN CLIENT DATA - PLATFORM DATA FOR FAN CLIENT */
|
||||
typedef struct FAN_DATA
|
||||
{
|
||||
int num_fantrays; // num of fans controlled by this fan client
|
||||
FAN_DATA_ATTR fan_attr;
|
||||
int len; // no of valid attributes for this fan client
|
||||
FAN_DATA_ATTR fan_attrs[MAX_FAN_ATTRS];
|
||||
}FAN_DATA;
|
||||
|
||||
typedef struct FAN_PDATA
|
||||
{
|
||||
int num_fantrays; // num of fans controlled by this fan client
|
||||
int len; // no of valid attributes for this fan client
|
||||
FAN_DATA_ATTR *fan_attrs;
|
||||
}FAN_PDATA;
|
||||
|
||||
extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||
extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
||||
|
||||
#endif
|
107
platform/pddf/i2c/modules/include/pddf_fan_driver.h
Normal file
107
platform/pddf/i2c/modules/include/pddf_fan_driver.h
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description
|
||||
* FAN driver related data structures
|
||||
*/
|
||||
#ifndef __PDDF_FAN_DRIVER_H__
|
||||
#define __PDDF_FAN_DRIVER_H__
|
||||
|
||||
enum fan_sysfs_attributes {
|
||||
FAN1_PRESENT,
|
||||
FAN2_PRESENT,
|
||||
FAN3_PRESENT,
|
||||
FAN4_PRESENT,
|
||||
FAN5_PRESENT,
|
||||
FAN6_PRESENT,
|
||||
FAN7_PRESENT,
|
||||
FAN8_PRESENT,
|
||||
FAN9_PRESENT,
|
||||
FAN10_PRESENT,
|
||||
FAN11_PRESENT,
|
||||
FAN12_PRESENT,
|
||||
FAN1_DIRECTION,
|
||||
FAN2_DIRECTION,
|
||||
FAN3_DIRECTION,
|
||||
FAN4_DIRECTION,
|
||||
FAN5_DIRECTION,
|
||||
FAN6_DIRECTION,
|
||||
FAN7_DIRECTION,
|
||||
FAN8_DIRECTION,
|
||||
FAN9_DIRECTION,
|
||||
FAN10_DIRECTION,
|
||||
FAN11_DIRECTION,
|
||||
FAN12_DIRECTION,
|
||||
FAN1_INPUT,
|
||||
FAN2_INPUT,
|
||||
FAN3_INPUT,
|
||||
FAN4_INPUT,
|
||||
FAN5_INPUT,
|
||||
FAN6_INPUT,
|
||||
FAN7_INPUT,
|
||||
FAN8_INPUT,
|
||||
FAN9_INPUT,
|
||||
FAN10_INPUT,
|
||||
FAN11_INPUT,
|
||||
FAN12_INPUT,
|
||||
FAN1_PWM,
|
||||
FAN2_PWM,
|
||||
FAN3_PWM,
|
||||
FAN4_PWM,
|
||||
FAN5_PWM,
|
||||
FAN6_PWM,
|
||||
FAN7_PWM,
|
||||
FAN8_PWM,
|
||||
FAN9_PWM,
|
||||
FAN10_PWM,
|
||||
FAN11_PWM,
|
||||
FAN12_PWM,
|
||||
FAN1_FAULT,
|
||||
FAN2_FAULT,
|
||||
FAN3_FAULT,
|
||||
FAN4_FAULT,
|
||||
FAN5_FAULT,
|
||||
FAN6_FAULT,
|
||||
FAN7_FAULT,
|
||||
FAN8_FAULT,
|
||||
FAN9_FAULT,
|
||||
FAN10_FAULT,
|
||||
FAN11_FAULT,
|
||||
FAN12_FAULT,
|
||||
FAN_MAX_ATTR
|
||||
};
|
||||
/* Each client has this additional data */
|
||||
struct fan_attr_info {
|
||||
char name[ATTR_NAME_LEN];
|
||||
struct mutex update_lock;
|
||||
char valid; /* != 0 if registers are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
union {
|
||||
char strval[STR_ATTR_SIZE];
|
||||
int intval;
|
||||
u16 shortval;
|
||||
u8 charval;
|
||||
}val;
|
||||
};
|
||||
|
||||
struct fan_data {
|
||||
struct device *hwmon_dev;
|
||||
int num_attr;
|
||||
struct attribute *fan_attribute_list[MAX_FAN_ATTRS];
|
||||
struct attribute_group fan_attribute_group;
|
||||
struct fan_attr_info attr_info[MAX_FAN_ATTRS];
|
||||
};
|
||||
|
||||
#endif
|
30
platform/pddf/i2c/modules/include/pddf_gpio_defs.h
Normal file
30
platform/pddf/i2c/modules/include/pddf_gpio_defs.h
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description:
|
||||
* Platform GPIO defines/structures header file
|
||||
*/
|
||||
|
||||
#ifndef __PAL_GPIO_DEFS_H__
|
||||
#define __PAL_GPIO_DEFS_H__
|
||||
|
||||
#include <linux/platform_data/pca953x.h>
|
||||
/* GPIO CLIENT DATA*/
|
||||
typedef struct GPIO_DATA
|
||||
{
|
||||
int gpio_base; // base bus number of the gpio pins
|
||||
}GPIO_DATA;
|
||||
|
||||
#endif
|
120
platform/pddf/i2c/modules/include/pddf_led_defs.h
Normal file
120
platform/pddf/i2c/modules/include/pddf_led_defs.h
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description
|
||||
* Platform LED related defines and structures
|
||||
*/
|
||||
|
||||
|
||||
/*****************************************
|
||||
* kobj list
|
||||
*****************************************/
|
||||
|
||||
struct kobject *platform_kobj=NULL;
|
||||
struct kobject *led_kobj=NULL;
|
||||
|
||||
struct kobject *state_attr_kobj=NULL;
|
||||
struct kobject *cur_state_kobj=NULL;
|
||||
|
||||
/*****************************************
|
||||
* Static Data provided from user
|
||||
* space JSON data file
|
||||
*****************************************/
|
||||
#define NAME_SIZE 32
|
||||
typedef enum {
|
||||
STATUS_LED_COLOR_GREEN,
|
||||
STATUS_LED_COLOR_GREEN_BLINK,
|
||||
STATUS_LED_COLOR_RED,
|
||||
STATUS_LED_COLOR_RED_BLINK,
|
||||
STATUS_LED_COLOR_AMBER,
|
||||
STATUS_LED_COLOR_AMBER_BLINK,
|
||||
STATUS_LED_COLOR_BLUE,
|
||||
STATUS_LED_COLOR_BLUE_BLINK,
|
||||
STATUS_LED_COLOR_OFF,
|
||||
MAX_LED_STATUS
|
||||
}LED_STATUS;
|
||||
|
||||
char* LED_STATUS_STR[] = {
|
||||
"STATUS_LED_COLOR_GREEN",
|
||||
"STATUS_LED_COLOR_GREEN_BLINK",
|
||||
"STATUS_LED_COLOR_RED",
|
||||
"STATUS_LED_COLOR_RED_BLINK",
|
||||
"STATUS_LED_COLOR_AMBER",
|
||||
"STATUS_LED_COLOR_AMBER_BLINK",
|
||||
"STATUS_LED_COLOR_BLUE",
|
||||
"STATUS_LED_COLOR_BLUE_BLINK",
|
||||
"STATUS_LED_COLOR_OFF"
|
||||
};
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char bits[NAME_SIZE];
|
||||
int pos;
|
||||
int mask_bits;
|
||||
}MASK_BITS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int swpld_addr;
|
||||
int swpld_addr_offset;
|
||||
MASK_BITS bits;
|
||||
unsigned short value;
|
||||
} LED_DATA;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int state;
|
||||
char color[NAME_SIZE];
|
||||
} CUR_STATE_DATA;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CUR_STATE_DATA cur_state;
|
||||
char device_name[NAME_SIZE];
|
||||
int index;
|
||||
LED_DATA data[MAX_LED_STATUS];
|
||||
int swpld_addr;
|
||||
int swpld_addr_offset;
|
||||
} LED_OPS_DATA;
|
||||
|
||||
typedef enum{
|
||||
LED_SYS,
|
||||
LED_PSU,
|
||||
LED_FAN,
|
||||
LED_FANTRAY,
|
||||
LED_DIAG,
|
||||
LED_LOC,
|
||||
LED_TYPE_MAX
|
||||
} LED_TYPE;
|
||||
char* LED_TYPE_STR[LED_TYPE_MAX] =
|
||||
{
|
||||
"LED_SYS",
|
||||
"LED_PSU",
|
||||
"LED_FAN",
|
||||
"LED_FANTRAY",
|
||||
"LED_DIAG",
|
||||
"LED_LOC",
|
||||
};
|
||||
|
||||
/*****************************************
|
||||
* Data exported from kernel for
|
||||
* user space plugin to get/set
|
||||
*****************************************/
|
||||
#define PDDF_LED_DATA_ATTR( _prefix, _name, _mode, _show, _store, _type, _len, _addr) \
|
||||
struct pddf_data_attribute pddf_dev_##_prefix##_attr_##_name = { .dev_attr = __ATTR(_name, _mode, _show, _store), \
|
||||
.type = _type , \
|
||||
.len = _len , \
|
||||
.addr = _addr }
|
31
platform/pddf/i2c/modules/include/pddf_mux_defs.h
Normal file
31
platform/pddf/i2c/modules/include/pddf_mux_defs.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description:
|
||||
* Platform MUX defines/structures header file
|
||||
*/
|
||||
|
||||
#ifndef __PAL_MUX_DEFS_H__
|
||||
#define __PAL_MUX_DEFS_H__
|
||||
|
||||
#include <linux/platform_data/pca954x.h>
|
||||
|
||||
/* MUX CLIENT DATA - PLATFORM DATA FOR PSU CLIENT */
|
||||
typedef struct MUX_DATA
|
||||
{
|
||||
int virt_bus; // Virtual base bus number of the mux channels
|
||||
}MUX_DATA;
|
||||
|
||||
#endif
|
41
platform/pddf/i2c/modules/include/pddf_psu_api.h
Normal file
41
platform/pddf/i2c/modules/include/pddf_psu_api.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description
|
||||
* PSU driver related api declarations
|
||||
*/
|
||||
|
||||
#ifndef __PDDF_PSU_API_H__
|
||||
#define __PDDF_PSU_API_H__
|
||||
|
||||
extern void get_psu_duplicate_sysfs(int idx, char *str);
|
||||
extern ssize_t psu_show_default(struct device *dev, struct device_attribute *da, char *buf);
|
||||
extern ssize_t psu_store_default(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
|
||||
extern int sonic_i2c_get_psu_present_default(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_psu_power_good_default(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_psu_model_name_default(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_psu_mfr_id_default(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_psu_serial_num_default(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_psu_fan_dir_default(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_psu_v_out_default(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_psu_i_out_default(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_psu_p_out_default(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_psu_fan1_speed_rpm_default(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_psu_temp1_input_default(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_psu_v_in_default(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_psu_i_in_default(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
|
||||
#endif
|
90
platform/pddf/i2c/modules/include/pddf_psu_defs.h
Normal file
90
platform/pddf/i2c/modules/include/pddf_psu_defs.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description:
|
||||
* Platform PSU defines/structures header file
|
||||
*/
|
||||
|
||||
#ifndef __PDDF_PSU_DEFS_H__
|
||||
#define __PDDF_PSU_DEFS_H__
|
||||
|
||||
|
||||
#define MAX_NUM_PSU 5
|
||||
#define MAX_PSU_ATTRS 32
|
||||
#define ATTR_NAME_LEN 32
|
||||
#define STR_ATTR_SIZE 32
|
||||
#define DEV_TYPE_LEN 32
|
||||
|
||||
/* Each client has this additional data
|
||||
*/
|
||||
|
||||
typedef struct PSU_DATA_ATTR
|
||||
{
|
||||
char aname[ATTR_NAME_LEN]; // attr name, taken from enum psu_sysfs_attributes
|
||||
char devtype[DEV_TYPE_LEN]; // either a 'eeprom' or 'cpld', or 'pmbus' attribute
|
||||
char devname[DEV_TYPE_LEN]; // Name of the device from where this sysfs attr is read
|
||||
uint32_t devaddr;
|
||||
uint32_t offset;
|
||||
uint32_t mask;
|
||||
uint32_t cmpval;
|
||||
uint32_t len;
|
||||
void *access_data;
|
||||
|
||||
}PSU_DATA_ATTR;
|
||||
|
||||
typedef struct PSU_SYSFS_ATTR_DATA
|
||||
{
|
||||
int index;
|
||||
unsigned short mode;
|
||||
ssize_t (*show)(struct device *dev, struct device_attribute *da, char *buf);
|
||||
int (*pre_get)(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
int (*do_get)(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
int (*post_get)(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
ssize_t (*store)(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
int (*pre_set)(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
int (*do_set)(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
int (*post_set)(void *client, PSU_DATA_ATTR *adata, void *data);
|
||||
void *data;
|
||||
} PSU_SYSFS_ATTR_DATA;
|
||||
|
||||
typedef struct PSU_SYSFS_ATTR_DATA_ENTRY
|
||||
{
|
||||
char name[ATTR_NAME_LEN];
|
||||
PSU_SYSFS_ATTR_DATA *a_ptr;
|
||||
} PSU_SYSFS_ATTR_DATA_ENTRY;
|
||||
|
||||
|
||||
/* PSU CLIENT DATA - PLATFORM DATA FOR PSU CLIENT */
|
||||
typedef struct PSU_DATA
|
||||
{
|
||||
int idx; // psu index
|
||||
int num_psu_fans;
|
||||
PSU_DATA_ATTR psu_attr;
|
||||
int len; // no of valid attributes for this psu client
|
||||
PSU_DATA_ATTR psu_attrs[MAX_PSU_ATTRS];
|
||||
}PSU_DATA;
|
||||
|
||||
typedef struct PSU_PDATA
|
||||
{
|
||||
int idx; // psu index
|
||||
int num_psu_fans; // num of fans supported by the PSU
|
||||
int len; // no of valid attributes for this psu client
|
||||
PSU_DATA_ATTR *psu_attrs;
|
||||
}PSU_PDATA;
|
||||
|
||||
extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||
extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
||||
|
||||
#endif
|
65
platform/pddf/i2c/modules/include/pddf_psu_driver.h
Normal file
65
platform/pddf/i2c/modules/include/pddf_psu_driver.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description
|
||||
* PSU driver data structures
|
||||
*/
|
||||
#ifndef __PDDF_PSU_DRIVER_H__
|
||||
#define __PDDF_PSU_DRIVER_H__
|
||||
|
||||
enum psu_sysfs_attributes {
|
||||
PSU_PRESENT,
|
||||
PSU_MODEL_NAME,
|
||||
PSU_POWER_GOOD,
|
||||
PSU_MFR_ID,
|
||||
PSU_SERIAL_NUM,
|
||||
PSU_FAN_DIR,
|
||||
PSU_V_OUT,
|
||||
PSU_I_OUT,
|
||||
PSU_P_OUT, /* This is in micro watts to comply with lm-sensors */
|
||||
PSU_FAN1_SPEED,
|
||||
PSU_TEMP1_INPUT,
|
||||
PSU_V_IN,
|
||||
PSU_I_IN,
|
||||
PSU_ATTR_MAX
|
||||
};
|
||||
|
||||
|
||||
/* Every client has psu_data which is divided into per attribute data */
|
||||
struct psu_attr_info {
|
||||
char name[ATTR_NAME_LEN];
|
||||
struct mutex update_lock;
|
||||
char valid; /* !=0 if registers are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
u8 status;
|
||||
union {
|
||||
char strval[STR_ATTR_SIZE];
|
||||
int intval;
|
||||
u16 shortval;
|
||||
u8 charval;
|
||||
}val;
|
||||
};
|
||||
struct psu_data {
|
||||
struct device *hwmon_dev;
|
||||
u8 index;
|
||||
int num_psu_fans;
|
||||
int num_attr;
|
||||
struct attribute *psu_attribute_list[MAX_PSU_ATTRS];
|
||||
struct attribute_group psu_attribute_group;
|
||||
struct psu_attr_info attr_info[MAX_PSU_ATTRS];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
51
platform/pddf/i2c/modules/include/pddf_sysstatus_defs.h
Normal file
51
platform/pddf/i2c/modules/include/pddf_sysstatus_defs.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description
|
||||
* Platform system status module structures
|
||||
*/
|
||||
|
||||
#ifndef __PDDF_SYSSTATUS_DEFS_H__
|
||||
#define __PDDF_SYSSTATUS_DEFS_H__
|
||||
|
||||
|
||||
#define ATTR_NAME_LEN 32
|
||||
#define MAX_ATTRS 32
|
||||
|
||||
|
||||
/* SYSSTATUS CLIENT DATA - PLATFORM DATA FOR SYSSTATUS CLIENT */
|
||||
typedef struct SYSSTATUS_ADDR_ATTR
|
||||
{
|
||||
char aname[ATTR_NAME_LEN]; // attr name
|
||||
uint32_t devaddr;
|
||||
uint32_t offset;
|
||||
uint32_t mask;
|
||||
uint32_t len;
|
||||
|
||||
}SYSSTATUS_ADDR_ATTR;
|
||||
|
||||
|
||||
typedef struct SYSSTATUS_DATA
|
||||
{
|
||||
int len;
|
||||
SYSSTATUS_ADDR_ATTR sysstatus_addr_attr;
|
||||
SYSSTATUS_ADDR_ATTR sysstatus_addr_attrs[MAX_ATTRS];
|
||||
|
||||
}SYSSTATUS_DATA;
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
44
platform/pddf/i2c/modules/include/pddf_xcvr_api.h
Normal file
44
platform/pddf/i2c/modules/include/pddf_xcvr_api.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description
|
||||
* Optics driver related api declarations
|
||||
*/
|
||||
#ifndef __PDDF_XCVR_API_H__
|
||||
#define __PDDF_XCVR_API_H__
|
||||
|
||||
extern int sonic_i2c_get_mod_pres(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data);
|
||||
extern int sonic_i2c_get_mod_reset(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data);
|
||||
extern int sonic_i2c_get_mod_intr_status(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data);
|
||||
extern int sonic_i2c_get_mod_lpmode(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data);
|
||||
extern int sonic_i2c_get_mod_rxlos(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data);
|
||||
extern int sonic_i2c_get_mod_txdisable(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data);
|
||||
extern int sonic_i2c_get_mod_txfault(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data);
|
||||
extern int sonic_i2c_set_mod_lpmode(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data);
|
||||
extern int sonic_i2c_set_mod_reset(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data);
|
||||
extern int sonic_i2c_set_mod_txdisable(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data);
|
||||
|
||||
extern ssize_t get_module_presence(struct device *dev, struct device_attribute *da, char *buf);
|
||||
extern ssize_t get_module_reset(struct device *dev, struct device_attribute *da, char *buf);
|
||||
extern ssize_t set_module_reset(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
extern ssize_t get_module_intr_status(struct device *dev, struct device_attribute *da, char *buf);
|
||||
extern ssize_t get_module_lpmode(struct device *dev, struct device_attribute *da, char *buf);
|
||||
extern ssize_t set_module_lpmode(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
extern ssize_t get_module_rxlos(struct device *dev, struct device_attribute *da, char *buf);
|
||||
extern ssize_t get_module_txdisable(struct device *dev, struct device_attribute *da, char *buf);
|
||||
extern ssize_t set_module_txdisable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
extern ssize_t get_module_txfault(struct device *dev, struct device_attribute *da, char *buf);
|
||||
|
||||
#endif
|
121
platform/pddf/i2c/modules/include/pddf_xcvr_defs.h
Normal file
121
platform/pddf/i2c/modules/include/pddf_xcvr_defs.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description:
|
||||
* Platform SFP defines/structures header file
|
||||
*/
|
||||
|
||||
#ifndef __PDDF_XCVR_DEFS_H__
|
||||
#define __PDDF_XCVR_DEFS_H__
|
||||
|
||||
|
||||
#define MAX_NUM_XCVR 5
|
||||
#define MAX_XCVR_ATTRS 20
|
||||
|
||||
|
||||
typedef struct XCVR_ATTR
|
||||
{
|
||||
char aname[32]; // attr name, taken from enum xcvr_sysfs_attributes
|
||||
char devtype[32]; // either a 'eeprom' or 'cpld', or 'pmbus' attribute
|
||||
char devname[32]; // name of the device from where this sysfs is to be read
|
||||
uint32_t devaddr;
|
||||
uint32_t offset;
|
||||
uint32_t mask;
|
||||
uint32_t cmpval;
|
||||
uint32_t len;
|
||||
|
||||
int (*pre_access)(void *client, void *data);
|
||||
int (*do_access)(void *client, void *data);
|
||||
int (*post_access)(void *client, void *data);
|
||||
|
||||
}XCVR_ATTR;
|
||||
|
||||
/* XCVR CLIENT DATA - PLATFORM DATA FOR XCVR CLIENT */
|
||||
typedef struct XCVR_DATA
|
||||
{
|
||||
int idx; // xcvr index
|
||||
XCVR_ATTR xcvr_attr;
|
||||
int len; // no of valid attributes for this xcvr client
|
||||
XCVR_ATTR xcvr_attrs[MAX_XCVR_ATTRS];
|
||||
}XCVR_DATA;
|
||||
|
||||
typedef struct XCVR_PDATA
|
||||
{
|
||||
int idx; // xcvr index
|
||||
unsigned short addr; // i2c address of the device
|
||||
int len; // no of valid attributes for this xcvr client
|
||||
XCVR_ATTR *xcvr_attrs;
|
||||
}XCVR_PDATA;
|
||||
|
||||
|
||||
#define BIT_INDEX(i) (1ULL << (i))
|
||||
|
||||
/* List of valid port types */
|
||||
typedef enum xcvr_port_type_e {
|
||||
PDDF_PORT_TYPE_INVALID,
|
||||
PDDF_PORT_TYPE_NOT_PRESENT,
|
||||
PDDF_PORT_TYPE_SFP,
|
||||
PDDF_PORT_TYPE_SFP_PLUS,
|
||||
PDDF_PORT_TYPE_QSFP,
|
||||
PDDF_PORT_TYPE_QSFP_PLUS,
|
||||
PDDF_PORT_TYPE_QSFP28
|
||||
} xcvr_port_type_t;
|
||||
|
||||
/* Each client has this additional data
|
||||
*/
|
||||
struct xcvr_data {
|
||||
struct device *xdev;
|
||||
struct mutex update_lock;
|
||||
char valid; /* !=0 if registers are valid */
|
||||
unsigned long last_updated; /* In jiffies */
|
||||
int index; /* port index */
|
||||
xcvr_port_type_t port_type;
|
||||
uint32_t modpres;
|
||||
uint32_t reset;
|
||||
uint32_t intr_status;
|
||||
uint32_t lpmode;
|
||||
uint32_t rxlos;
|
||||
uint32_t txdisable;
|
||||
uint32_t txfault;
|
||||
};
|
||||
|
||||
typedef struct XCVR_SYSFS_ATTR_OPS
|
||||
{
|
||||
int index;
|
||||
ssize_t (*show)(struct device *dev, struct device_attribute *da, char *buf);
|
||||
int (*pre_get)(struct i2c_client *client, XCVR_ATTR *adata, struct xcvr_data *data);
|
||||
int (*do_get)(struct i2c_client *client, XCVR_ATTR *adata, struct xcvr_data *data);
|
||||
int (*post_get)(struct i2c_client *client, XCVR_ATTR *adata, struct xcvr_data *data);
|
||||
ssize_t (*store)(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
int (*pre_set)(struct i2c_client *client, XCVR_ATTR *adata, struct xcvr_data *data);
|
||||
int (*do_set)(struct i2c_client *client, XCVR_ATTR *adata, struct xcvr_data *data);
|
||||
int (*post_set)(struct i2c_client *client, XCVR_ATTR *adata, struct xcvr_data *data);
|
||||
} XCVR_SYSFS_ATTR_OPS;
|
||||
|
||||
enum xcvr_sysfs_attributes {
|
||||
XCVR_PRESENT,
|
||||
XCVR_RESET,
|
||||
XCVR_INTR_STATUS,
|
||||
XCVR_LPMODE,
|
||||
XCVR_RXLOS,
|
||||
XCVR_TXDISABLE,
|
||||
XCVR_TXFAULT,
|
||||
XCVR_ATTR_MAX
|
||||
};
|
||||
|
||||
extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||
extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
||||
|
||||
#endif
|
4
platform/pddf/i2c/modules/led/Makefile
Normal file
4
platform/pddf/i2c/modules/led/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
TARGET := pddf_led_module
|
||||
obj-m := $(TARGET).o
|
||||
|
||||
CFLAGS_$(obj-m):= -I$(M)/modules/include
|
659
platform/pddf/i2c/modules/led/pddf_led_module.c
Normal file
659
platform/pddf/i2c/modules/led/pddf_led_module.c
Normal file
@ -0,0 +1,659 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* A pddf kernel module to manage various LEDs of a switch
|
||||
*/
|
||||
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include "pddf_led_defs.h"
|
||||
#include "pddf_client_defs.h"
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define DEBUG 0
|
||||
LED_OPS_DATA sys_led_ops_data[1]={0};
|
||||
LED_OPS_DATA* psu_led_ops_data=NULL;
|
||||
LED_OPS_DATA diag_led_ops_data[1]= {0};
|
||||
LED_OPS_DATA fan_led_ops_data[1]= {0};
|
||||
LED_OPS_DATA loc_led_ops_data[1]= {0};
|
||||
LED_OPS_DATA* fantray_led_ops_data=NULL;
|
||||
LED_OPS_DATA temp_data={0};
|
||||
LED_OPS_DATA* dev_list[LED_TYPE_MAX] = {
|
||||
sys_led_ops_data,
|
||||
NULL,
|
||||
fan_led_ops_data,
|
||||
NULL,
|
||||
diag_led_ops_data,
|
||||
loc_led_ops_data,
|
||||
};
|
||||
int num_psus = 0;
|
||||
int num_fantrays = 0;
|
||||
|
||||
extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||
extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
||||
extern ssize_t show_pddf_data(struct device *dev, struct device_attribute *da, char *buf);
|
||||
extern ssize_t store_pddf_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
|
||||
static LED_STATUS find_state_index(const char* state_str) {
|
||||
int index;
|
||||
char *ptr = (char *)state_str;
|
||||
while (*ptr && *ptr!= '\n' && *ptr !='\0') ptr++;
|
||||
*ptr='\0';
|
||||
for ( index = 0; index < MAX_LED_STATUS; index++) {
|
||||
/*int rc = strcmp(state_str, LED_STATUS_STR[index]) ;*/
|
||||
if (strcmp(state_str, LED_STATUS_STR[index]) == 0 ) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return MAX_LED_STATUS;
|
||||
}
|
||||
|
||||
static LED_TYPE get_dev_type(char* name)
|
||||
{
|
||||
LED_TYPE ret = LED_TYPE_MAX;
|
||||
if(strcasecmp(name, "SYS_LED")==0) {
|
||||
ret = LED_SYS;
|
||||
} else if(strcasecmp(name, "FAN_LED")==0) {
|
||||
ret = LED_FAN;
|
||||
} else if(strstr(name, "PSU_LED")) {
|
||||
ret = LED_PSU;
|
||||
} else if(strcasecmp(name, "DIAG_LED")==0) {
|
||||
ret = LED_DIAG;
|
||||
} else if(strcasecmp(name, "LOC_LED")==0) {
|
||||
ret = LED_LOC;
|
||||
} else if(strstr(name, "FANTRAY_LED")) {
|
||||
ret = LED_FANTRAY;
|
||||
}
|
||||
#if DEBUG > 1
|
||||
pddf_dbg(LED, KERN_INFO "LED get_dev_type: %s; %d\n", name, ret);
|
||||
#endif
|
||||
return (ret);
|
||||
}
|
||||
static int dev_index_check(LED_TYPE type, int index)
|
||||
{
|
||||
#if DEBUG
|
||||
pddf_dbg(LED, "dev_index_check: type:%s index:%d num_psus:%d num_fantrays:%d\n",
|
||||
LED_TYPE_STR[type], index, num_psus, num_fantrays);
|
||||
#endif
|
||||
switch(type)
|
||||
{
|
||||
case LED_PSU:
|
||||
if(index >= num_psus) return (-1);
|
||||
break;
|
||||
case LED_FANTRAY:
|
||||
if(index >= num_fantrays) return (-1);
|
||||
break;
|
||||
default:
|
||||
if(index >= 1) return (-1);
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static LED_OPS_DATA* find_led_ops_data(struct device_attribute *da)
|
||||
{
|
||||
struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da;
|
||||
LED_OPS_DATA* ptr=(LED_OPS_DATA*)_ptr->addr;
|
||||
LED_TYPE led_type;
|
||||
if(!ptr || strlen(ptr->device_name)==0 ) return(NULL);
|
||||
|
||||
|
||||
if((led_type=get_dev_type(ptr->device_name))==LED_TYPE_MAX) {
|
||||
printk(KERN_ERR "PDDF_LED ERROR *%s Unsupported Led Type\n", __func__);
|
||||
return(NULL);
|
||||
}
|
||||
if(dev_index_check(led_type, ptr->index)==-1) {
|
||||
printk(KERN_ERR "PDDF_LED ERROR %s invalid index: %d for type:%s\n", __func__, ptr->index, ptr->device_name);
|
||||
return(NULL);
|
||||
}
|
||||
#if DEBUG > 1
|
||||
pddf_dbg(LED, "find_led_ops_data: name:%s; index=%d tempAddr:%p actualAddr:%p\n",
|
||||
ptr->device_name, ptr->index, ptr, dev_list[led_type]+ptr->index);
|
||||
#endif
|
||||
return (dev_list[led_type]+ptr->index);
|
||||
}
|
||||
|
||||
static void print_led_data(LED_OPS_DATA *ptr, LED_STATUS state)
|
||||
{
|
||||
int i = 0;
|
||||
if(!ptr) return ;
|
||||
pddf_dbg(LED, KERN_INFO "Print %s index:%d num_psus:%d num_fantrays:%d ADDR=%p\n",
|
||||
ptr->device_name, ptr->index, num_psus, num_fantrays, ptr);
|
||||
pddf_dbg(LED, KERN_INFO "\tindex: %d\n", ptr->index);
|
||||
pddf_dbg(LED, KERN_INFO "\tcur_state: %d; %s \n", ptr->cur_state.state, ptr->cur_state.color);
|
||||
for (i = 0; i< MAX_LED_STATUS; i++) {
|
||||
if(ptr->data[i].swpld_addr && (i == state || state == -1)) {
|
||||
pddf_dbg(LED, KERN_INFO "\t\t[%s]: addr/offset:0x%x;0x%x color:%s; value:%x; mask_bits: 0x%x; pos:%d\n",
|
||||
LED_STATUS_STR[i],
|
||||
ptr->data[i].swpld_addr, ptr->data[i].swpld_addr_offset,
|
||||
LED_STATUS_STR[i], ptr->data[i].value, ptr->data[i].bits.mask_bits, ptr->data[i].bits.pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t get_status_led(struct device_attribute *da)
|
||||
{
|
||||
int ret=0;
|
||||
struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da;
|
||||
LED_OPS_DATA* temp_data_ptr=(LED_OPS_DATA*)_ptr->addr;
|
||||
LED_OPS_DATA* ops_ptr=find_led_ops_data(da);
|
||||
uint32_t color_val=0, sys_val=0;
|
||||
int state=0;
|
||||
if (!ops_ptr) {
|
||||
pddf_dbg(LED, KERN_ERR "ERROR %s: Cannot find LED Ptr", __func__);
|
||||
return (-1);
|
||||
}
|
||||
if (ops_ptr->swpld_addr == 0x0) {
|
||||
pddf_dbg(LED, KERN_ERR "ERROR %s: device: %s %d not configured\n", __func__,
|
||||
temp_data_ptr->device_name, temp_data_ptr->index);
|
||||
return (-1);
|
||||
}
|
||||
sys_val = board_i2c_cpld_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset);
|
||||
if (sys_val < 0)
|
||||
return sys_val;
|
||||
|
||||
strcpy(temp_data.cur_state.color, "None");
|
||||
for (state=0; state<MAX_LED_STATUS; state++) {
|
||||
color_val = (sys_val & ~ops_ptr->data[state].bits.mask_bits);
|
||||
if ((color_val ^ (ops_ptr->data[state].value<<ops_ptr->data[state].bits.pos))==0) {
|
||||
strcpy(temp_data.cur_state.color, LED_STATUS_STR[state]);
|
||||
}
|
||||
}
|
||||
#if DEBUG > 1
|
||||
pddf_dbg(LED, KERN_ERR "Get : %s:%d addr/offset:0x%x; 0x%x value=0x%x [%s]\n",
|
||||
ops_ptr->device_name, ops_ptr->index,
|
||||
ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, sys_val,
|
||||
temp_data.cur_state.color);
|
||||
#endif
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
ssize_t set_status_led(struct device_attribute *da)
|
||||
{
|
||||
int ret=0;
|
||||
uint32_t sys_val=0, new_val=0;
|
||||
LED_STATUS cur_state = MAX_LED_STATUS;
|
||||
struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da;
|
||||
LED_OPS_DATA* temp_data_ptr=(LED_OPS_DATA*)_ptr->addr;
|
||||
LED_OPS_DATA* ops_ptr=find_led_ops_data(da);
|
||||
char* _buf=temp_data_ptr->cur_state.color;
|
||||
|
||||
if (!ops_ptr) {
|
||||
pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR %s: Cannot find LED Ptr", __func__);
|
||||
return (-1);
|
||||
}
|
||||
if (ops_ptr->swpld_addr == 0x0) {
|
||||
pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR %s: device: %s %d not configured\n",
|
||||
__func__, ops_ptr->device_name, ops_ptr->index);
|
||||
return (-1);
|
||||
}
|
||||
pddf_dbg(LED, KERN_ERR "%s: Set [%s;%d] color[%s]\n", __func__,
|
||||
temp_data_ptr->device_name, temp_data_ptr->index,
|
||||
temp_data_ptr->cur_state.color);
|
||||
cur_state = find_state_index(_buf);
|
||||
|
||||
if (cur_state == MAX_LED_STATUS) {
|
||||
pddf_dbg(LED, KERN_ERR "ERROR %s: not supported: %s\n", _buf, __func__);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if(ops_ptr->data[cur_state].swpld_addr != 0x0) {
|
||||
sys_val = board_i2c_cpld_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset);
|
||||
if (sys_val < 0)
|
||||
return sys_val;
|
||||
|
||||
new_val = (sys_val & ops_ptr->data[cur_state].bits.mask_bits) |
|
||||
(ops_ptr->data[cur_state].value << ops_ptr->data[cur_state].bits.pos);
|
||||
|
||||
} else {
|
||||
pddf_dbg(LED, KERN_ERR "ERROR %s: %s %d state %d; %s not configured\n",__func__,
|
||||
ops_ptr->device_name, ops_ptr->index, cur_state, _buf);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
board_i2c_cpld_write(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset, new_val);
|
||||
pddf_dbg(LED, KERN_INFO "Set color:%s; 0x%x:0x%x sys_val:0x%x new_val:0x%x read:0x%x\n",
|
||||
LED_STATUS_STR[cur_state],
|
||||
ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset,
|
||||
sys_val, new_val,
|
||||
ret = board_i2c_cpld_read(ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset));
|
||||
if (ret < 0)
|
||||
{
|
||||
pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR %s: Error %d in reading from cpld(0x%x) offset 0x%x\n", __FUNCTION__, ret, ops_ptr->swpld_addr, ops_ptr->swpld_addr_offset);
|
||||
return ret;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
ssize_t show_pddf_data(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
int ret = 0;
|
||||
struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da;
|
||||
switch(ptr->type)
|
||||
{
|
||||
case PDDF_CHAR:
|
||||
ret = sprintf(buf, "%s\n", ptr->addr);
|
||||
break;
|
||||
case PDDF_INT_DEC:
|
||||
ret = sprintf(buf, "%d\n", *(int*)(ptr->addr));
|
||||
break;
|
||||
case PDDF_INT_HEX:
|
||||
ret = sprintf(buf, "0x%x\n", *(int*)(ptr->addr));
|
||||
break;
|
||||
case PDDF_USHORT:
|
||||
ret = sprintf(buf, "0x%x\n", *(unsigned short *)(ptr->addr));
|
||||
break;
|
||||
case PDDF_UINT32:
|
||||
ret = sprintf(buf, "0x%x\n", *(uint32_t *)(ptr->addr));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#if DEBUG > 1
|
||||
pddf_dbg(LED, "[ READ ] DATA ATTR PTR [%s] TYPE:%d, Value:[%s]\n",
|
||||
ptr->dev_attr.attr.name, ptr->type, buf);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t store_pddf_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
int ret = 0, num = 0;
|
||||
struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da;
|
||||
switch(ptr->type)
|
||||
{
|
||||
case PDDF_CHAR:
|
||||
strncpy(ptr->addr, buf, strlen(buf)-1); // to discard newline char form buf
|
||||
ptr->addr[strlen(buf)-1] = '\0';
|
||||
#if DEBUG
|
||||
pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_CHAR VALUE:%s\n",
|
||||
ptr->dev_attr.attr.name, ptr->addr);
|
||||
#endif
|
||||
break;
|
||||
case PDDF_INT_DEC:
|
||||
ret = kstrtoint(buf,10,&num);
|
||||
if (ret==0)
|
||||
*(int *)(ptr->addr) = num;
|
||||
#if DEBUG
|
||||
pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_DEC VALUE:%d\n",
|
||||
ptr->dev_attr.attr.name, *(int *)(ptr->addr));
|
||||
#endif
|
||||
break;
|
||||
case PDDF_INT_HEX:
|
||||
ret = kstrtoint(buf,16,&num);
|
||||
if (ret==0)
|
||||
*(int *)(ptr->addr) = num;
|
||||
#if DEBUG
|
||||
pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_HEX VALUE:0x%x\n",
|
||||
ptr->dev_attr.attr.name, *(int *)(ptr->addr));
|
||||
#endif
|
||||
break;
|
||||
case PDDF_USHORT:
|
||||
ret = kstrtoint(buf,16,&num);
|
||||
if (ret==0)
|
||||
*(unsigned short *)(ptr->addr) = (unsigned short)num;
|
||||
#if DEBUG
|
||||
pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_USHORT VALUE:%x\n",
|
||||
ptr->dev_attr.attr.name, *(unsigned short *)(ptr->addr));
|
||||
#endif
|
||||
break;
|
||||
case PDDF_UINT32:
|
||||
ret = kstrtoint(buf,16,&num);
|
||||
if (ret==0)
|
||||
*(uint32_t *)(ptr->addr) = (uint32_t)num;
|
||||
#if DEBUG
|
||||
pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR [%s] PDDF_UINT32 VALUE:%d\n",
|
||||
ptr->dev_attr.attr.name, *(uint32_t *)(ptr->addr));
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int load_led_ops_data(struct device_attribute *da, LED_STATUS state)
|
||||
{
|
||||
struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da;
|
||||
LED_OPS_DATA* ptr=(LED_OPS_DATA*)_ptr->addr;
|
||||
LED_TYPE led_type;
|
||||
LED_OPS_DATA* ops_ptr=NULL;
|
||||
if(!ptr || strlen(ptr->device_name)==0 ) {
|
||||
pddf_dbg(LED, KERN_INFO "SYSTEM_LED: load_led_ops_data return -1 device_name:%s\n", ptr? ptr->device_name:"NULL");
|
||||
return(-1);
|
||||
}
|
||||
if(ptr->device_name)
|
||||
{
|
||||
pddf_dbg(LED, KERN_INFO "[%s]: load_led_ops_data: index=%d addr=0x%x;0x%x valu=0x%x\n",
|
||||
ptr->device_name, ptr->index, ptr->swpld_addr, ptr->swpld_addr_offset, ptr->data[0].value);
|
||||
}
|
||||
if((led_type=get_dev_type(ptr->device_name))==LED_TYPE_MAX) {
|
||||
pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR *%s Unsupported Led Type\n", __func__);
|
||||
return(-1);
|
||||
}
|
||||
if(dev_index_check(led_type, ptr->index)==-1) {
|
||||
pddf_dbg(LED, KERN_ERR "PDDF_LED ERROR %s invalid index: %d for type:%d\n", __func__, ptr->index, led_type);
|
||||
return(-1);
|
||||
}
|
||||
ops_ptr = dev_list[led_type]+ptr->index;
|
||||
|
||||
memcpy(ops_ptr->device_name, ptr->device_name, sizeof(ops_ptr->device_name));
|
||||
ops_ptr->index = ptr->index;
|
||||
memcpy(&ops_ptr->data[state], &ptr->data[0], sizeof(LED_DATA));
|
||||
ops_ptr->data[state].swpld_addr = ptr->swpld_addr;
|
||||
ops_ptr->data[state].swpld_addr_offset = ptr->swpld_addr_offset;
|
||||
ops_ptr->swpld_addr = ptr->swpld_addr;
|
||||
ops_ptr->swpld_addr_offset = ptr->swpld_addr_offset;
|
||||
|
||||
print_led_data(dev_list[led_type]+ptr->index, state);
|
||||
|
||||
memset(ptr, 0, sizeof(LED_OPS_DATA));
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int show_led_ops_data(struct device_attribute *da)
|
||||
{
|
||||
LED_OPS_DATA* ops_ptr=find_led_ops_data(da);
|
||||
print_led_data(ops_ptr, -1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int verify_led_ops_data(struct device_attribute *da)
|
||||
{
|
||||
struct pddf_data_attribute *_ptr = (struct pddf_data_attribute *)da;
|
||||
LED_OPS_DATA* ptr=(LED_OPS_DATA*)_ptr->addr;
|
||||
LED_OPS_DATA* ops_ptr=find_led_ops_data(da);
|
||||
|
||||
if(ops_ptr)
|
||||
memcpy(ptr, ops_ptr, sizeof(LED_OPS_DATA));
|
||||
else
|
||||
{
|
||||
pddf_dbg(LED, "SYSTEM_LED: verify_led_ops_data: Failed to find ops_ptr name:%s; index=%d\n", ptr->device_name, ptr->index);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
ssize_t dev_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
#if DEBUG
|
||||
pddf_dbg(LED, KERN_INFO "dev_operation [%s]\n", buf);
|
||||
#endif
|
||||
if(strstr(buf, "STATUS_LED_COLOR")!= NULL) {
|
||||
LED_STATUS index = find_state_index(buf);
|
||||
if (index < MAX_LED_STATUS ) {
|
||||
load_led_ops_data(da, index);
|
||||
} else {
|
||||
printk(KERN_ERR "PDDF_ERROR %s: Invalid state for dev_ops %s", __FUNCTION__, buf);
|
||||
}
|
||||
}
|
||||
else if(strncmp(buf, "show", strlen("show"))==0 ) {
|
||||
show_led_ops_data(da);
|
||||
}
|
||||
else if(strncmp(buf, "verify", strlen("verify"))==0 ) {
|
||||
verify_led_ops_data(da);
|
||||
}
|
||||
else if(strncmp(buf, "get_status", strlen("get_status"))==0 ) {
|
||||
get_status_led(da);
|
||||
}
|
||||
else if(strncmp(buf, "set_status", strlen("set_status"))==0 ) {
|
||||
set_status_led(da);
|
||||
}
|
||||
else {
|
||||
printk(KERN_ERR "PDDF_ERROR %s: Invalid value for dev_ops %s", __FUNCTION__, buf);
|
||||
}
|
||||
return(count);
|
||||
}
|
||||
|
||||
ssize_t store_config_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
int ret, num;
|
||||
struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da;
|
||||
if(strncmp(ptr->dev_attr.attr.name, "num_psus", strlen("num_psus"))==0 ) {
|
||||
ret = kstrtoint(buf,10,&num);
|
||||
if (ret==0)
|
||||
*(int *)(ptr->addr) = num;
|
||||
if(psu_led_ops_data == NULL) {
|
||||
if ((psu_led_ops_data = kzalloc(num * sizeof(LED_OPS_DATA), GFP_KERNEL)) == NULL) {
|
||||
printk(KERN_ERR "PDDF_LED ERROR failed to allocate memory for PSU LED\n");
|
||||
return (count);
|
||||
}
|
||||
pddf_dbg(LED, "Allocate PSU LED Memory ADDR=%p\n", psu_led_ops_data);
|
||||
dev_list[LED_PSU]=psu_led_ops_data;
|
||||
}
|
||||
#if DEBUG
|
||||
pddf_dbg(LED, "[ WRITE ] ATTR CONFIG [%s] VALUE:%d; %d\n",
|
||||
ptr->dev_attr.attr.name, num, num_psus);
|
||||
#endif
|
||||
return(count);
|
||||
}
|
||||
if(strncmp(ptr->dev_attr.attr.name, "num_fantrays", strlen("num_fantrays"))==0 ) {
|
||||
ret = kstrtoint(buf,10,&num);
|
||||
if (ret==0)
|
||||
*(int *)(ptr->addr) = num;
|
||||
if (fantray_led_ops_data == NULL) {
|
||||
if ((fantray_led_ops_data = kzalloc(num * sizeof(LED_OPS_DATA), GFP_KERNEL)) == NULL) {
|
||||
printk(KERN_ERR "PDDF_LED ERROR failed to allocate memory for FANTRAY LED\n");
|
||||
return (count);
|
||||
}
|
||||
pddf_dbg(LED, "Allocate FanTray LED Memory ADDR=%p\n", fantray_led_ops_data);
|
||||
dev_list[LED_FANTRAY]=fantray_led_ops_data;
|
||||
}
|
||||
#if DEBUG
|
||||
pddf_dbg(LED, "[ WRITE ] ATTR CONFIG [%s] VALUE:%d; %d\n",
|
||||
ptr->dev_attr.attr.name, num, num_fantrays);
|
||||
#endif
|
||||
return(count);
|
||||
}
|
||||
return (count);
|
||||
}
|
||||
|
||||
ssize_t store_bits_data(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
int len = 0, num1 = 0, num2 = 0, i=0, rc1=0, rc2=0;
|
||||
char mask=0xFF;
|
||||
char *pptr=NULL;
|
||||
char bits[NAME_SIZE];
|
||||
struct pddf_data_attribute *ptr = (struct pddf_data_attribute *)da;
|
||||
MASK_BITS* bits_ptr=(MASK_BITS*)(ptr->addr);
|
||||
strncpy(bits_ptr->bits, buf, strlen(buf)-1); // to discard newline char form buf
|
||||
bits_ptr->bits[strlen(buf)-1] = '\0';
|
||||
if((pptr=strstr(buf,":")) != NULL) {
|
||||
len=pptr-buf;
|
||||
sprintf(bits, buf);
|
||||
bits[len]='\0';
|
||||
rc1=kstrtoint(bits,16,&num1);
|
||||
if (rc1==0)
|
||||
{
|
||||
sprintf(bits, ++pptr);
|
||||
rc2=kstrtoint(bits,16,&num2);
|
||||
if (rc2==0)
|
||||
{
|
||||
for (i=num2; i<=num1; i++) {
|
||||
mask &= ~(1 << i);
|
||||
}
|
||||
bits_ptr->mask_bits = mask;
|
||||
bits_ptr->pos = num2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rc1=kstrtoint(buf,16,&num1);
|
||||
if (rc1==0)
|
||||
{
|
||||
bits_ptr->mask_bits = mask & ~(1 << num1);
|
||||
bits_ptr->pos = num1;
|
||||
}
|
||||
}
|
||||
#if DEBUG
|
||||
pddf_dbg(LED, KERN_ERR "[ WRITE ] ATTR PTR Bits [%s] VALUE:%s mask:0x%x; pos:0x%x\n",
|
||||
ptr->dev_attr.attr.name, bits_ptr->bits, bits_ptr->mask_bits, bits_ptr->pos);
|
||||
#endif
|
||||
return (count);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* platform/ attributes
|
||||
**************************************************************************/
|
||||
PDDF_LED_DATA_ATTR(platform, num_psus, S_IWUSR|S_IRUGO, show_pddf_data,
|
||||
store_config_data, PDDF_INT_DEC, sizeof(int), (void*)&num_psus);
|
||||
PDDF_LED_DATA_ATTR(platform, num_fantrays, S_IWUSR|S_IRUGO, show_pddf_data,
|
||||
store_config_data, PDDF_INT_DEC, sizeof(int), (void*)&num_fantrays);
|
||||
|
||||
struct attribute* attrs_platform[]={
|
||||
&pddf_dev_platform_attr_num_psus.dev_attr.attr,
|
||||
&pddf_dev_platform_attr_num_fantrays.dev_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
struct attribute_group attr_group_platform={
|
||||
.attrs = attrs_platform,
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
* led/ attributes
|
||||
**************************************************************************/
|
||||
PDDF_LED_DATA_ATTR(dev, device_name, S_IWUSR|S_IRUGO, show_pddf_data,
|
||||
store_pddf_data, PDDF_CHAR, NAME_SIZE, (void*)&temp_data.device_name);
|
||||
PDDF_LED_DATA_ATTR(dev, index, S_IWUSR|S_IRUGO, show_pddf_data,
|
||||
store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&temp_data.index);
|
||||
PDDF_LED_DATA_ATTR(dev, swpld_addr, S_IWUSR|S_IRUGO, show_pddf_data,
|
||||
store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&temp_data.swpld_addr);
|
||||
PDDF_LED_DATA_ATTR(dev, swpld_addr_offset, S_IWUSR|S_IRUGO, show_pddf_data,
|
||||
store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&temp_data.swpld_addr_offset);
|
||||
PDDF_LED_DATA_ATTR(dev, dev_ops , S_IWUSR, NULL,
|
||||
dev_operation, PDDF_CHAR, NAME_SIZE, (void*)&temp_data);
|
||||
|
||||
struct attribute* attrs_dev[]={
|
||||
&pddf_dev_dev_attr_device_name.dev_attr.attr,
|
||||
&pddf_dev_dev_attr_index.dev_attr.attr,
|
||||
&pddf_dev_dev_attr_swpld_addr.dev_attr.attr,
|
||||
&pddf_dev_dev_attr_swpld_addr_offset.dev_attr.attr,
|
||||
&pddf_dev_dev_attr_dev_ops.dev_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
struct attribute_group attr_group_dev={
|
||||
.attrs = attrs_dev,
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
* state_attr/ attributes
|
||||
**************************************************************************/
|
||||
#define LED_DEV_STATE_ATTR_GROUP(name, func) \
|
||||
PDDF_LED_DATA_ATTR(name, bits, S_IWUSR|S_IRUGO, show_pddf_data, \
|
||||
store_bits_data, PDDF_CHAR, NAME_SIZE, func.bits.bits); \
|
||||
PDDF_LED_DATA_ATTR(name, value, S_IWUSR|S_IRUGO, show_pddf_data, \
|
||||
store_pddf_data, PDDF_USHORT, sizeof(unsigned short), func.value); \
|
||||
struct attribute* attrs_##name[]={ \
|
||||
&pddf_dev_##name##_attr_bits.dev_attr.attr, \
|
||||
&pddf_dev_##name##_attr_value.dev_attr.attr, \
|
||||
NULL, \
|
||||
}; \
|
||||
struct attribute_group attr_group_##name={ \
|
||||
.attrs = attrs_##name, \
|
||||
}; \
|
||||
|
||||
|
||||
LED_DEV_STATE_ATTR_GROUP(state_attr, (void*)&temp_data.data[0])
|
||||
|
||||
/**************************************************************************
|
||||
* cur_state/ attributes
|
||||
**************************************************************************/
|
||||
PDDF_LED_DATA_ATTR(cur_state, color, S_IWUSR|S_IRUGO, show_pddf_data,
|
||||
store_pddf_data, PDDF_CHAR, NAME_SIZE, (void*)&temp_data.cur_state.color);
|
||||
|
||||
struct attribute* attrs_cur_state[]={
|
||||
&pddf_dev_cur_state_attr_color.dev_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
struct attribute_group attr_group_cur_state={
|
||||
.attrs = attrs_cur_state,
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
#define KOBJ_FREE(obj) \
|
||||
if(obj) kobject_put(obj); \
|
||||
|
||||
void free_kobjs(void)
|
||||
{
|
||||
KOBJ_FREE(cur_state_kobj)
|
||||
KOBJ_FREE(state_attr_kobj)
|
||||
KOBJ_FREE(led_kobj)
|
||||
KOBJ_FREE(platform_kobj)
|
||||
}
|
||||
|
||||
int KBOJ_CREATE(char* name, struct kobject* parent, struct kobject** child)
|
||||
{
|
||||
if (parent) {
|
||||
*child = kobject_create_and_add(name, parent);
|
||||
} else {
|
||||
printk(KERN_ERR "PDDF_LED ERROR to create %s kobj; null parent\n", name);
|
||||
free_kobjs();
|
||||
return (-ENOMEM);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int LED_DEV_ATTR_CREATE(struct kobject *kobj, const struct attribute_group *attr, const char* name)
|
||||
{
|
||||
int status = sysfs_create_group(kobj, attr);
|
||||
if(status) {
|
||||
pddf_dbg(LED, KERN_ERR "Driver ERROR: sysfs_create %s failed rc=%d\n", name, status);
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
static int __init led_init(void) {
|
||||
struct kobject *device_kobj;
|
||||
pddf_dbg(LED, KERN_INFO "PDDF GENERIC LED MODULE init..\n");
|
||||
|
||||
device_kobj = get_device_i2c_kobj();
|
||||
if(!device_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
KBOJ_CREATE("platform", device_kobj, &platform_kobj);
|
||||
KBOJ_CREATE("led", device_kobj, &led_kobj);
|
||||
KBOJ_CREATE("state_attr", led_kobj, &state_attr_kobj);
|
||||
KBOJ_CREATE("cur_state", led_kobj, &cur_state_kobj);
|
||||
|
||||
LED_DEV_ATTR_CREATE(platform_kobj, &attr_group_platform, "attr_group_platform");
|
||||
LED_DEV_ATTR_CREATE(led_kobj, &attr_group_dev, "attr_group_dev");
|
||||
LED_DEV_ATTR_CREATE(state_attr_kobj, &attr_group_state_attr, "attr_group_state_attr");
|
||||
LED_DEV_ATTR_CREATE(cur_state_kobj, &attr_group_cur_state, "attr_group_cur_state");
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static void __exit led_exit(void) {
|
||||
pddf_dbg(LED, "PDDF GENERIC LED MODULE exit..\n");
|
||||
free_kobjs();
|
||||
if(psu_led_ops_data) kfree(psu_led_ops_data);
|
||||
if(fantray_led_ops_data) kfree(fantray_led_ops_data);
|
||||
}
|
||||
|
||||
module_init(led_init);
|
||||
module_exit(led_exit);
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("led driver");
|
||||
MODULE_LICENSE("GPL");
|
4
platform/pddf/i2c/modules/mux/Makefile
Normal file
4
platform/pddf/i2c/modules/mux/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
obj-m := pddf_mux_module.o
|
||||
|
||||
CFLAGS_$(obj-m):= -I$(M)/modules/include
|
211
platform/pddf/i2c/modules/mux/pddf_mux_module.c
Normal file
211
platform/pddf/i2c/modules/mux/pddf_mux_module.c
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* A pddf kernel module to create I2C client for pca954x type of multiplexer
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/kobject.h>
|
||||
#include "pddf_client_defs.h"
|
||||
#include "pddf_mux_defs.h"
|
||||
|
||||
|
||||
static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
extern void* get_device_table(char *name);
|
||||
extern void delete_device_table(char *name);
|
||||
|
||||
|
||||
MUX_DATA mux_data = {0};
|
||||
|
||||
/* MUX CLIENT DATA */
|
||||
PDDF_DATA_ATTR(virt_bus, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_HEX, sizeof(int), (void*)&mux_data.virt_bus, NULL);
|
||||
PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, (void*)&mux_data, (void*)&pddf_data);
|
||||
|
||||
|
||||
|
||||
static struct attribute *mux_attributes[] = {
|
||||
&attr_virt_bus.dev_attr.attr,
|
||||
&attr_dev_ops.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group pddf_mux_client_data_group = {
|
||||
.attrs = mux_attributes,
|
||||
};
|
||||
|
||||
struct i2c_board_info *i2c_get_mux_board_info(MUX_DATA* mdata, NEW_DEV_ATTR *device_data)
|
||||
{
|
||||
static struct i2c_board_info board_info;
|
||||
static struct pca954x_platform_mode platform_modes[8];
|
||||
static struct pca954x_platform_data mux_platform_data;
|
||||
int num_modes, i;
|
||||
|
||||
if (strncmp(device_data->dev_type, "pca9548", strlen("pca9548")) == 0)
|
||||
num_modes = 8;
|
||||
else if (strncmp(device_data->dev_type, "pca9546", strlen("pca9546")) == 0)
|
||||
num_modes = 6;
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "%s: Unknown type of mux device\n", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(i = 0; i < num_modes; i++) {
|
||||
platform_modes[i] = (struct pca954x_platform_mode) {
|
||||
.adap_id = (mdata->virt_bus + i),
|
||||
.deselect_on_exit = 1,
|
||||
};
|
||||
}
|
||||
|
||||
mux_platform_data = (struct pca954x_platform_data) {
|
||||
.modes = platform_modes,
|
||||
.num_modes = num_modes,
|
||||
};
|
||||
|
||||
board_info = (struct i2c_board_info) {
|
||||
.platform_data = &mux_platform_data,
|
||||
};
|
||||
|
||||
board_info.addr = device_data->dev_addr;
|
||||
strcpy(board_info.type, device_data->dev_type);
|
||||
|
||||
return &board_info;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
MUX_DATA *mux_ptr = (MUX_DATA *)(ptr->addr);
|
||||
NEW_DEV_ATTR *device_ptr = (NEW_DEV_ATTR *)(ptr->data);
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_board_info *board_info;
|
||||
struct i2c_client *client_ptr;
|
||||
|
||||
if (strncmp(buf, "add", strlen(buf)-1)==0)
|
||||
{
|
||||
adapter = i2c_get_adapter(device_ptr->parent_bus);
|
||||
board_info = i2c_get_mux_board_info(mux_ptr, device_ptr);
|
||||
|
||||
client_ptr = i2c_new_device(adapter, board_info);
|
||||
|
||||
if (client_ptr != NULL)
|
||||
{
|
||||
i2c_put_adapter(adapter);
|
||||
pddf_dbg(MUX, KERN_ERR "Created %s client: 0x%p\n", device_ptr->i2c_name, (void *)client_ptr);
|
||||
add_device_table(device_ptr->i2c_name, (void*)client_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
i2c_put_adapter(adapter);
|
||||
goto free_data;
|
||||
}
|
||||
}
|
||||
else if (strncmp(buf, "delete", strlen(buf)-1)==0)
|
||||
{
|
||||
/*Get the i2c_client handle for the created client*/
|
||||
client_ptr = (struct i2c_client *)get_device_table(device_ptr->i2c_name);
|
||||
if (client_ptr)
|
||||
{
|
||||
pddf_dbg(MUX, KERN_ERR "Removing %s client: 0x%p\n", device_ptr->i2c_name, (void *)client_ptr);
|
||||
i2c_unregister_device(client_ptr);
|
||||
/*TODO: Nullyfy the platform data*/
|
||||
delete_device_table(device_ptr->i2c_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "Unable to get the client handle for %s\n", device_ptr->i2c_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s", __FUNCTION__, buf);
|
||||
}
|
||||
|
||||
free_data:
|
||||
memset(mux_ptr, 0, sizeof(MUX_DATA));
|
||||
/*TODO: free the device_ptr->data is dynamically allocated*/
|
||||
memset(device_ptr, 0 , sizeof(NEW_DEV_ATTR));
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static struct kobject *mux_kobj;
|
||||
|
||||
int __init mux_data_init(void)
|
||||
{
|
||||
struct kobject *device_kobj;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
pddf_dbg(MUX, "MUX_DATA MODULE.. init\n");
|
||||
|
||||
device_kobj = get_device_i2c_kobj();
|
||||
if(!device_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
mux_kobj = kobject_create_and_add("mux", device_kobj);
|
||||
if(!mux_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
ret = sysfs_create_group(mux_kobj, &pddf_clients_data_group);
|
||||
if (ret)
|
||||
{
|
||||
kobject_put(mux_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(MUX, "CREATED PDDF I2C CLIENTS CREATION SYSFS GROUP\n");
|
||||
|
||||
ret = sysfs_create_group(mux_kobj, &pddf_mux_client_data_group);
|
||||
if (ret)
|
||||
{
|
||||
sysfs_remove_group(mux_kobj, &pddf_clients_data_group);
|
||||
kobject_put(mux_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(MUX, "CREATED MUX DATA SYSFS GROUP\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit mux_data_exit(void)
|
||||
{
|
||||
pddf_dbg(MUX, "MUX_DATA MODULE.. exit\n");
|
||||
sysfs_remove_group(mux_kobj, &pddf_mux_client_data_group);
|
||||
sysfs_remove_group(mux_kobj, &pddf_clients_data_group);
|
||||
kobject_put(mux_kobj);
|
||||
pddf_dbg(MUX, KERN_ERR "%s: Removed the kobjects for 'mux'\n",__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(mux_data_init);
|
||||
module_exit(mux_data_exit);
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("mux platform data");
|
||||
MODULE_LICENSE("GPL");
|
4
platform/pddf/i2c/modules/psu/Makefile
Normal file
4
platform/pddf/i2c/modules/psu/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
subdir-m := driver
|
||||
obj-m := pddf_psu_module.o
|
||||
|
||||
CFLAGS_$(obj-m):= -I$(M)/modules/include
|
6
platform/pddf/i2c/modules/psu/driver/Makefile
Normal file
6
platform/pddf/i2c/modules/psu/driver/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
TARGET = pddf_psu_driver_module
|
||||
obj-m := $(TARGET).o
|
||||
|
||||
$(TARGET)-objs := pddf_psu_api.o pddf_psu_driver.o
|
||||
|
||||
ccflags-y := -I$(M)/modules/include
|
707
platform/pddf/i2c/modules/psu/driver/pddf_psu_api.c
Normal file
707
platform/pddf/i2c/modules/psu/driver/pddf_psu_api.c
Normal file
@ -0,0 +1,707 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description of various APIs related to PSU component
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/kobject.h>
|
||||
#include "pddf_psu_defs.h"
|
||||
#include "pddf_psu_driver.h"
|
||||
|
||||
|
||||
/*#define PSU_DEBUG*/
|
||||
#ifdef PSU_DEBUG
|
||||
#define psu_dbg(...) printk(__VA_ARGS__)
|
||||
#else
|
||||
#define psu_dbg(...)
|
||||
#endif
|
||||
|
||||
|
||||
void get_psu_duplicate_sysfs(int idx, char *str)
|
||||
{
|
||||
switch (idx)
|
||||
{
|
||||
case PSU_V_OUT:
|
||||
strcpy(str, "in3_input");
|
||||
break;
|
||||
case PSU_I_OUT:
|
||||
strcpy(str, "curr2_input");
|
||||
break;
|
||||
case PSU_P_OUT:
|
||||
strcpy(str, "power2_input");
|
||||
break;
|
||||
case PSU_FAN1_SPEED:
|
||||
strcpy(str, "fan1_input");
|
||||
break;
|
||||
case PSU_TEMP1_INPUT:
|
||||
strcpy(str, "temp1_input");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int two_complement_to_int(u16 data, u8 valid_bit, int mask)
|
||||
{
|
||||
u16 valid_data = data & mask;
|
||||
bool is_negative = valid_data >> (valid_bit - 1);
|
||||
|
||||
return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data;
|
||||
}
|
||||
|
||||
int psu_update_hw(struct device *dev, struct psu_attr_info *info, PSU_DATA_ATTR *udata)
|
||||
{
|
||||
int status = 0;
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
PSU_SYSFS_ATTR_DATA *sysfs_attr_data = NULL;
|
||||
|
||||
|
||||
mutex_lock(&info->update_lock);
|
||||
|
||||
sysfs_attr_data = udata->access_data;
|
||||
if (sysfs_attr_data->pre_set != NULL)
|
||||
{
|
||||
status = (sysfs_attr_data->pre_set)(client, udata, info);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: pre_set function fails for %s attribute\n", __FUNCTION__, udata->aname);
|
||||
}
|
||||
if (sysfs_attr_data->do_set != NULL)
|
||||
{
|
||||
status = (sysfs_attr_data->do_set)(client, udata, info);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: do_set function fails for %s attribute\n", __FUNCTION__, udata->aname);
|
||||
|
||||
}
|
||||
if (sysfs_attr_data->post_set != NULL)
|
||||
{
|
||||
status = (sysfs_attr_data->post_set)(client, udata, info);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: post_set function fails for %s attribute\n", __FUNCTION__, udata->aname);
|
||||
}
|
||||
|
||||
mutex_unlock(&info->update_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int psu_update_attr(struct device *dev, struct psu_attr_info *data, PSU_DATA_ATTR *udata)
|
||||
{
|
||||
int status = 0;
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
PSU_SYSFS_ATTR_DATA *sysfs_attr_data=NULL;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || !data->valid)
|
||||
{
|
||||
dev_dbg(&client->dev, "Starting update for %s\n", data->name);
|
||||
|
||||
sysfs_attr_data = udata->access_data;
|
||||
if (sysfs_attr_data->pre_get != NULL)
|
||||
{
|
||||
status = (sysfs_attr_data->pre_get)(client, udata, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, udata->aname);
|
||||
}
|
||||
if (sysfs_attr_data->do_get != NULL)
|
||||
{
|
||||
status = (sysfs_attr_data->do_get)(client, udata, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, udata->aname);
|
||||
|
||||
}
|
||||
if (sysfs_attr_data->post_get != NULL)
|
||||
{
|
||||
status = (sysfs_attr_data->post_get)(client, udata, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, udata->aname);
|
||||
}
|
||||
|
||||
data->last_updated = jiffies;
|
||||
data->valid = 1;
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t psu_show_default(struct device *dev, struct device_attribute *da, char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct psu_data *data = i2c_get_clientdata(client);
|
||||
PSU_PDATA *pdata = (PSU_PDATA *)(client->dev.platform_data);
|
||||
PSU_DATA_ATTR *usr_data = NULL;
|
||||
struct psu_attr_info *sysfs_attr_info = NULL;
|
||||
int i, status=0;
|
||||
u16 value = 0;
|
||||
int exponent, mantissa;
|
||||
int multiplier = 1000;
|
||||
char new_str[ATTR_NAME_LEN] = "";
|
||||
PSU_SYSFS_ATTR_DATA *ptr = NULL;
|
||||
|
||||
for (i=0;i<data->num_attr;i++)
|
||||
{
|
||||
ptr = (PSU_SYSFS_ATTR_DATA *)pdata->psu_attrs[i].access_data;
|
||||
get_psu_duplicate_sysfs(ptr->index , new_str);
|
||||
if ( strcmp(attr->dev_attr.attr.name, pdata->psu_attrs[i].aname) == 0 || strcmp(attr->dev_attr.attr.name, new_str) == 0 )
|
||||
{
|
||||
sysfs_attr_info = &data->attr_info[i];
|
||||
usr_data = &pdata->psu_attrs[i];
|
||||
strcpy(new_str, "");
|
||||
}
|
||||
}
|
||||
|
||||
if (sysfs_attr_info==NULL || usr_data==NULL)
|
||||
{
|
||||
printk(KERN_ERR "%s is not supported attribute for this client\n", attr->dev_attr.attr.name);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
psu_update_attr(dev, sysfs_attr_info, usr_data);
|
||||
|
||||
switch(attr->index)
|
||||
{
|
||||
case PSU_PRESENT:
|
||||
case PSU_POWER_GOOD:
|
||||
status = sysfs_attr_info->val.intval;
|
||||
return sprintf(buf, "%d\n", status);
|
||||
break;
|
||||
case PSU_MODEL_NAME:
|
||||
case PSU_MFR_ID:
|
||||
case PSU_SERIAL_NUM:
|
||||
case PSU_FAN_DIR:
|
||||
return sprintf(buf, "%s\n", sysfs_attr_info->val.strval);
|
||||
break;
|
||||
case PSU_V_OUT:
|
||||
case PSU_I_OUT:
|
||||
case PSU_V_IN:
|
||||
case PSU_I_IN:
|
||||
multiplier = 1000;
|
||||
value = sysfs_attr_info->val.shortval;
|
||||
exponent = two_complement_to_int(value >> 11, 5, 0x1f);
|
||||
mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff);
|
||||
if (exponent >= 0)
|
||||
return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier);
|
||||
else
|
||||
return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent));
|
||||
|
||||
break;
|
||||
case PSU_P_OUT:
|
||||
multiplier = 1000000;
|
||||
value = sysfs_attr_info->val.shortval;
|
||||
exponent = two_complement_to_int(value >> 11, 5, 0x1f);
|
||||
mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff);
|
||||
if (exponent >= 0)
|
||||
return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier);
|
||||
else
|
||||
return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent));
|
||||
|
||||
break;
|
||||
case PSU_FAN1_SPEED:
|
||||
value = sysfs_attr_info->val.shortval;
|
||||
exponent = two_complement_to_int(value >> 11, 5, 0x1f);
|
||||
mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff);
|
||||
if (exponent >= 0)
|
||||
return sprintf(buf, "%d\n", (mantissa << exponent));
|
||||
else
|
||||
return sprintf(buf, "%d\n", (mantissa) / (1 << -exponent));
|
||||
|
||||
break;
|
||||
case PSU_TEMP1_INPUT:
|
||||
multiplier = 1000;
|
||||
value = sysfs_attr_info->val.shortval;
|
||||
exponent = two_complement_to_int(value >> 11, 5, 0x1f);
|
||||
mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff);
|
||||
if (exponent >= 0)
|
||||
return sprintf(buf, "%d\n", (mantissa << exponent) * multiplier);
|
||||
else
|
||||
return sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent));
|
||||
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "%s: Unable to find attribute index for %s\n", __FUNCTION__, usr_data->aname);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
return sprintf(buf, "%d\n", status);
|
||||
}
|
||||
|
||||
|
||||
ssize_t psu_store_default(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct psu_data *data = i2c_get_clientdata(client);
|
||||
PSU_PDATA *pdata = (PSU_PDATA *)(client->dev.platform_data);
|
||||
PSU_DATA_ATTR *usr_data = NULL;
|
||||
struct psu_attr_info *sysfs_attr_info = NULL;
|
||||
int i;
|
||||
|
||||
for (i=0;i<data->num_attr;i++)
|
||||
{
|
||||
if (strcmp(data->attr_info[i].name, attr->dev_attr.attr.name) == 0 && strcmp(pdata->psu_attrs[i].aname, attr->dev_attr.attr.name) == 0)
|
||||
{
|
||||
sysfs_attr_info = &data->attr_info[i];
|
||||
usr_data = &pdata->psu_attrs[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (sysfs_attr_info==NULL || usr_data==NULL) {
|
||||
printk(KERN_ERR "%s is not supported attribute for this client\n", attr->dev_attr.attr.name);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch(attr->index)
|
||||
{
|
||||
/*No write attributes for now in PSU*/
|
||||
default:
|
||||
goto exit;
|
||||
}
|
||||
|
||||
psu_update_hw(dev, sysfs_attr_info, usr_data);
|
||||
|
||||
exit:
|
||||
return count;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_psu_present_default(void *client, PSU_DATA_ATTR *adata, void *data)
|
||||
{
|
||||
int status = 0;
|
||||
int val = 0;
|
||||
struct psu_attr_info *padata = (struct psu_attr_info *)data;
|
||||
|
||||
|
||||
if (strncmp(adata->devtype, "cpld", strlen("cpld")) == 0)
|
||||
{
|
||||
val = board_i2c_cpld_read(adata->devaddr , adata->offset);
|
||||
if (val < 0)
|
||||
return val;
|
||||
padata->val.intval = ((val & adata->mask) == adata->cmpval);
|
||||
psu_dbg(KERN_ERR "%s: status_value = 0x%x\n", __FUNCTION__, padata->val.intval);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_psu_power_good_default(void *client, PSU_DATA_ATTR *adata, void *data)
|
||||
{
|
||||
int status = 0;
|
||||
int val = 0;
|
||||
struct psu_attr_info *padata = (struct psu_attr_info *)data;
|
||||
|
||||
if (strncmp(adata->devtype, "cpld", strlen("cpld")) == 0)
|
||||
{
|
||||
val = board_i2c_cpld_read(adata->devaddr , adata->offset);
|
||||
if (val < 0)
|
||||
return val;
|
||||
padata->val.intval = ((val & adata->mask) == adata->cmpval);
|
||||
psu_dbg(KERN_ERR "%s: status_value = 0x%x\n", __FUNCTION__, padata->val.intval);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_psu_model_name_default(void *client, PSU_DATA_ATTR *adata, void *data)
|
||||
{
|
||||
int status = 0, retry = 10;
|
||||
struct psu_attr_info *padata = (struct psu_attr_info *)data;
|
||||
char model[32]=""; //temporary placeholder for model name
|
||||
uint8_t offset = (uint8_t)adata->offset;
|
||||
int data_len = adata->len;
|
||||
|
||||
while (retry)
|
||||
{
|
||||
status = i2c_smbus_read_i2c_block_data((struct i2c_client *)client, offset, data_len-1, model);
|
||||
if (unlikely(status<0))
|
||||
{
|
||||
msleep(60);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
model[0] = '\0';
|
||||
dev_dbg(&((struct i2c_client *)client)->dev, "unable to read model name from (0x%x)\n", ((struct i2c_client *)client)->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
model[data_len-1] = '\0';
|
||||
}
|
||||
|
||||
if (strncmp(adata->devtype, "pmbus", strlen("pmbus")) == 0)
|
||||
strncpy(padata->val.strval, model+1, data_len-1);
|
||||
else
|
||||
strncpy(padata->val.strval, model, data_len);
|
||||
|
||||
psu_dbg(KERN_ERR "%s: status = %d, model_name : %s\n", __FUNCTION__, status, padata->val.strval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_psu_mfr_id_default(void *client, PSU_DATA_ATTR *adata, void *data)
|
||||
{
|
||||
|
||||
int status = 0, retry = 10;
|
||||
struct psu_attr_info *padata = (struct psu_attr_info *)data;
|
||||
char mfr_id[16] = ""; // temporary place holder for mfr_id
|
||||
uint8_t offset = (uint8_t)adata->offset;
|
||||
int data_len = adata->len;
|
||||
|
||||
while (retry)
|
||||
{
|
||||
status = i2c_smbus_read_i2c_block_data((struct i2c_client *)client, offset, data_len-1, mfr_id);
|
||||
if (unlikely(status<0))
|
||||
{
|
||||
msleep(60);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
mfr_id[0] = '\0';
|
||||
dev_dbg(&((struct i2c_client *)client)->dev, "unable to read mfr_id from (0x%x)\n", ((struct i2c_client *)client)->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
mfr_id[data_len-1] = '\0';
|
||||
}
|
||||
|
||||
if (strncmp(adata->devtype, "pmbus", strlen("pmbus")) == 0)
|
||||
strncpy(padata->val.strval, mfr_id+1, data_len-1);
|
||||
else
|
||||
strncpy(padata->val.strval, mfr_id, data_len);
|
||||
|
||||
psu_dbg(KERN_ERR "%s: status = %d, mfr_id : %s\n", __FUNCTION__, status, padata->val.strval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_psu_serial_num_default(void *client, PSU_DATA_ATTR *adata, void *data)
|
||||
{
|
||||
|
||||
int status = 0, retry = 10;
|
||||
struct psu_attr_info *padata = (struct psu_attr_info *)data;
|
||||
char serial[32] = ""; // temporary string to store the serial num
|
||||
uint8_t offset = (uint8_t)adata->offset;
|
||||
int data_len = adata->len;
|
||||
|
||||
while (retry)
|
||||
{
|
||||
status = i2c_smbus_read_i2c_block_data((struct i2c_client *)client, offset, data_len-1, serial);
|
||||
if (unlikely(status<0))
|
||||
{
|
||||
msleep(60);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
serial[0] = '\0';
|
||||
dev_dbg(&((struct i2c_client *)client)->dev, "unable to read serial num from (0x%x)\n", ((struct i2c_client *)client)->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
serial[data_len-1] = '\0';
|
||||
}
|
||||
|
||||
if (strncmp(adata->devtype, "pmbus", strlen("pmbus")) == 0)
|
||||
strncpy(padata->val.strval, serial+1, data_len-1);
|
||||
else
|
||||
strncpy(padata->val.strval, serial, data_len);
|
||||
|
||||
psu_dbg(KERN_ERR "%s: status = %d, serial_num : %s\n", __FUNCTION__, status, padata->val.strval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_psu_fan_dir_default(void *client, PSU_DATA_ATTR *adata, void *data)
|
||||
{
|
||||
|
||||
int status = 0, retry = 10;
|
||||
struct psu_attr_info *padata = (struct psu_attr_info *)data;
|
||||
char fan_dir[5] = "";
|
||||
uint8_t offset = (uint8_t)adata->offset;
|
||||
int data_len = adata->len;
|
||||
|
||||
while (retry)
|
||||
{
|
||||
status = i2c_smbus_read_i2c_block_data((struct i2c_client *)client, offset, data_len-1, fan_dir);
|
||||
if (unlikely(status<0))
|
||||
{
|
||||
msleep(60);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
fan_dir[0] = '\0';
|
||||
dev_dbg(&((struct i2c_client *)client)->dev, "unable to read fan_dir from (0x%x)\n", ((struct i2c_client *)client)->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
fan_dir[data_len-1] = '\0';
|
||||
}
|
||||
|
||||
if (strncmp(adata->devtype, "pmbus", strlen("pmbus")) == 0)
|
||||
strncpy(padata->val.strval, fan_dir+1, data_len-1);
|
||||
else
|
||||
strncpy(padata->val.strval, fan_dir, data_len);
|
||||
|
||||
psu_dbg(KERN_ERR "%s: status = %d, fan_dir : %s\n", __FUNCTION__, status, padata->val.strval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_psu_v_out_default(void *client, PSU_DATA_ATTR *adata, void *data)
|
||||
{
|
||||
|
||||
int status = 0, retry = 10;
|
||||
struct psu_attr_info *padata = (struct psu_attr_info *)data;
|
||||
uint8_t offset = (uint8_t)adata->offset;
|
||||
|
||||
while (retry) {
|
||||
status = i2c_smbus_read_word_data((struct i2c_client *)client, offset);
|
||||
if (unlikely(status < 0)) {
|
||||
msleep(60);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
padata->val.shortval = 0;
|
||||
dev_dbg(&((struct i2c_client *)client)->dev, "unable to read v_out from (0x%x)\n", ((struct i2c_client *)client)->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
padata->val.shortval = status;
|
||||
}
|
||||
|
||||
psu_dbg(KERN_ERR "%s: v_out : %d\n", __FUNCTION__, padata->val.shortval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_psu_i_out_default(void *client, PSU_DATA_ATTR *adata, void *data)
|
||||
{
|
||||
|
||||
int status = 0, retry = 10;
|
||||
struct psu_attr_info *padata = (struct psu_attr_info *)data;
|
||||
uint8_t offset = (uint8_t)adata->offset;
|
||||
|
||||
while (retry) {
|
||||
status = i2c_smbus_read_word_data((struct i2c_client *)client, offset);
|
||||
if (unlikely(status < 0)) {
|
||||
msleep(60);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
padata->val.shortval = 0;
|
||||
dev_dbg(&((struct i2c_client *)client)->dev, "unable to read i_out from (0x%x)\n", ((struct i2c_client *)client)->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
padata->val.shortval = status;
|
||||
}
|
||||
|
||||
psu_dbg(KERN_ERR "%s: i_out : %d\n", __FUNCTION__, padata->val.shortval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_psu_p_out_default(void *client, PSU_DATA_ATTR *adata, void *data)
|
||||
{
|
||||
|
||||
int status = 0, retry = 10;
|
||||
struct psu_attr_info *padata = (struct psu_attr_info *)data;
|
||||
uint8_t offset = (uint8_t)adata->offset;
|
||||
|
||||
while (retry) {
|
||||
status = i2c_smbus_read_word_data((struct i2c_client *)client, offset);
|
||||
if (unlikely(status < 0)) {
|
||||
msleep(60);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
padata->val.shortval = 0;
|
||||
dev_dbg(&((struct i2c_client *)client)->dev, "unable to read p_out from (0x%x)\n", ((struct i2c_client *)client)->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
padata->val.shortval = status;
|
||||
}
|
||||
|
||||
psu_dbg(KERN_ERR "%s: p_out : %d\n", __FUNCTION__, padata->val.shortval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_psu_v_in_default(void *client, PSU_DATA_ATTR *adata, void *data)
|
||||
{
|
||||
|
||||
int status = 0, retry = 10;
|
||||
struct psu_attr_info *padata = (struct psu_attr_info *)data;
|
||||
uint8_t offset = (uint8_t)adata->offset;
|
||||
|
||||
while (retry) {
|
||||
status = i2c_smbus_read_word_data((struct i2c_client *)client, offset);
|
||||
if (unlikely(status < 0)) {
|
||||
msleep(60);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
padata->val.shortval = 0;
|
||||
dev_dbg(&((struct i2c_client *)client)->dev, "unable to read v_in from (0x%x)\n", ((struct i2c_client *)client)->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
padata->val.shortval = status;
|
||||
}
|
||||
|
||||
psu_dbg(KERN_ERR "%s: v_in : %d\n", __FUNCTION__, padata->val.shortval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_psu_i_in_default(void *client, PSU_DATA_ATTR *adata, void *data)
|
||||
{
|
||||
|
||||
int status = 0, retry = 10;
|
||||
struct psu_attr_info *padata = (struct psu_attr_info *)data;
|
||||
uint8_t offset = (uint8_t)adata->offset;
|
||||
|
||||
while (retry) {
|
||||
status = i2c_smbus_read_word_data((struct i2c_client *)client, offset);
|
||||
if (unlikely(status < 0)) {
|
||||
msleep(60);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
padata->val.shortval = 0;
|
||||
dev_dbg(&((struct i2c_client *)client)->dev, "unable to read i_in from (0x%x)\n", ((struct i2c_client *)client)->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
padata->val.shortval = status;
|
||||
}
|
||||
|
||||
psu_dbg(KERN_ERR "%s: i_in : %d\n", __FUNCTION__, padata->val.shortval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_psu_fan1_speed_rpm_default(void *client, PSU_DATA_ATTR *adata, void *data)
|
||||
{
|
||||
|
||||
int status = 0, retry = 10;
|
||||
struct psu_attr_info *padata = (struct psu_attr_info *)data;
|
||||
uint8_t offset = (uint8_t)adata->offset;
|
||||
|
||||
while (retry) {
|
||||
status = i2c_smbus_read_word_data((struct i2c_client *)client, offset);
|
||||
if (unlikely(status < 0)) {
|
||||
msleep(60);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
padata->val.shortval = 0;
|
||||
dev_dbg(&((struct i2c_client *)client)->dev, "unable to read fan1_speed_rpm from (0x%x)\n", ((struct i2c_client *)client)->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
padata->val.shortval = status;
|
||||
}
|
||||
|
||||
psu_dbg(KERN_ERR "%s: fan1_speed_rpm : %d\n", __FUNCTION__, padata->val.shortval);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_psu_temp1_input_default(void *client, PSU_DATA_ATTR *adata, void *data)
|
||||
{
|
||||
|
||||
int status = 0, retry = 10;
|
||||
struct psu_attr_info *padata = (struct psu_attr_info *)data;
|
||||
uint8_t offset = (uint8_t)adata->offset;
|
||||
|
||||
while (retry) {
|
||||
status = i2c_smbus_read_word_data((struct i2c_client *)client, offset);
|
||||
if (unlikely(status < 0)) {
|
||||
msleep(60);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
padata->val.shortval = 0;
|
||||
dev_dbg(&((struct i2c_client *)client)->dev, "unable to read temp1_input from (0x%x)\n", ((struct i2c_client *)client)->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
padata->val.shortval = status;
|
||||
}
|
||||
|
||||
psu_dbg(KERN_ERR "%s: temp1_input : %d\n", __FUNCTION__, padata->val.shortval);
|
||||
return 0;
|
||||
}
|
381
platform/pddf/i2c/modules/psu/driver/pddf_psu_driver.c
Normal file
381
platform/pddf/i2c/modules/psu/driver/pddf_psu_driver.c
Normal file
@ -0,0 +1,381 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* A pddf kernel module driver for PSU
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/kobject.h>
|
||||
#include "pddf_client_defs.h"
|
||||
#include "pddf_psu_defs.h"
|
||||
#include "pddf_psu_driver.h"
|
||||
#include "pddf_psu_api.h"
|
||||
|
||||
|
||||
static unsigned short normal_i2c[] = { I2C_CLIENT_END };
|
||||
|
||||
struct pddf_ops_t pddf_psu_ops = {
|
||||
.pre_init = NULL,
|
||||
.post_init = NULL,
|
||||
|
||||
.pre_probe = NULL,
|
||||
.post_probe = NULL,
|
||||
|
||||
.pre_remove = NULL,
|
||||
.post_remove = NULL,
|
||||
|
||||
.pre_exit = NULL,
|
||||
.post_exit = NULL,
|
||||
};
|
||||
EXPORT_SYMBOL(pddf_psu_ops);
|
||||
|
||||
|
||||
PSU_SYSFS_ATTR_DATA access_psu_present = {PSU_PRESENT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_present_default, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(access_psu_present);
|
||||
|
||||
PSU_SYSFS_ATTR_DATA access_psu_model_name = {PSU_MODEL_NAME, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_model_name_default, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(access_psu_model_name);
|
||||
|
||||
PSU_SYSFS_ATTR_DATA access_psu_power_good = {PSU_POWER_GOOD, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_power_good_default, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(access_psu_power_good);
|
||||
|
||||
PSU_SYSFS_ATTR_DATA access_psu_mfr_id = {PSU_MFR_ID, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_mfr_id_default, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(access_psu_mfr_id);
|
||||
|
||||
PSU_SYSFS_ATTR_DATA access_psu_serial_num = {PSU_SERIAL_NUM, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_serial_num_default, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(access_psu_serial_num);
|
||||
|
||||
PSU_SYSFS_ATTR_DATA access_psu_fan_dir = {PSU_FAN_DIR, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_fan_dir_default, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(access_psu_fan_dir);
|
||||
|
||||
PSU_SYSFS_ATTR_DATA access_psu_v_out = {PSU_V_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_v_out_default, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(access_psu_v_out);
|
||||
|
||||
PSU_SYSFS_ATTR_DATA access_psu_i_out = {PSU_I_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_i_out_default, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(access_psu_i_out);
|
||||
|
||||
PSU_SYSFS_ATTR_DATA access_psu_p_out = {PSU_P_OUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_p_out_default, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(access_psu_p_out);
|
||||
|
||||
PSU_SYSFS_ATTR_DATA access_psu_fan1_speed_rpm = {PSU_FAN1_SPEED, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_fan1_speed_rpm_default, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(access_psu_fan1_speed_rpm);
|
||||
|
||||
PSU_SYSFS_ATTR_DATA access_psu_temp1_input = {PSU_TEMP1_INPUT, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_temp1_input_default, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(access_psu_temp1_input);
|
||||
|
||||
PSU_SYSFS_ATTR_DATA access_psu_v_in = {PSU_V_IN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_v_in_default, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(access_psu_v_in);
|
||||
|
||||
PSU_SYSFS_ATTR_DATA access_psu_i_in = {PSU_I_IN, S_IRUGO, psu_show_default, NULL, sonic_i2c_get_psu_i_in_default, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(access_psu_i_in);
|
||||
|
||||
|
||||
PSU_SYSFS_ATTR_DATA_ENTRY psu_sysfs_attr_data_tbl[]=
|
||||
{
|
||||
{ "psu_present", &access_psu_present},
|
||||
{ "psu_model_name", &access_psu_model_name},
|
||||
{ "psu_power_good" , &access_psu_power_good},
|
||||
{ "psu_mfr_id" , &access_psu_mfr_id},
|
||||
{ "psu_serial_num" , &access_psu_serial_num},
|
||||
{ "psu_fan_dir" , &access_psu_fan_dir},
|
||||
{ "psu_v_out" , &access_psu_v_out},
|
||||
{ "psu_i_out" , &access_psu_i_out},
|
||||
{ "psu_p_out" , &access_psu_p_out},
|
||||
{ "psu_fan1_speed_rpm" , &access_psu_fan1_speed_rpm},
|
||||
{ "psu_temp1_input" , &access_psu_temp1_input},
|
||||
{ "psu_v_in" , &access_psu_v_in},
|
||||
{ "psu_i_in" , &access_psu_i_in}
|
||||
};
|
||||
|
||||
void *get_psu_access_data(char *name)
|
||||
{
|
||||
int i=0;
|
||||
for(i=0; i<(sizeof(psu_sysfs_attr_data_tbl)/sizeof(psu_sysfs_attr_data_tbl[0])); i++)
|
||||
{
|
||||
if(strcmp(name, psu_sysfs_attr_data_tbl[i].name) ==0)
|
||||
{
|
||||
return &psu_sysfs_attr_data_tbl[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(get_psu_access_data);
|
||||
|
||||
|
||||
static int psu_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *dev_id)
|
||||
{
|
||||
struct psu_data *data;
|
||||
int status =0;
|
||||
int i,num, j=0;
|
||||
PSU_PDATA *psu_platform_data;
|
||||
PSU_DATA_ATTR *data_attr;
|
||||
PSU_SYSFS_ATTR_DATA_ENTRY *sysfs_data_entry;
|
||||
char new_str[ATTR_NAME_LEN] = "";
|
||||
|
||||
|
||||
if (client == NULL) {
|
||||
printk("NULL Client.. \n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (pddf_psu_ops.pre_probe)
|
||||
{
|
||||
status = (pddf_psu_ops.pre_probe)(client, dev_id);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
|
||||
status = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
data = kzalloc(sizeof(struct psu_data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
status = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
dev_info(&client->dev, "chip found\n");
|
||||
|
||||
/* Take control of the platform data */
|
||||
psu_platform_data = (PSU_PDATA *)(client->dev.platform_data);
|
||||
num = psu_platform_data->len;
|
||||
data->index = psu_platform_data->idx - 1;
|
||||
data->num_psu_fans = psu_platform_data->num_psu_fans;
|
||||
data->num_attr = num;
|
||||
|
||||
|
||||
|
||||
/* Create and Add supported attr in the 'attributes' list */
|
||||
for (i=0; i<num; i++)
|
||||
{
|
||||
/*struct attribute *aptr = NULL;*/
|
||||
struct sensor_device_attribute *dy_ptr = NULL;
|
||||
data_attr = psu_platform_data->psu_attrs + i;
|
||||
sysfs_data_entry = get_psu_access_data(data_attr->aname);
|
||||
if (sysfs_data_entry == NULL)
|
||||
{
|
||||
printk(KERN_ERR "%s: Wrong attribute name provided by user '%s'\n", __FUNCTION__, data_attr->aname);
|
||||
continue;
|
||||
}
|
||||
|
||||
dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL);
|
||||
dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1];
|
||||
strcpy((char *)dy_ptr->dev_attr.attr.name, data_attr->aname);
|
||||
dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode;
|
||||
dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show;
|
||||
dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store;
|
||||
dy_ptr->index = sysfs_data_entry->a_ptr->index;
|
||||
|
||||
data->psu_attribute_list[i] = &dy_ptr->dev_attr.attr;
|
||||
strcpy(data->attr_info[i].name, data_attr->aname);
|
||||
data->attr_info[i].valid = 0;
|
||||
mutex_init(&data->attr_info[i].update_lock);
|
||||
|
||||
/*Create a duplicate entry*/
|
||||
get_psu_duplicate_sysfs(dy_ptr->index, new_str);
|
||||
if (strcmp(new_str,""))
|
||||
{
|
||||
dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL);
|
||||
dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1];
|
||||
strcpy((char *)dy_ptr->dev_attr.attr.name, new_str);
|
||||
dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode;
|
||||
dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show;
|
||||
dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store;
|
||||
dy_ptr->index = sysfs_data_entry->a_ptr->index;
|
||||
|
||||
data->psu_attribute_list[num+j] = &dy_ptr->dev_attr.attr;
|
||||
j++;
|
||||
strcpy(new_str,"");
|
||||
}
|
||||
}
|
||||
data->psu_attribute_list[i+j] = NULL;
|
||||
data->psu_attribute_group.attrs = data->psu_attribute_list;
|
||||
|
||||
/* Register sysfs hooks */
|
||||
status = sysfs_create_group(&client->dev.kobj, &data->psu_attribute_group);
|
||||
if (status) {
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
status = PTR_ERR(data->hwmon_dev);
|
||||
goto exit_remove;
|
||||
}
|
||||
|
||||
dev_info(&client->dev, "%s: psu '%s'\n",
|
||||
dev_name(data->hwmon_dev), client->name);
|
||||
|
||||
/* Add a support for post probe function */
|
||||
if (pddf_psu_ops.post_probe)
|
||||
{
|
||||
status = (pddf_psu_ops.post_probe)(client, dev_id);
|
||||
if (status != 0)
|
||||
goto exit_remove;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
exit_remove:
|
||||
sysfs_remove_group(&client->dev.kobj, &data->psu_attribute_group);
|
||||
exit_free:
|
||||
/* Free all the allocated attributes */
|
||||
for (i=0;data->psu_attribute_list[i]!=NULL;i++)
|
||||
{
|
||||
struct sensor_device_attribute *ptr = (struct sensor_device_attribute *)data->psu_attribute_list[i];
|
||||
kfree(ptr);
|
||||
data->psu_attribute_list[i] = NULL;
|
||||
pddf_dbg(PSU, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__);
|
||||
}
|
||||
kfree(data);
|
||||
exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
static int psu_remove(struct i2c_client *client)
|
||||
{
|
||||
int i=0, ret = 0;
|
||||
struct psu_data *data = i2c_get_clientdata(client);
|
||||
PSU_PDATA *platdata = (PSU_PDATA *)client->dev.platform_data; // use dev_get_platdata()
|
||||
PSU_DATA_ATTR *platdata_sub = platdata->psu_attrs;
|
||||
struct sensor_device_attribute *ptr = NULL;
|
||||
|
||||
if (pddf_psu_ops.pre_remove)
|
||||
{
|
||||
ret = (pddf_psu_ops.pre_remove)(client);
|
||||
if (ret!=0)
|
||||
printk(KERN_ERR "FAN pre_remove function failed\n");
|
||||
}
|
||||
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &data->psu_attribute_group);
|
||||
for (i=0; data->psu_attribute_list[i]!=NULL; i++)
|
||||
{
|
||||
ptr = (struct sensor_device_attribute *)data->psu_attribute_list[i];
|
||||
kfree(ptr);
|
||||
data->psu_attribute_list[i] = NULL;
|
||||
}
|
||||
pddf_dbg(PSU, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__);
|
||||
kfree(data);
|
||||
if (platdata_sub) {
|
||||
printk(KERN_DEBUG "%s: Freeing platform subdata\n", __FUNCTION__);
|
||||
kfree(platdata_sub);
|
||||
}
|
||||
if (platdata) {
|
||||
printk(KERN_DEBUG "%s: Freeing platform data\n", __FUNCTION__);
|
||||
kfree(platdata);
|
||||
}
|
||||
|
||||
if (pddf_psu_ops.post_remove)
|
||||
{
|
||||
ret = (pddf_psu_ops.post_remove)(client);
|
||||
if (ret!=0)
|
||||
printk(KERN_ERR "FAN post_remove function failed\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum psu_intf
|
||||
{
|
||||
eeprom_intf,
|
||||
smbus_intf
|
||||
};
|
||||
|
||||
static const struct i2c_device_id psu_id[] = {
|
||||
{"psu_eeprom", eeprom_intf},
|
||||
{"psu_pmbus", smbus_intf},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, psu_id);
|
||||
|
||||
static struct i2c_driver psu_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "psu",
|
||||
},
|
||||
.probe = psu_probe,
|
||||
.remove = psu_remove,
|
||||
.id_table = psu_id,
|
||||
.address_list = normal_i2c,
|
||||
};
|
||||
|
||||
int example_fun(void)
|
||||
{
|
||||
pddf_dbg(PSU, KERN_ERR "CALLING FUN...\n");
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(example_fun);
|
||||
|
||||
|
||||
int psu_init(void)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
if (pddf_psu_ops.pre_init)
|
||||
{
|
||||
status = (pddf_psu_ops.pre_init)();
|
||||
if (status!=0)
|
||||
return status;
|
||||
}
|
||||
|
||||
pddf_dbg(PSU, KERN_ERR "GENERIC_PSU_DRIVER.. init Invoked..\n");
|
||||
status = i2c_add_driver(&psu_driver);
|
||||
if (status!=0)
|
||||
return status;
|
||||
|
||||
if (pddf_psu_ops.post_init)
|
||||
{
|
||||
status = (pddf_psu_ops.post_init)();
|
||||
if (status!=0)
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(psu_init);
|
||||
|
||||
void __exit psu_exit(void)
|
||||
{
|
||||
pddf_dbg(PSU, "GENERIC_PSU_DRIVER.. exit\n");
|
||||
if (pddf_psu_ops.pre_exit) (pddf_psu_ops.pre_exit)();
|
||||
i2c_del_driver(&psu_driver);
|
||||
if (pddf_psu_ops.post_exit) (pddf_psu_ops.post_exit)();
|
||||
}
|
||||
EXPORT_SYMBOL(psu_exit);
|
||||
|
||||
module_init(psu_init);
|
||||
module_exit(psu_exit);
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("psu driver");
|
||||
MODULE_LICENSE("GPL");
|
283
platform/pddf/i2c/modules/psu/pddf_psu_module.c
Normal file
283
platform/pddf/i2c/modules/psu/pddf_psu_module.c
Normal file
@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* A pddf kernel module to create I2C client for PSU
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/kobject.h>
|
||||
#include "pddf_client_defs.h"
|
||||
#include "pddf_psu_defs.h"
|
||||
|
||||
|
||||
static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
extern void *get_psu_access_data(char *);
|
||||
extern void* get_device_table(char *name);
|
||||
extern void delete_device_table(char *name);
|
||||
|
||||
PSU_DATA psu_data = {0};
|
||||
|
||||
|
||||
|
||||
/* PSU CLIENT DATA */
|
||||
PDDF_DATA_ATTR(psu_idx, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&psu_data.idx, NULL);
|
||||
PDDF_DATA_ATTR(psu_fans, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&psu_data.num_psu_fans, NULL);
|
||||
|
||||
PDDF_DATA_ATTR(attr_name, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, (void*)&psu_data.psu_attr.aname, NULL);
|
||||
PDDF_DATA_ATTR(attr_devtype, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 8, (void*)&psu_data.psu_attr.devtype, NULL);
|
||||
PDDF_DATA_ATTR(attr_devname, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 8, (void*)&psu_data.psu_attr.devname, NULL);
|
||||
PDDF_DATA_ATTR(attr_devaddr, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&psu_data.psu_attr.devaddr, NULL);
|
||||
PDDF_DATA_ATTR(attr_offset, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&psu_data.psu_attr.offset, NULL);
|
||||
PDDF_DATA_ATTR(attr_mask, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&psu_data.psu_attr.mask, NULL);
|
||||
PDDF_DATA_ATTR(attr_cmpval, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&psu_data.psu_attr.cmpval, NULL);
|
||||
PDDF_DATA_ATTR(attr_len, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&psu_data.psu_attr.len, NULL);
|
||||
PDDF_DATA_ATTR(attr_ops, S_IWUSR, NULL, do_attr_operation, PDDF_CHAR, 8, (void*)&psu_data, NULL);
|
||||
PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, (void*)&psu_data, (void*)&pddf_data);
|
||||
|
||||
|
||||
|
||||
static struct attribute *psu_attributes[] = {
|
||||
&attr_psu_idx.dev_attr.attr,
|
||||
&attr_psu_fans.dev_attr.attr,
|
||||
|
||||
&attr_attr_name.dev_attr.attr,
|
||||
&attr_attr_devtype.dev_attr.attr,
|
||||
&attr_attr_devname.dev_attr.attr,
|
||||
&attr_attr_devaddr.dev_attr.attr,
|
||||
&attr_attr_offset.dev_attr.attr,
|
||||
&attr_attr_mask.dev_attr.attr,
|
||||
&attr_attr_cmpval.dev_attr.attr,
|
||||
&attr_attr_len.dev_attr.attr,
|
||||
&attr_attr_ops.dev_attr.attr,
|
||||
&attr_dev_ops.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group pddf_psu_client_data_group = {
|
||||
.attrs = psu_attributes,
|
||||
};
|
||||
|
||||
|
||||
static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
PSU_DATA *pdata = (PSU_DATA *)(ptr->addr);
|
||||
PSU_SYSFS_ATTR_DATA_ENTRY *access_ptr;
|
||||
|
||||
|
||||
pdata->psu_attrs[pdata->len] = pdata->psu_attr;
|
||||
access_ptr = get_psu_access_data(pdata->psu_attrs[pdata->len].aname);
|
||||
if (access_ptr != NULL && access_ptr->a_ptr != NULL)
|
||||
{
|
||||
pdata->psu_attrs[pdata->len].access_data = access_ptr->a_ptr ;
|
||||
}
|
||||
|
||||
|
||||
pdata->len++;
|
||||
memset(&pdata->psu_attr, 0, sizeof(pdata->psu_attr));
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
struct i2c_board_info *i2c_get_psu_board_info(PSU_DATA *pdata, NEW_DEV_ATTR *cdata)
|
||||
{
|
||||
int num = pdata->len;
|
||||
int i = 0;
|
||||
static struct i2c_board_info board_info;
|
||||
PSU_PDATA *psu_platform_data;
|
||||
|
||||
|
||||
if (strcmp(cdata->dev_type, "psu_pmbus")==0 || strcmp(cdata->dev_type, "psu_eeprom")==0 )
|
||||
{
|
||||
/* Allocate the psu_platform_data */
|
||||
psu_platform_data = (PSU_PDATA *)kzalloc(sizeof(PSU_PDATA), GFP_KERNEL);
|
||||
psu_platform_data->psu_attrs = (PSU_DATA_ATTR *)kzalloc(num*sizeof(PSU_DATA_ATTR), GFP_KERNEL);
|
||||
|
||||
|
||||
psu_platform_data->idx = pdata->idx;
|
||||
psu_platform_data->num_psu_fans = pdata->num_psu_fans;
|
||||
psu_platform_data->len = pdata->len;
|
||||
|
||||
for (i=0;i<num;i++)
|
||||
{
|
||||
psu_platform_data->psu_attrs[i] = pdata->psu_attrs[i];
|
||||
}
|
||||
|
||||
board_info = (struct i2c_board_info) {
|
||||
.platform_data = psu_platform_data,
|
||||
};
|
||||
|
||||
board_info.addr = cdata->dev_addr;
|
||||
strcpy(board_info.type, cdata->dev_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "%s:Unknown type of device %s. Unable to clreate I2C client for it\n",__FUNCTION__, cdata->dev_type);
|
||||
}
|
||||
|
||||
return &board_info;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
PSU_DATA *pdata = (PSU_DATA *)(ptr->addr);
|
||||
NEW_DEV_ATTR *cdata = (NEW_DEV_ATTR *)(ptr->data);
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_board_info *board_info;
|
||||
struct i2c_client *client_ptr;
|
||||
|
||||
|
||||
if (strncmp(buf, "add", strlen(buf)-1)==0)
|
||||
{
|
||||
adapter = i2c_get_adapter(cdata->parent_bus);
|
||||
board_info = i2c_get_psu_board_info(pdata, cdata);
|
||||
|
||||
/* Populate the platform data for psu */
|
||||
client_ptr = i2c_new_device(adapter, board_info);
|
||||
|
||||
if(client_ptr != NULL)
|
||||
{
|
||||
i2c_put_adapter(adapter);
|
||||
pddf_dbg(PSU, KERN_ERR "Created a %s client: 0x%p\n", cdata->i2c_name , (void *)client_ptr);
|
||||
add_device_table(cdata->i2c_name, (void*)client_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
i2c_put_adapter(adapter);
|
||||
goto free_data;
|
||||
}
|
||||
}
|
||||
else if (strncmp(buf, "delete", strlen(buf)-1)==0)
|
||||
{
|
||||
/*Get the i2c_client handle for the created client*/
|
||||
client_ptr = (struct i2c_client *)get_device_table(cdata->i2c_name);
|
||||
if (client_ptr)
|
||||
{
|
||||
pddf_dbg(PSU, KERN_ERR "Removing %s client: 0x%p\n", cdata->i2c_name, (void *)client_ptr);
|
||||
i2c_unregister_device(client_ptr);
|
||||
delete_device_table(cdata->i2c_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "Unable to get the client handle for %s\n", cdata->i2c_name);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s", __FUNCTION__, buf);
|
||||
}
|
||||
|
||||
goto clear_data;
|
||||
|
||||
free_data:
|
||||
if (board_info->platform_data)
|
||||
{
|
||||
PSU_PDATA *psu_platform_data = board_info->platform_data;
|
||||
if (psu_platform_data->psu_attrs)
|
||||
{
|
||||
printk(KERN_ERR "%s: Unable to create i2c client. Freeing the platform subdata\n", __FUNCTION__);
|
||||
kfree(psu_platform_data->psu_attrs);
|
||||
}
|
||||
printk(KERN_ERR "%s: Unable to create i2c client. Freeing the platform data\n", __FUNCTION__);
|
||||
kfree(psu_platform_data);
|
||||
}
|
||||
|
||||
clear_data:
|
||||
memset(pdata, 0, sizeof(PSU_DATA));
|
||||
/*TODO: free the data cdata->data if data is dynal=mically allocated*/
|
||||
memset(cdata, 0, sizeof(NEW_DEV_ATTR));
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static struct kobject *psu_kobj;
|
||||
static struct kobject *i2c_kobj;
|
||||
|
||||
int __init pddf_data_init(void)
|
||||
{
|
||||
struct kobject *device_kobj;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
pddf_dbg(PSU, "PDDF_DATA MODULE.. init\n");
|
||||
|
||||
device_kobj = get_device_i2c_kobj();
|
||||
if(!device_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
psu_kobj = kobject_create_and_add("psu", device_kobj);
|
||||
if(!psu_kobj)
|
||||
return -ENOMEM;
|
||||
i2c_kobj = kobject_create_and_add("i2c", psu_kobj);
|
||||
if(!i2c_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = sysfs_create_group(i2c_kobj, &pddf_clients_data_group);
|
||||
if (ret)
|
||||
{
|
||||
kobject_put(i2c_kobj);
|
||||
kobject_put(psu_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(PSU, "CREATED PSU I2C CLIENTS CREATION SYSFS GROUP\n");
|
||||
|
||||
ret = sysfs_create_group(i2c_kobj, &pddf_psu_client_data_group);
|
||||
if (ret)
|
||||
{
|
||||
sysfs_remove_group(i2c_kobj, &pddf_clients_data_group);
|
||||
kobject_put(i2c_kobj);
|
||||
kobject_put(psu_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(PSU, "CREATED PDDF PSU DATA SYSFS GROUP\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit pddf_data_exit(void)
|
||||
{
|
||||
|
||||
pddf_dbg(PSU, "PDDF_DATA MODULE.. exit\n");
|
||||
sysfs_remove_group(i2c_kobj, &pddf_psu_client_data_group);
|
||||
sysfs_remove_group(i2c_kobj, &pddf_clients_data_group);
|
||||
kobject_put(i2c_kobj);
|
||||
kobject_put(psu_kobj);
|
||||
pddf_dbg(PSU, KERN_ERR "%s: Removed the kobjects for 'i2c' and 'psu'\n",__FUNCTION__);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(pddf_data_init);
|
||||
module_exit(pddf_data_exit);
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("psu platform data");
|
||||
MODULE_LICENSE("GPL");
|
4
platform/pddf/i2c/modules/sysstatus/Makefile
Normal file
4
platform/pddf/i2c/modules/sysstatus/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
TARGET := pddf_sysstatus_module
|
||||
obj-m := $(TARGET).o
|
||||
|
||||
CFLAGS_$(obj-m):= -I$(M)/modules/include
|
235
platform/pddf/i2c/modules/sysstatus/pddf_sysstatus_module.c
Normal file
235
platform/pddf/i2c/modules/sysstatus/pddf_sysstatus_module.c
Normal file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* A pddf kernel module for system status registers
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/kobject.h>
|
||||
#include "pddf_client_defs.h"
|
||||
#include "pddf_sysstatus_defs.h"
|
||||
|
||||
|
||||
|
||||
SYSSTATUS_DATA sysstatus_data = {0};
|
||||
|
||||
extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||
extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
||||
|
||||
static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
ssize_t show_sysstatus_data(struct device *dev, struct device_attribute *da, char *buf);
|
||||
|
||||
|
||||
PDDF_DATA_ATTR(attr_name, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32,
|
||||
(void*)&sysstatus_data.sysstatus_addr_attr.aname, NULL);
|
||||
PDDF_DATA_ATTR(attr_devaddr, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32,
|
||||
sizeof(uint32_t), (void*)&sysstatus_data.sysstatus_addr_attr.devaddr , NULL);
|
||||
PDDF_DATA_ATTR(attr_offset, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32,
|
||||
sizeof(uint32_t), (void*)&sysstatus_data.sysstatus_addr_attr.offset, NULL);
|
||||
PDDF_DATA_ATTR(attr_mask, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32,
|
||||
sizeof(uint32_t), (void*)&sysstatus_data.sysstatus_addr_attr.mask , NULL);
|
||||
PDDF_DATA_ATTR(attr_len, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32,
|
||||
sizeof(uint32_t), (void*)&sysstatus_data.sysstatus_addr_attr.len , NULL);
|
||||
PDDF_DATA_ATTR(attr_ops, S_IWUSR, NULL, do_attr_operation, PDDF_CHAR, 8, (void*)&sysstatus_data, NULL);
|
||||
|
||||
|
||||
|
||||
static struct attribute *sysstatus_addr_attributes[] = {
|
||||
&attr_attr_name.dev_attr.attr,
|
||||
&attr_attr_devaddr.dev_attr.attr,
|
||||
&attr_attr_offset.dev_attr.attr,
|
||||
&attr_attr_mask.dev_attr.attr,
|
||||
&attr_attr_len.dev_attr.attr,
|
||||
&attr_attr_ops.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
PDDF_DATA_ATTR(board_info, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, 32, NULL, NULL);
|
||||
PDDF_DATA_ATTR(cpld1_version, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
PDDF_DATA_ATTR(cpld2_version, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
PDDF_DATA_ATTR(cpld3_version, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
PDDF_DATA_ATTR(power_module_status, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
PDDF_DATA_ATTR(system_reset1, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
PDDF_DATA_ATTR(system_reset2, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
PDDF_DATA_ATTR(system_reset3, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
PDDF_DATA_ATTR(system_reset4, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
PDDF_DATA_ATTR(system_reset5, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
PDDF_DATA_ATTR(system_reset6, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
PDDF_DATA_ATTR(system_reset7, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
PDDF_DATA_ATTR(system_reset8, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
PDDF_DATA_ATTR(misc1, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
PDDF_DATA_ATTR(misc2, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
PDDF_DATA_ATTR(misc3, S_IWUSR|S_IRUGO, show_sysstatus_data, NULL, PDDF_UINT32, sizeof(uint32_t), NULL, NULL);
|
||||
|
||||
|
||||
|
||||
static struct attribute *sysstatus_data_attributes[] = {
|
||||
&attr_board_info.dev_attr.attr,
|
||||
&attr_cpld1_version.dev_attr.attr,
|
||||
&attr_cpld2_version.dev_attr.attr,
|
||||
&attr_cpld3_version.dev_attr.attr,
|
||||
&attr_power_module_status.dev_attr.attr,
|
||||
&attr_system_reset1.dev_attr.attr,
|
||||
&attr_system_reset2.dev_attr.attr,
|
||||
&attr_system_reset3.dev_attr.attr,
|
||||
&attr_system_reset4.dev_attr.attr,
|
||||
&attr_system_reset5.dev_attr.attr,
|
||||
&attr_system_reset6.dev_attr.attr,
|
||||
&attr_system_reset7.dev_attr.attr,
|
||||
&attr_system_reset8.dev_attr.attr,
|
||||
&attr_misc1.dev_attr.attr,
|
||||
&attr_misc2.dev_attr.attr,
|
||||
&attr_misc3.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
static const struct attribute_group pddf_sysstatus_addr_group = {
|
||||
.attrs = sysstatus_addr_attributes,
|
||||
};
|
||||
|
||||
|
||||
static const struct attribute_group pddf_sysstatus_data_group = {
|
||||
.attrs = sysstatus_data_attributes,
|
||||
};
|
||||
|
||||
|
||||
static struct kobject *sysstatus_addr_kobj;
|
||||
static struct kobject *sysstatus_data_kobj;
|
||||
|
||||
|
||||
|
||||
ssize_t show_sysstatus_data(struct device *dev, struct device_attribute *da, char *buf)
|
||||
{
|
||||
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
|
||||
SYSSTATUS_DATA *data = &sysstatus_data;
|
||||
struct SYSSTATUS_ADDR_ATTR *sysstatus_addr_attrs = NULL;
|
||||
int i, status ;
|
||||
|
||||
|
||||
for (i=0;i<MAX_ATTRS;i++)
|
||||
{
|
||||
if (strcmp(data->sysstatus_addr_attrs[i].aname, attr->dev_attr.attr.name) == 0 )
|
||||
{
|
||||
sysstatus_addr_attrs = &data->sysstatus_addr_attrs[i];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (sysstatus_addr_attrs==NULL )
|
||||
{
|
||||
printk(KERN_DEBUG "%s is not supported attribute for this client\n",data->sysstatus_addr_attrs[i].aname);
|
||||
status = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = board_i2c_cpld_read( sysstatus_addr_attrs->devaddr, sysstatus_addr_attrs->offset);
|
||||
}
|
||||
|
||||
return sprintf(buf, "0x%x\n", (status&sysstatus_addr_attrs->mask));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
SYSSTATUS_DATA *pdata = (SYSSTATUS_DATA *)(ptr->addr);
|
||||
|
||||
pdata->sysstatus_addr_attrs[pdata->len] = pdata->sysstatus_addr_attr;
|
||||
pdata->len++;
|
||||
pddf_dbg(SYSSTATUS, KERN_ERR "%s: Populating the data for %s\n", __FUNCTION__, pdata->sysstatus_addr_attr.aname);
|
||||
memset(&pdata->sysstatus_addr_attr, 0, sizeof(pdata->sysstatus_addr_attr));
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int __init sysstatus_data_init(void)
|
||||
{
|
||||
struct kobject *device_kobj;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
pddf_dbg(SYSSTATUS, "PDDF SYSSTATUS MODULE.. init\n");
|
||||
|
||||
device_kobj = get_device_i2c_kobj();
|
||||
if(!device_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
sysstatus_addr_kobj = kobject_create_and_add("sysstatus", device_kobj);
|
||||
if(!sysstatus_addr_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
sysstatus_data_kobj = kobject_create_and_add("sysstatus_data", sysstatus_addr_kobj);
|
||||
if(!sysstatus_data_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
ret = sysfs_create_group(sysstatus_addr_kobj, &pddf_sysstatus_addr_group);
|
||||
if (ret)
|
||||
{
|
||||
kobject_put(sysstatus_addr_kobj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(sysstatus_data_kobj, &pddf_sysstatus_data_group);
|
||||
if (ret)
|
||||
{
|
||||
sysfs_remove_group(sysstatus_addr_kobj, &pddf_sysstatus_addr_group);
|
||||
kobject_put(sysstatus_data_kobj);
|
||||
kobject_put(sysstatus_addr_kobj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit sysstatus_data_exit(void)
|
||||
{
|
||||
pddf_dbg(SYSSTATUS, "PDDF SYSSTATUS MODULE.. exit\n");
|
||||
sysfs_remove_group(sysstatus_data_kobj, &pddf_sysstatus_data_group);
|
||||
sysfs_remove_group(sysstatus_addr_kobj, &pddf_sysstatus_addr_group);
|
||||
kobject_put(sysstatus_data_kobj);
|
||||
kobject_put(sysstatus_addr_kobj);
|
||||
pddf_dbg(SYSSTATUS, KERN_ERR "%s: Removed the kobjects for 'SYSSTATUS'\n",__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(sysstatus_data_init);
|
||||
module_exit(sysstatus_data_exit);
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("SYSSTATUS platform data");
|
||||
MODULE_LICENSE("GPL");
|
4
platform/pddf/i2c/modules/xcvr/Makefile
Normal file
4
platform/pddf/i2c/modules/xcvr/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
subdir-m := driver
|
||||
obj-m := pddf_xcvr_module.o
|
||||
|
||||
CFLAGS_$(obj-m):= -I$(M)/modules/include
|
7
platform/pddf/i2c/modules/xcvr/driver/Makefile
Normal file
7
platform/pddf/i2c/modules/xcvr/driver/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
TARGET = pddf_xcvr_driver_module
|
||||
|
||||
obj-m := $(TARGET).o
|
||||
|
||||
$(TARGET)-objs := pddf_xcvr_api.o pddf_xcvr_driver.o
|
||||
|
||||
ccflags-y := -I$(M)/modules/include
|
909
platform/pddf/i2c/modules/xcvr/driver/pddf_xcvr_api.c
Normal file
909
platform/pddf/i2c/modules/xcvr/driver/pddf_xcvr_api.c
Normal file
@ -0,0 +1,909 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* Description of various APIs related to transciever component
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/kobject.h>
|
||||
#include "pddf_xcvr_defs.h"
|
||||
|
||||
/*#define SFP_DEBUG*/
|
||||
#ifdef SFP_DEBUG
|
||||
#define sfp_dbg(...) printk(__VA_ARGS__)
|
||||
#else
|
||||
#define sfp_dbg(...)
|
||||
#endif
|
||||
|
||||
extern XCVR_SYSFS_ATTR_OPS xcvr_ops[];
|
||||
extern void *get_device_table(char *name);
|
||||
|
||||
int get_xcvr_module_attr_data(struct i2c_client *client, struct device *dev,
|
||||
struct device_attribute *da);
|
||||
|
||||
int xcvr_i2c_cpld_read(XCVR_ATTR *info)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
if (info!=NULL)
|
||||
{
|
||||
if (info->len==1)
|
||||
{
|
||||
status = board_i2c_cpld_read(info->devaddr , info->offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the I2C client for the CPLD */
|
||||
struct i2c_client *client_ptr=NULL;
|
||||
client_ptr = (struct i2c_client *)get_device_table(info->devname);
|
||||
if (client_ptr)
|
||||
{
|
||||
if (info->len==2)
|
||||
{
|
||||
status = i2c_smbus_read_word_swapped(client_ptr, info->offset);
|
||||
}
|
||||
else
|
||||
printk(KERN_ERR "PDDF_XCVR: Doesn't support block CPLD read yet");
|
||||
}
|
||||
else
|
||||
printk(KERN_ERR "Unable to get the client handle for %s\n", info->devname);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_mod_pres(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data)
|
||||
{
|
||||
int status = 0;
|
||||
uint32_t modpres = 0;
|
||||
|
||||
if ( strcmp(info->devtype, "cpld") == 0)
|
||||
{
|
||||
status = xcvr_i2c_cpld_read(info);
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
else
|
||||
{
|
||||
modpres = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
|
||||
sfp_dbg(KERN_INFO "\nMod presence :0x%x, reg_value = 0x%x, devaddr=0x%x, mask=0x%x, offset=0x%x\n", modpres, status, info->devaddr, info->mask, info->offset);
|
||||
}
|
||||
}
|
||||
else if(strcmp(info->devtype, "eeprom") == 0)
|
||||
{
|
||||
/* get client client for eeprom - Not Applicable */
|
||||
}
|
||||
data->modpres = modpres;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_mod_reset(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data)
|
||||
{
|
||||
int status = 0;
|
||||
uint32_t modreset=0;
|
||||
|
||||
if (strcmp(info->devtype, "cpld") == 0)
|
||||
{
|
||||
status = xcvr_i2c_cpld_read(info);
|
||||
if (status < 0)
|
||||
return status;
|
||||
else
|
||||
{
|
||||
modreset = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
|
||||
sfp_dbg(KERN_INFO "\nMod Reset :0x%x, reg_value = 0x%x\n", modreset, status);
|
||||
}
|
||||
}
|
||||
else if(strcmp(info->devtype, "eeprom") == 0)
|
||||
{
|
||||
/* get client client for eeprom - Not Applicable */
|
||||
}
|
||||
|
||||
data->reset = modreset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_mod_intr_status(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data)
|
||||
{
|
||||
int status = 0;
|
||||
uint32_t mod_intr = 0;
|
||||
|
||||
if (strcmp(info->devtype, "cpld") == 0)
|
||||
{
|
||||
status = xcvr_i2c_cpld_read(info);
|
||||
if (status < 0)
|
||||
return status;
|
||||
else
|
||||
{
|
||||
mod_intr = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
|
||||
sfp_dbg(KERN_INFO "\nModule Interrupt :0x%x, reg_value = 0x%x\n", mod_intr, status);
|
||||
}
|
||||
}
|
||||
else if(strcmp(info->devtype, "eeprom") == 0)
|
||||
{
|
||||
/* get client client for eeprom - Not Applicable */
|
||||
}
|
||||
|
||||
data->intr_status = mod_intr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int sonic_i2c_get_mod_lpmode(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data)
|
||||
{
|
||||
int status = 0;
|
||||
uint32_t lpmode = 0;
|
||||
|
||||
if (strcmp(info->devtype, "cpld") == 0)
|
||||
{
|
||||
status = xcvr_i2c_cpld_read(info);
|
||||
if (status < 0)
|
||||
return status;
|
||||
else
|
||||
{
|
||||
lpmode = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
|
||||
sfp_dbg(KERN_INFO "\nModule LPmode :0x%x, reg_value = 0x%x\n", lpmode, status);
|
||||
}
|
||||
}
|
||||
else if (strcmp(info->devtype, "eeprom") == 0)
|
||||
{
|
||||
/* get client client for eeprom - Not Applicable */
|
||||
}
|
||||
|
||||
data->lpmode = lpmode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_mod_rxlos(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data)
|
||||
{
|
||||
int status = 0;
|
||||
uint32_t rxlos = 0;
|
||||
|
||||
|
||||
if (strcmp(info->devtype, "cpld") == 0)
|
||||
{
|
||||
status = xcvr_i2c_cpld_read(info);
|
||||
if (status < 0)
|
||||
return status;
|
||||
else
|
||||
{
|
||||
rxlos = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
|
||||
sfp_dbg(KERN_INFO "\nModule RxLOS :0x%x, reg_value = 0x%x\n", rxlos, status);
|
||||
}
|
||||
}
|
||||
data->rxlos = rxlos;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_mod_txdisable(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data)
|
||||
{
|
||||
int status = 0;
|
||||
uint32_t txdis = 0;
|
||||
|
||||
if (strcmp(info->devtype, "cpld") == 0)
|
||||
{
|
||||
status = xcvr_i2c_cpld_read(info);
|
||||
if (status < 0)
|
||||
return status;
|
||||
else
|
||||
{
|
||||
txdis = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
|
||||
sfp_dbg(KERN_INFO "\nModule TxDisable :0x%x, reg_value = 0x%x\n", txdis, status);
|
||||
}
|
||||
}
|
||||
data->txdisable = txdis;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_get_mod_txfault(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data)
|
||||
{
|
||||
int status = 0;
|
||||
uint32_t txflt = 0;
|
||||
|
||||
if (strcmp(info->devtype, "cpld") == 0)
|
||||
{
|
||||
status = xcvr_i2c_cpld_read(info);
|
||||
if (status < 0)
|
||||
return status;
|
||||
else
|
||||
{
|
||||
txflt = ((status & BIT_INDEX(info->mask)) == info->cmpval) ? 1 : 0;
|
||||
sfp_dbg(KERN_INFO "\nModule TxFault :0x%x, reg_value = 0x%x\n", txflt, status);
|
||||
}
|
||||
|
||||
}
|
||||
data->txfault = txflt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sonic_i2c_set_mod_reset(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data)
|
||||
{
|
||||
int status = 0;
|
||||
unsigned int val_mask = 0, dnd_value = 0;
|
||||
uint32_t reg;
|
||||
struct i2c_client *client_ptr=NULL;
|
||||
|
||||
if (strcmp(info->devtype, "cpld") == 0)
|
||||
{
|
||||
val_mask = BIT_INDEX(info->mask);
|
||||
/* Get the I2C client for the CPLD */
|
||||
client_ptr = (struct i2c_client *)get_device_table(info->devname);
|
||||
|
||||
if (client_ptr)
|
||||
{
|
||||
if (info->len == 1)
|
||||
status = board_i2c_cpld_read(info->devaddr , info->offset);
|
||||
else if (info->len == 2)
|
||||
status = i2c_smbus_read_word_data(client_ptr, info->offset);
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "PDDF_XCVR: Doesn't support block CPLD read yet");
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "Unable to get the client handle for %s\n", info->devname);
|
||||
status = -1;
|
||||
}
|
||||
/*printk(KERN_ERR "sonic_i2c_set_mod_reset:client_ptr=0x%x, status=0x%x, offset=0x%x, len=%d\n", client_ptr, status, info->offset, info->len);*/
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
else
|
||||
{
|
||||
dnd_value = status & ~val_mask;
|
||||
if (((data->reset == 1) && (info->cmpval != 0)) || ((data->reset == 0) && (info->cmpval == 0)))
|
||||
reg = dnd_value | val_mask;
|
||||
else
|
||||
reg = dnd_value;
|
||||
if (info->len == 1)
|
||||
status = board_i2c_cpld_write(info->devaddr, info->offset, (uint8_t)reg);
|
||||
else if (info->len == 2)
|
||||
status = i2c_smbus_write_word_swapped(client_ptr, info->offset, (uint16_t)reg);
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "PDDF_XCVR: Doesn't support block CPLD write yet");
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int sonic_i2c_set_mod_lpmode(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data)
|
||||
{
|
||||
int status = 0;
|
||||
unsigned int val_mask = 0, dnd_value = 0;
|
||||
uint32_t reg;
|
||||
struct i2c_client *client_ptr=NULL;
|
||||
|
||||
if (strcmp(info->devtype, "cpld") == 0)
|
||||
{
|
||||
val_mask = BIT_INDEX(info->mask);
|
||||
/* Get the I2C client for the CPLD */
|
||||
client_ptr = (struct i2c_client *)get_device_table(info->devname);
|
||||
|
||||
if (client_ptr)
|
||||
{
|
||||
if (info->len == 1)
|
||||
status = board_i2c_cpld_read(info->devaddr , info->offset);
|
||||
else if (info->len == 2)
|
||||
status = i2c_smbus_read_word_data(client_ptr, info->offset);
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "PDDF_XCVR: Doesn't support block CPLD read yet");
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "Unable to get the client handle for %s\n", info->devname);
|
||||
status = -1;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
else
|
||||
{
|
||||
dnd_value = status & ~val_mask;
|
||||
if (((data->lpmode == 1) && (info->cmpval != 0)) || ((data->lpmode == 0) && (info->cmpval == 0)))
|
||||
reg = dnd_value | val_mask;
|
||||
else
|
||||
reg = dnd_value;
|
||||
if (info->len == 1)
|
||||
status = board_i2c_cpld_write(info->devaddr, info->offset, (uint8_t)reg);
|
||||
else if (info->len == 2)
|
||||
status = i2c_smbus_write_word_swapped(client_ptr, info->offset, (uint16_t)reg);
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "PDDF_XCVR: Doesn't support block CPLD write yet");
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int sonic_i2c_set_mod_txdisable(struct i2c_client *client, XCVR_ATTR *info, struct xcvr_data *data)
|
||||
{
|
||||
int status = 0;
|
||||
unsigned int val_mask = 0, dnd_value = 0;
|
||||
uint32_t reg;
|
||||
struct i2c_client *client_ptr=NULL;
|
||||
|
||||
if (strcmp(info->devtype, "cpld") == 0)
|
||||
{
|
||||
val_mask = BIT_INDEX(info->mask);
|
||||
/* Get the I2C client for the CPLD */
|
||||
client_ptr = (struct i2c_client *)get_device_table(info->devname);
|
||||
|
||||
if (client_ptr)
|
||||
{
|
||||
if (info->len == 1)
|
||||
status = board_i2c_cpld_read(info->devaddr , info->offset);
|
||||
else if (info->len == 2)
|
||||
status = i2c_smbus_read_word_data(client_ptr, info->offset);
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "PDDF_XCVR: Doesn't support block CPLD read yet");
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "Unable to get the client handle for %s\n", info->devname);
|
||||
status = -1;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
else
|
||||
{
|
||||
dnd_value = status & ~val_mask;
|
||||
if (((data->txdisable == 1) && (info->cmpval != 0)) || ((data->txdisable == 0) && (info->cmpval == 0)))
|
||||
reg = dnd_value | val_mask;
|
||||
else
|
||||
reg = dnd_value;
|
||||
if (info->len == 1)
|
||||
status = board_i2c_cpld_write(info->devaddr, info->offset, (uint8_t)reg);
|
||||
else if (info->len == 2)
|
||||
status = i2c_smbus_write_word_swapped(client_ptr, info->offset, (uint16_t)reg);
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "PDDF_XCVR: Doesn't support block CPLD write yet");
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
ssize_t get_module_presence(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct xcvr_data *data = i2c_get_clientdata(client);
|
||||
XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data);
|
||||
XCVR_ATTR *attr_data = NULL;
|
||||
XCVR_SYSFS_ATTR_OPS *attr_ops = NULL;
|
||||
int status = 0, i;
|
||||
|
||||
for (i=0; i<pdata->len; i++)
|
||||
{
|
||||
attr_data = &pdata->xcvr_attrs[i];
|
||||
if (strcmp(attr_data->aname, attr->dev_attr.attr.name) == 0)
|
||||
{
|
||||
attr_ops = &xcvr_ops[attr->index];
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
if (attr_ops->pre_get != NULL)
|
||||
{
|
||||
status = (attr_ops->pre_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
if (attr_ops->do_get != NULL)
|
||||
{
|
||||
status = (attr_ops->do_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: do_get function fails for %s attribute. ret %d\n", __FUNCTION__, attr_data->aname, status);
|
||||
|
||||
}
|
||||
if (attr_ops->post_get != NULL)
|
||||
{
|
||||
status = (attr_ops->post_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
return sprintf(buf, "%d\n", data->modpres);
|
||||
}
|
||||
}
|
||||
return sprintf(buf, "%s","");
|
||||
}
|
||||
|
||||
ssize_t get_module_reset(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct xcvr_data *data = i2c_get_clientdata(client);
|
||||
XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data);
|
||||
XCVR_ATTR *attr_data = NULL;
|
||||
XCVR_SYSFS_ATTR_OPS *attr_ops = NULL;
|
||||
int status = 0, i;
|
||||
|
||||
for (i=0; i<pdata->len; i++)
|
||||
{
|
||||
attr_data = &pdata->xcvr_attrs[i];
|
||||
if (strcmp(attr_data->aname, attr->dev_attr.attr.name) == 0)
|
||||
{
|
||||
attr_ops = &xcvr_ops[attr->index];
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
if (attr_ops->pre_get != NULL)
|
||||
{
|
||||
status = (attr_ops->pre_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
if (attr_ops->do_get != NULL)
|
||||
{
|
||||
status = (attr_ops->do_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
|
||||
}
|
||||
if (attr_ops->post_get != NULL)
|
||||
{
|
||||
status = (attr_ops->post_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return sprintf(buf, "%d\n", data->reset);
|
||||
}
|
||||
}
|
||||
return sprintf(buf, "%s","");
|
||||
}
|
||||
|
||||
ssize_t set_module_reset(struct device *dev, struct device_attribute *da, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct xcvr_data *data = i2c_get_clientdata(client);
|
||||
XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data);
|
||||
XCVR_ATTR *attr_data = NULL;
|
||||
XCVR_SYSFS_ATTR_OPS *attr_ops = NULL;
|
||||
int status = 0, i;
|
||||
unsigned int set_value;
|
||||
|
||||
for (i=0; i<pdata->len; i++)
|
||||
{
|
||||
attr_data = &pdata->xcvr_attrs[i];
|
||||
if (strcmp(attr_data->aname, attr->dev_attr.attr.name) == 0)
|
||||
{
|
||||
attr_ops = &xcvr_ops[attr->index];
|
||||
if(kstrtoint(buf, 10, &set_value))
|
||||
return -EINVAL;
|
||||
if ((set_value != 1) && (set_value != 0))
|
||||
return -EINVAL;
|
||||
|
||||
data->reset = set_value;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
if (attr_ops->pre_set != NULL)
|
||||
{
|
||||
status = (attr_ops->pre_set)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
if (attr_ops->do_set != NULL)
|
||||
{
|
||||
status = (attr_ops->do_set)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
|
||||
}
|
||||
if (attr_ops->post_set != NULL)
|
||||
{
|
||||
status = (attr_ops->post_set)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ssize_t get_module_intr_status(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct xcvr_data *data = i2c_get_clientdata(client);
|
||||
XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data);
|
||||
XCVR_ATTR *attr_data = NULL;
|
||||
XCVR_SYSFS_ATTR_OPS *attr_ops = NULL;
|
||||
int status = 0, i;
|
||||
|
||||
for (i=0; i<pdata->len; i++)
|
||||
{
|
||||
attr_data = &pdata->xcvr_attrs[i];
|
||||
if (strcmp(attr_data->aname, attr->dev_attr.attr.name) == 0)
|
||||
{
|
||||
attr_ops = &xcvr_ops[attr->index];
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
if (attr_ops->pre_get != NULL)
|
||||
{
|
||||
status = (attr_ops->pre_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
if (attr_ops->do_get != NULL)
|
||||
{
|
||||
status = (attr_ops->do_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
|
||||
}
|
||||
if (attr_ops->post_get != NULL)
|
||||
{
|
||||
status = (attr_ops->post_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
return sprintf(buf, "%d\n", data->intr_status);
|
||||
}
|
||||
}
|
||||
return sprintf(buf, "%s","");
|
||||
}
|
||||
|
||||
int get_xcvr_module_attr_data(struct i2c_client *client, struct device *dev,
|
||||
struct device_attribute *da)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data);
|
||||
XCVR_ATTR *attr_data = NULL;
|
||||
int i;
|
||||
|
||||
for (i=0; i < pdata->len; i++)
|
||||
{
|
||||
attr_data = &pdata->xcvr_attrs[i];
|
||||
if (strcmp(attr_data->aname, attr->dev_attr.attr.name) == 0)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t get_module_lpmode(struct device *dev, struct device_attribute *da, char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data);
|
||||
struct xcvr_data *data = i2c_get_clientdata(client);
|
||||
XCVR_ATTR *attr_data = NULL;
|
||||
XCVR_SYSFS_ATTR_OPS *attr_ops = NULL;
|
||||
int idx, status = 0;
|
||||
|
||||
idx = get_xcvr_module_attr_data(client, dev, da);
|
||||
|
||||
if (idx>=0) attr_data = &pdata->xcvr_attrs[idx];
|
||||
|
||||
if (attr_data!=NULL)
|
||||
{
|
||||
|
||||
attr_ops = &xcvr_ops[attr->index];
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
if (attr_ops->pre_get != NULL)
|
||||
{
|
||||
status = (attr_ops->pre_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
if (attr_ops->do_get != NULL)
|
||||
{
|
||||
status = (attr_ops->do_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
|
||||
}
|
||||
if (attr_ops->post_get != NULL)
|
||||
{
|
||||
status = (attr_ops->post_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
return sprintf(buf, "%d\n", data->lpmode);
|
||||
}
|
||||
else
|
||||
return sprintf(buf,"%s","");
|
||||
}
|
||||
|
||||
ssize_t set_module_lpmode(struct device *dev, struct device_attribute *da, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct xcvr_data *data = i2c_get_clientdata(client);
|
||||
XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data);
|
||||
int idx, status = 0;
|
||||
uint32_t set_value;
|
||||
XCVR_ATTR *attr_data = NULL;
|
||||
XCVR_SYSFS_ATTR_OPS *attr_ops = NULL;
|
||||
|
||||
idx = get_xcvr_module_attr_data(client, dev, da);
|
||||
|
||||
if (idx>=0) attr_data = &pdata->xcvr_attrs[idx];
|
||||
|
||||
if (attr_data!=NULL)
|
||||
{
|
||||
attr_ops = &xcvr_ops[attr->index];
|
||||
if(kstrtoint(buf, 10, &set_value))
|
||||
return -EINVAL;
|
||||
if ((set_value != 1) && (set_value != 0))
|
||||
return -EINVAL;
|
||||
|
||||
data->lpmode = set_value;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
if (attr_ops->pre_set != NULL)
|
||||
{
|
||||
status = (attr_ops->pre_set)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
if (attr_ops->do_set != NULL)
|
||||
{
|
||||
status = (attr_ops->do_set)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
|
||||
}
|
||||
if (attr_ops->post_set != NULL)
|
||||
{
|
||||
status = (attr_ops->post_set)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
ssize_t get_module_rxlos(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct xcvr_data *data = i2c_get_clientdata(client);
|
||||
XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data);
|
||||
int idx, status = 0;
|
||||
XCVR_ATTR *attr_data = NULL;
|
||||
XCVR_SYSFS_ATTR_OPS *attr_ops = NULL;
|
||||
|
||||
idx = get_xcvr_module_attr_data(client, dev, da);
|
||||
|
||||
if (idx>=0) attr_data = &pdata->xcvr_attrs[idx];
|
||||
|
||||
if (attr_data!=NULL)
|
||||
{
|
||||
attr_ops = &xcvr_ops[attr->index];
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
if (attr_ops->pre_get != NULL)
|
||||
{
|
||||
status = (attr_ops->pre_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
if (attr_ops->do_get != NULL)
|
||||
{
|
||||
status = (attr_ops->do_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
|
||||
}
|
||||
if (attr_ops->post_get != NULL)
|
||||
{
|
||||
status = (attr_ops->post_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
return sprintf(buf, "%d\n", data->rxlos);
|
||||
}
|
||||
else
|
||||
return sprintf(buf,"%s","");
|
||||
}
|
||||
|
||||
ssize_t get_module_txdisable(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct xcvr_data *data = i2c_get_clientdata(client);
|
||||
XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data);
|
||||
int idx, status = 0;
|
||||
XCVR_ATTR *attr_data = NULL;
|
||||
XCVR_SYSFS_ATTR_OPS *attr_ops = NULL;
|
||||
|
||||
idx = get_xcvr_module_attr_data(client, dev, da);
|
||||
|
||||
if (idx>=0) attr_data = &pdata->xcvr_attrs[idx];
|
||||
|
||||
if (attr_data!=NULL)
|
||||
{
|
||||
attr_ops = &xcvr_ops[attr->index];
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
if (attr_ops->pre_get != NULL)
|
||||
{
|
||||
status = (attr_ops->pre_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
if (attr_ops->do_get != NULL)
|
||||
{
|
||||
status = (attr_ops->do_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
|
||||
}
|
||||
if (attr_ops->post_get != NULL)
|
||||
{
|
||||
status = (attr_ops->post_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
return sprintf(buf, "%d\n", data->txdisable);
|
||||
}
|
||||
else
|
||||
return sprintf(buf,"%s","");
|
||||
}
|
||||
|
||||
ssize_t set_module_txdisable(struct device *dev, struct device_attribute *da, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct xcvr_data *data = i2c_get_clientdata(client);
|
||||
XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data);
|
||||
int idx, status = 0;
|
||||
uint32_t set_value;
|
||||
XCVR_ATTR *attr_data = NULL;
|
||||
XCVR_SYSFS_ATTR_OPS *attr_ops = NULL;
|
||||
|
||||
idx = get_xcvr_module_attr_data(client, dev, da);
|
||||
|
||||
if (idx>=0) attr_data = &pdata->xcvr_attrs[idx];
|
||||
|
||||
if (attr_data!=NULL)
|
||||
{
|
||||
attr_ops = &xcvr_ops[attr->index];
|
||||
if(kstrtoint(buf, 10, &set_value))
|
||||
return -EINVAL;
|
||||
if ((set_value != 1) && (set_value != 0))
|
||||
return -EINVAL;
|
||||
|
||||
data->txdisable = set_value;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
if (attr_ops->pre_set != NULL)
|
||||
{
|
||||
status = (attr_ops->pre_set)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: pre_set function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
if (attr_ops->do_set != NULL)
|
||||
{
|
||||
status = (attr_ops->do_set)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: do_set function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
|
||||
}
|
||||
if (attr_ops->post_set != NULL)
|
||||
{
|
||||
status = (attr_ops->post_set)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: post_set function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
ssize_t get_module_txfault(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
XCVR_PDATA *pdata = (XCVR_PDATA *)(client->dev.platform_data);
|
||||
struct xcvr_data *data = i2c_get_clientdata(client);
|
||||
int idx, status = 0;
|
||||
XCVR_ATTR *attr_data = NULL;
|
||||
XCVR_SYSFS_ATTR_OPS *attr_ops = NULL;
|
||||
|
||||
idx = get_xcvr_module_attr_data(client, dev, da);
|
||||
|
||||
if (idx>=0) attr_data = &pdata->xcvr_attrs[idx];
|
||||
|
||||
if (attr_data!=NULL)
|
||||
{
|
||||
attr_ops = &xcvr_ops[attr->index];
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
if (attr_ops->pre_get != NULL)
|
||||
{
|
||||
status = (attr_ops->pre_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: pre_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
if (attr_ops->do_get != NULL)
|
||||
{
|
||||
status = (attr_ops->do_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: do_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
|
||||
}
|
||||
if (attr_ops->post_get != NULL)
|
||||
{
|
||||
status = (attr_ops->post_get)(client, attr_data, data);
|
||||
if (status!=0)
|
||||
printk(KERN_ERR "%s: post_get function fails for %s attribute\n", __FUNCTION__, attr_data->aname);
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
return sprintf(buf, "%d\n", data->txfault);
|
||||
}
|
||||
return sprintf(buf,"%s","");
|
||||
}
|
296
platform/pddf/i2c/modules/xcvr/driver/pddf_xcvr_driver.c
Normal file
296
platform/pddf/i2c/modules/xcvr/driver/pddf_xcvr_driver.c
Normal file
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* A pddf kernel driver module for Optic component
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/kobject.h>
|
||||
#include "pddf_client_defs.h"
|
||||
#include "pddf_xcvr_defs.h"
|
||||
#include "pddf_xcvr_api.h"
|
||||
|
||||
|
||||
struct pddf_ops_t pddf_xcvr_ops = {
|
||||
.pre_init = NULL,
|
||||
.post_init = NULL,
|
||||
|
||||
.pre_probe = NULL,
|
||||
.post_probe = NULL,
|
||||
|
||||
.pre_remove = NULL,
|
||||
.post_remove = NULL,
|
||||
|
||||
.pre_exit = NULL,
|
||||
.post_exit = NULL,
|
||||
};
|
||||
EXPORT_SYMBOL(pddf_xcvr_ops);
|
||||
|
||||
XCVR_SYSFS_ATTR_OPS xcvr_ops[XCVR_ATTR_MAX] = {
|
||||
{XCVR_PRESENT, get_module_presence, NULL, sonic_i2c_get_mod_pres, NULL, NULL, NULL, NULL, NULL},
|
||||
{XCVR_RESET, get_module_reset, NULL, sonic_i2c_get_mod_reset, NULL, set_module_reset, NULL, sonic_i2c_set_mod_reset, NULL},
|
||||
{XCVR_INTR_STATUS, get_module_intr_status, NULL, sonic_i2c_get_mod_intr_status, NULL, NULL, NULL, NULL, NULL},
|
||||
{XCVR_LPMODE, get_module_lpmode, NULL, sonic_i2c_get_mod_lpmode, NULL, set_module_lpmode, NULL, sonic_i2c_set_mod_lpmode, NULL},
|
||||
{XCVR_RXLOS, get_module_rxlos, NULL, sonic_i2c_get_mod_rxlos, NULL, NULL, NULL, NULL, NULL},
|
||||
{XCVR_TXDISABLE, get_module_txdisable, NULL, sonic_i2c_get_mod_txdisable, NULL, set_module_txdisable, NULL, sonic_i2c_set_mod_txdisable, NULL},
|
||||
{XCVR_TXFAULT, get_module_txfault, NULL, sonic_i2c_get_mod_txfault, NULL, NULL, NULL, NULL, NULL},
|
||||
};
|
||||
EXPORT_SYMBOL(xcvr_ops);
|
||||
|
||||
|
||||
/* sysfs attributes
|
||||
*/
|
||||
static SENSOR_DEVICE_ATTR(xcvr_present, S_IWUSR|S_IRUGO, get_module_presence, NULL, XCVR_PRESENT);
|
||||
static SENSOR_DEVICE_ATTR(xcvr_reset, S_IWUSR|S_IRUGO, get_module_reset, set_module_reset, XCVR_RESET);
|
||||
static SENSOR_DEVICE_ATTR(xcvr_intr_status, S_IWUSR|S_IRUGO, get_module_intr_status, NULL, XCVR_INTR_STATUS);
|
||||
static SENSOR_DEVICE_ATTR(xcvr_lpmode, S_IWUSR|S_IRUGO, get_module_lpmode, set_module_lpmode, XCVR_LPMODE);
|
||||
static SENSOR_DEVICE_ATTR(xcvr_rxlos, S_IWUSR|S_IRUGO, get_module_rxlos, NULL, XCVR_RXLOS);
|
||||
static SENSOR_DEVICE_ATTR(xcvr_txdisable, S_IWUSR|S_IRUGO, get_module_txdisable, set_module_txdisable, XCVR_TXDISABLE);
|
||||
static SENSOR_DEVICE_ATTR(xcvr_txfault, S_IWUSR|S_IRUGO, get_module_txfault, NULL, XCVR_TXFAULT);
|
||||
|
||||
/* List of all the xcvr attribute structures
|
||||
* to get name, use sensor_dev_attr_<>.dev_attr.attr.name
|
||||
* to get the id, use sensor_dev_attr_<>.dev_attr.index
|
||||
*/
|
||||
static struct sensor_device_attribute *xcvr_attr_list[MAX_XCVR_ATTRS] = {
|
||||
&sensor_dev_attr_xcvr_present,
|
||||
&sensor_dev_attr_xcvr_reset,
|
||||
&sensor_dev_attr_xcvr_intr_status,
|
||||
&sensor_dev_attr_xcvr_lpmode,
|
||||
&sensor_dev_attr_xcvr_rxlos,
|
||||
&sensor_dev_attr_xcvr_txdisable,
|
||||
&sensor_dev_attr_xcvr_txfault,
|
||||
};
|
||||
|
||||
static struct attribute *xcvr_attributes[MAX_XCVR_ATTRS] = {NULL};
|
||||
|
||||
static const struct attribute_group xcvr_group = {
|
||||
.attrs = xcvr_attributes,
|
||||
};
|
||||
|
||||
static int xcvr_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *dev_id)
|
||||
{
|
||||
struct xcvr_data *data;
|
||||
int status =0;
|
||||
int i,j,num;
|
||||
XCVR_PDATA *xcvr_platform_data;
|
||||
XCVR_ATTR *attr_data;
|
||||
|
||||
if (client == NULL) {
|
||||
pddf_dbg(XCVR, "NULL Client.. \n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (pddf_xcvr_ops.pre_probe)
|
||||
{
|
||||
status = (pddf_xcvr_ops.pre_probe)(client, dev_id);
|
||||
if (status != 0)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
|
||||
status = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
data = kzalloc(sizeof(struct xcvr_data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
status = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
data->valid = 0;
|
||||
|
||||
dev_info(&client->dev, "chip found\n");
|
||||
|
||||
/* Take control of the platform data */
|
||||
xcvr_platform_data = (XCVR_PDATA *)(client->dev.platform_data);
|
||||
num = xcvr_platform_data->len;
|
||||
data->index = xcvr_platform_data->idx - 1;
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
/* Add supported attr in the 'attributes' list */
|
||||
for (i=0; i<num; i++)
|
||||
{
|
||||
struct attribute *aptr = NULL;
|
||||
attr_data = xcvr_platform_data->xcvr_attrs + i;
|
||||
for(j=0;j<XCVR_ATTR_MAX;j++)
|
||||
{
|
||||
aptr = &xcvr_attr_list[j]->dev_attr.attr;
|
||||
|
||||
if (strncmp(aptr->name, attr_data->aname, strlen(attr_data->aname))==0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j<XCVR_ATTR_MAX)
|
||||
xcvr_attributes[i] = &xcvr_attr_list[j]->dev_attr.attr;
|
||||
|
||||
}
|
||||
xcvr_attributes[i] = NULL;
|
||||
|
||||
/* Register sysfs hooks */
|
||||
status = sysfs_create_group(&client->dev.kobj, &xcvr_group);
|
||||
if (status) {
|
||||
goto exit_free;
|
||||
}
|
||||
|
||||
data->xdev = hwmon_device_register(&client->dev);
|
||||
if (IS_ERR(data->xdev)) {
|
||||
status = PTR_ERR(data->xdev);
|
||||
goto exit_remove;
|
||||
}
|
||||
|
||||
dev_info(&client->dev, "%s: xcvr '%s'\n",
|
||||
dev_name(data->xdev), client->name);
|
||||
|
||||
/* Add a support for post probe function */
|
||||
if (pddf_xcvr_ops.post_probe)
|
||||
{
|
||||
status = (pddf_xcvr_ops.post_probe)(client, dev_id);
|
||||
if (status != 0)
|
||||
goto exit_remove;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
exit_remove:
|
||||
sysfs_remove_group(&client->dev.kobj, &xcvr_group);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int xcvr_remove(struct i2c_client *client)
|
||||
{
|
||||
int ret = 0;
|
||||
struct xcvr_data *data = i2c_get_clientdata(client);
|
||||
XCVR_PDATA *platdata = (XCVR_PDATA *)client->dev.platform_data;
|
||||
XCVR_ATTR *platdata_sub = platdata->xcvr_attrs;
|
||||
|
||||
if (pddf_xcvr_ops.pre_remove)
|
||||
{
|
||||
ret = (pddf_xcvr_ops.pre_remove)(client);
|
||||
if (ret!=0)
|
||||
printk(KERN_ERR "FAN pre_remove function failed\n");
|
||||
}
|
||||
|
||||
hwmon_device_unregister(data->xdev);
|
||||
sysfs_remove_group(&client->dev.kobj, &xcvr_group);
|
||||
kfree(data);
|
||||
|
||||
if (platdata_sub) {
|
||||
pddf_dbg(XCVR, KERN_DEBUG "%s: Freeing platform subdata\n", __FUNCTION__);
|
||||
kfree(platdata_sub);
|
||||
}
|
||||
if (platdata) {
|
||||
pddf_dbg(XCVR, KERN_DEBUG "%s: Freeing platform data\n", __FUNCTION__);
|
||||
kfree(platdata);
|
||||
}
|
||||
|
||||
if (pddf_xcvr_ops.post_remove)
|
||||
{
|
||||
ret = (pddf_xcvr_ops.post_remove)(client);
|
||||
if (ret!=0)
|
||||
printk(KERN_ERR "FAN post_remove function failed\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum xcvr_intf
|
||||
{
|
||||
XCVR_CTRL_INTF,
|
||||
};
|
||||
|
||||
static const struct i2c_device_id xcvr_ids[] = {
|
||||
{ "pddf_xcvr", XCVR_CTRL_INTF },
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, xcvr_ids);
|
||||
|
||||
static struct i2c_driver xcvr_driver = {
|
||||
/*.class = I2C_CLASS_HWMON,*/
|
||||
.driver = {
|
||||
.name = "xcvr",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = xcvr_probe,
|
||||
.remove = xcvr_remove,
|
||||
.id_table = xcvr_ids,
|
||||
};
|
||||
|
||||
|
||||
/*int __init xcvr_init(void)*/
|
||||
int xcvr_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (pddf_xcvr_ops.pre_init)
|
||||
{
|
||||
ret = (pddf_xcvr_ops.pre_init)();
|
||||
if (ret!=0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
pddf_dbg(XCVR, KERN_ERR "PDDF XCVR DRIVER.. init Invoked..\n");
|
||||
ret = i2c_add_driver(&xcvr_driver);
|
||||
if (ret!=0)
|
||||
return ret;
|
||||
|
||||
if (pddf_xcvr_ops.post_init)
|
||||
{
|
||||
ret = (pddf_xcvr_ops.post_init)();
|
||||
if (ret!=0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(xcvr_init);
|
||||
|
||||
void __exit xcvr_exit(void)
|
||||
{
|
||||
pddf_dbg(XCVR, "PDDF XCVR DRIVER.. exit\n");
|
||||
if (pddf_xcvr_ops.pre_exit) (pddf_xcvr_ops.pre_exit)();
|
||||
i2c_del_driver(&xcvr_driver);
|
||||
if (pddf_xcvr_ops.post_exit) (pddf_xcvr_ops.post_exit)();
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(xcvr_exit);
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("Driver for transceiver operations");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(xcvr_init);
|
||||
module_exit(xcvr_exit);
|
275
platform/pddf/i2c/modules/xcvr/pddf_xcvr_module.c
Normal file
275
platform/pddf/i2c/modules/xcvr/pddf_xcvr_module.c
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright 2019 Broadcom.
|
||||
* The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* A pddf kernel module to create i2C client for optics
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/kobject.h>
|
||||
#include "pddf_client_defs.h"
|
||||
#include "pddf_xcvr_defs.h"
|
||||
|
||||
static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
extern void* get_device_table(char *name);
|
||||
extern void delete_device_table(char *name);
|
||||
|
||||
XCVR_DATA xcvr_data = {0};
|
||||
|
||||
/* XCVR CLIENT DATA */
|
||||
PDDF_DATA_ATTR(dev_idx, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&xcvr_data.idx, NULL);
|
||||
|
||||
PDDF_DATA_ATTR(attr_name, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 32, (void*)&xcvr_data.xcvr_attr.aname, NULL);
|
||||
PDDF_DATA_ATTR(attr_devtype, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 8, (void*)&xcvr_data.xcvr_attr.devtype, NULL);
|
||||
PDDF_DATA_ATTR(attr_devname, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_CHAR, 8, (void*)&xcvr_data.xcvr_attr.devname, NULL);
|
||||
PDDF_DATA_ATTR(attr_devaddr, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&xcvr_data.xcvr_attr.devaddr, NULL);
|
||||
PDDF_DATA_ATTR(attr_offset, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&xcvr_data.xcvr_attr.offset, NULL);
|
||||
PDDF_DATA_ATTR(attr_mask, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&xcvr_data.xcvr_attr.mask, NULL);
|
||||
PDDF_DATA_ATTR(attr_cmpval, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_UINT32, sizeof(uint32_t), (void*)&xcvr_data.xcvr_attr.cmpval, NULL);
|
||||
PDDF_DATA_ATTR(attr_len, S_IWUSR|S_IRUGO, show_pddf_data, store_pddf_data, PDDF_INT_DEC, sizeof(int), (void*)&xcvr_data.xcvr_attr.len, NULL);
|
||||
PDDF_DATA_ATTR(attr_ops, S_IWUSR, NULL, do_attr_operation, PDDF_CHAR, 8, (void*)&xcvr_data, NULL);
|
||||
PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, (void*)&xcvr_data, (void*)&pddf_data);
|
||||
|
||||
|
||||
static struct attribute *xcvr_attributes[] = {
|
||||
&attr_dev_idx.dev_attr.attr,
|
||||
|
||||
&attr_attr_name.dev_attr.attr,
|
||||
&attr_attr_devtype.dev_attr.attr,
|
||||
&attr_attr_devname.dev_attr.attr,
|
||||
&attr_attr_devaddr.dev_attr.attr,
|
||||
&attr_attr_offset.dev_attr.attr,
|
||||
&attr_attr_mask.dev_attr.attr,
|
||||
&attr_attr_cmpval.dev_attr.attr,
|
||||
&attr_attr_len.dev_attr.attr,
|
||||
&attr_attr_ops.dev_attr.attr,
|
||||
&attr_dev_ops.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group pddf_xcvr_client_data_group = {
|
||||
.attrs = xcvr_attributes,
|
||||
};
|
||||
|
||||
|
||||
static ssize_t do_attr_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
XCVR_DATA *pdata = (XCVR_DATA *)(ptr->addr);
|
||||
|
||||
pdata->xcvr_attrs[pdata->len] = pdata->xcvr_attr;
|
||||
pdata->len++;
|
||||
memset(&pdata->xcvr_attr, 0, sizeof(pdata->xcvr_attr));
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*PDDF_DATA_ATTR(dev_ops, S_IWUSR, NULL, do_device_operation, PDDF_CHAR, 8, (void*)&pddf_attr, (void*)NULL);*/
|
||||
static ssize_t do_device_operation(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
|
||||
{
|
||||
int i = 0;
|
||||
PDDF_ATTR *ptr = (PDDF_ATTR *)da;
|
||||
XCVR_DATA *pdata = (XCVR_DATA *)(ptr->addr);
|
||||
NEW_DEV_ATTR *cdata = (NEW_DEV_ATTR *)(ptr->data);
|
||||
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_board_info board_info;
|
||||
struct i2c_client *client_ptr;
|
||||
|
||||
/* Populate the platform data for xcvr */
|
||||
if (strncmp(buf, "add", strlen(buf)-1)==0)
|
||||
{
|
||||
if (strcmp(cdata->dev_type, "pddf_xcvr")==0)
|
||||
{
|
||||
int num = pdata->len;
|
||||
XCVR_PDATA *xcvr_platform_data;
|
||||
|
||||
adapter = i2c_get_adapter(cdata->parent_bus);
|
||||
/* Allocate the xcvr_platform_data */
|
||||
xcvr_platform_data = (XCVR_PDATA *)kzalloc(sizeof(XCVR_PDATA), GFP_KERNEL);
|
||||
xcvr_platform_data->xcvr_attrs = (XCVR_ATTR *)kzalloc(num*sizeof(XCVR_ATTR), GFP_KERNEL);
|
||||
|
||||
|
||||
xcvr_platform_data->idx = pdata->idx;
|
||||
xcvr_platform_data->len = pdata->len;
|
||||
|
||||
for (i=0;i<num;i++)
|
||||
{
|
||||
xcvr_platform_data->xcvr_attrs[i] = pdata->xcvr_attrs[i];
|
||||
}
|
||||
|
||||
board_info = (struct i2c_board_info) {
|
||||
.platform_data = xcvr_platform_data,
|
||||
};
|
||||
|
||||
board_info.addr = cdata->dev_addr;
|
||||
strcpy(board_info.type, cdata->dev_type);
|
||||
|
||||
client_ptr = i2c_new_device(adapter, &board_info);
|
||||
if (client_ptr != NULL) {
|
||||
i2c_put_adapter(adapter);
|
||||
pddf_dbg(XCVR, KERN_ERR "Created a %s client: 0x%p\n", cdata->i2c_name, (void *)client_ptr);
|
||||
add_device_table(cdata->i2c_name, (void*)client_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
i2c_put_adapter(adapter);
|
||||
goto free_data;
|
||||
}
|
||||
}
|
||||
else if((strcmp(cdata->dev_type, "optoe1")==0) || (strcmp(cdata->dev_type, "optoe2")==0))
|
||||
{
|
||||
|
||||
adapter = i2c_get_adapter(cdata->parent_bus);
|
||||
board_info = (struct i2c_board_info) {
|
||||
.platform_data = (void *)NULL,
|
||||
};
|
||||
|
||||
board_info.addr = cdata->dev_addr;
|
||||
strcpy(board_info.type, cdata->dev_type);
|
||||
|
||||
client_ptr = i2c_new_device(adapter, &board_info);
|
||||
if(client_ptr != NULL) {
|
||||
i2c_put_adapter(adapter);
|
||||
pddf_dbg(XCVR, KERN_ERR "Created %s, type:%s client: 0x%p\n", cdata->i2c_name, cdata->dev_type, (void *)client_ptr);
|
||||
add_device_table(cdata->i2c_name, (void*)client_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
i2c_put_adapter(adapter);
|
||||
printk(KERN_ERR "Error creating a client %s on 0x%x, client_ptr:0x%p\n", board_info.type, board_info.addr, (void *)client_ptr);
|
||||
goto free_data;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "%s:Unknown type of device %s. Unable to create I2C client for it\n",__FUNCTION__, cdata->dev_type);
|
||||
}
|
||||
}
|
||||
else if (strncmp(buf, "delete", strlen(buf)-1)==0)
|
||||
{
|
||||
/*Get the i2c_client handle for the created client*/
|
||||
client_ptr = (struct i2c_client *)get_device_table(cdata->i2c_name);
|
||||
if (client_ptr)
|
||||
{
|
||||
pddf_dbg(XCVR, KERN_ERR "Removing %s client: 0x%p\n", cdata->i2c_name, (void *)client_ptr);
|
||||
i2c_unregister_device(client_ptr);
|
||||
delete_device_table(cdata->i2c_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
pddf_dbg(XCVR, KERN_ERR "Unable to get the client handle for %s\n", cdata->i2c_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "PDDF_ERROR: %s: Invalid value for dev_ops %s", __FUNCTION__, buf);
|
||||
}
|
||||
|
||||
goto clear_data;
|
||||
|
||||
free_data:
|
||||
if (board_info.platform_data)
|
||||
{
|
||||
XCVR_PDATA *xcvr_platform_data = board_info.platform_data;
|
||||
if (xcvr_platform_data->xcvr_attrs)
|
||||
{
|
||||
printk(KERN_ERR "%s: Unable to create i2c client. Freeing the platform subdata\n", __FUNCTION__);
|
||||
kfree(xcvr_platform_data->xcvr_attrs);
|
||||
}
|
||||
printk(KERN_ERR "%s: Unable to create i2c client. Freeing the platform data\n", __FUNCTION__);
|
||||
kfree(xcvr_platform_data);
|
||||
}
|
||||
|
||||
clear_data:
|
||||
memset(pdata, 0, sizeof(XCVR_DATA));
|
||||
/*TODO: free the data cdata->data if data is dynal=mically allocated*/
|
||||
memset(cdata, 0, sizeof(NEW_DEV_ATTR));
|
||||
return count;
|
||||
}
|
||||
|
||||
struct kobject *xcvr_kobj;
|
||||
struct kobject *i2c_kobj;
|
||||
int __init pddf_data_init(void)
|
||||
{
|
||||
struct kobject *device_kobj;
|
||||
int ret = 0;
|
||||
|
||||
pddf_dbg(XCVR, KERN_ERR "XCVR PDDF MODULE.. init\n");
|
||||
|
||||
device_kobj = get_device_i2c_kobj();
|
||||
if(!device_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
xcvr_kobj = kobject_create_and_add("xcvr", device_kobj);
|
||||
if(!xcvr_kobj)
|
||||
return -ENOMEM;
|
||||
i2c_kobj = kobject_create_and_add("i2c", xcvr_kobj);
|
||||
if(!i2c_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = sysfs_create_group(i2c_kobj, &pddf_clients_data_group);
|
||||
if (ret)
|
||||
{
|
||||
kobject_put(i2c_kobj);
|
||||
kobject_put(xcvr_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(XCVR, "CREATED SFP I2C CLIENTS CREATION SYSFS GROUP\n");
|
||||
|
||||
ret = sysfs_create_group(i2c_kobj, &pddf_xcvr_client_data_group);
|
||||
if (ret)
|
||||
{
|
||||
sysfs_remove_group(i2c_kobj, &pddf_clients_data_group);
|
||||
kobject_put(i2c_kobj);
|
||||
kobject_put(xcvr_kobj);
|
||||
return ret;
|
||||
}
|
||||
pddf_dbg(XCVR, "CREATED PDDF SFP DATA SYSFS GROUP\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit pddf_data_exit(void)
|
||||
{
|
||||
|
||||
pddf_dbg(XCVR, "XCVR PDDF MODULE.. exit\n");
|
||||
sysfs_remove_group(i2c_kobj, &pddf_xcvr_client_data_group);
|
||||
sysfs_remove_group(i2c_kobj, &pddf_clients_data_group);
|
||||
kobject_put(i2c_kobj);
|
||||
kobject_put(xcvr_kobj);
|
||||
pddf_dbg(XCVR, KERN_ERR "%s: Removed the kobjects for 'i2c' and 'xcvr'\n",__FUNCTION__);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(pddf_data_init);
|
||||
module_exit(pddf_data_exit);
|
||||
|
||||
MODULE_AUTHOR("Broadcom");
|
||||
MODULE_DESCRIPTION("sfp platform data");
|
||||
MODULE_LICENSE("GPL");
|
13
platform/pddf/i2c/service/pddf-platform-init.service
Normal file
13
platform/pddf/i2c/service/pddf-platform-init.service
Normal file
@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=PDDF module and device initialization service
|
||||
Before=pmon.service
|
||||
DefaultDependencies=no
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/pddf_util.py install
|
||||
ExecStop=/usr/local/bin/pddf_util.py clean
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
14
platform/pddf/i2c/setup.py
Executable file
14
platform/pddf/i2c/setup.py
Executable file
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from setuptools import setup
|
||||
import os
|
||||
|
||||
setup(
|
||||
name='pddf-platform',
|
||||
version='%s' % os.environ.get('PLATFORM_MODULE_VERSION', '1.0'),
|
||||
description='Module to initialize Platform',
|
||||
packages=[
|
||||
'modules',
|
||||
],
|
||||
)
|
||||
|
605
platform/pddf/i2c/utils/pddf_util.py
Executable file
605
platform/pddf/i2c/utils/pddf_util.py
Executable file
@ -0,0 +1,605 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
|
||||
"""
|
||||
Usage: %(scriptName)s [options] command object
|
||||
|
||||
options:
|
||||
-h | --help : this help message
|
||||
-d | --debug : run with debug mode
|
||||
-f | --force : ignore error during installation or clean
|
||||
command:
|
||||
install : install drivers and generate related sysfs nodes
|
||||
clean : uninstall drivers and remove related sysfs nodes
|
||||
switch-pddf : switch to pddf mode, installing pddf drivers and generating sysfs nodes
|
||||
switch-nonpddf : switch to per platform, non-pddf mode
|
||||
"""
|
||||
|
||||
import commands
|
||||
import logging
|
||||
import getopt
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import pddfparse
|
||||
|
||||
PLATFORM_ROOT_PATH = '/usr/share/sonic/device'
|
||||
SONIC_CFGGEN_PATH = '/usr/local/bin/sonic-cfggen'
|
||||
HWSKU_KEY = 'DEVICE_METADATA.localhost.hwsku'
|
||||
PLATFORM_KEY = 'DEVICE_METADATA.localhost.platform'
|
||||
|
||||
PROJECT_NAME = 'PDDF'
|
||||
version = '1.1'
|
||||
verbose = False
|
||||
DEBUG = False
|
||||
args = []
|
||||
ALL_DEVICE = {}
|
||||
FORCE = 0
|
||||
kos = []
|
||||
perm_kos = []
|
||||
devs = []
|
||||
|
||||
# Instantiate the class pddf_obj
|
||||
try:
|
||||
pddf_obj = pddfparse.PddfParse()
|
||||
except Exception as e:
|
||||
print "%s" % str(e)
|
||||
sys.exit()
|
||||
|
||||
|
||||
|
||||
if DEBUG == True:
|
||||
print sys.argv[0]
|
||||
print 'ARGV :', sys.argv[1:]
|
||||
|
||||
def main():
|
||||
global DEBUG
|
||||
global args
|
||||
global FORCE
|
||||
global kos
|
||||
|
||||
if len(sys.argv)<2:
|
||||
show_help()
|
||||
|
||||
options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help',
|
||||
'debug',
|
||||
'force',
|
||||
])
|
||||
if DEBUG == True:
|
||||
print options
|
||||
print args
|
||||
print len(sys.argv)
|
||||
|
||||
# generate the KOS list from pddf device JSON file
|
||||
if 'std_perm_kos' in pddf_obj.data['PLATFORM'].keys():
|
||||
kos.extend(pddf_obj.data['PLATFORM']['std_perm_kos'])
|
||||
perm_kos.extend(pddf_obj.data['PLATFORM']['std_perm_kos'])
|
||||
kos.extend(pddf_obj.data['PLATFORM']['std_kos'])
|
||||
kos.extend(pddf_obj.data['PLATFORM']['pddf_kos'])
|
||||
|
||||
kos = ['modprobe '+i for i in kos]
|
||||
|
||||
if 'custom_kos' in pddf_obj.data['PLATFORM']:
|
||||
custom_kos = pddf_obj.data['PLATFORM']['custom_kos']
|
||||
kos.extend(['modprobe -f '+i for i in custom_kos])
|
||||
|
||||
for opt, arg in options:
|
||||
if opt in ('-h', '--help'):
|
||||
show_help()
|
||||
elif opt in ('-d', '--debug'):
|
||||
DEBUG = True
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
elif opt in ('-f', '--force'):
|
||||
FORCE = 1
|
||||
else:
|
||||
logging.info('no option')
|
||||
for arg in args:
|
||||
if arg == 'install':
|
||||
do_install()
|
||||
elif arg == 'clean':
|
||||
do_uninstall()
|
||||
elif arg == 'switch-pddf':
|
||||
do_switch_pddf()
|
||||
elif arg == 'switch-nonpddf':
|
||||
do_switch_nonpddf()
|
||||
else:
|
||||
show_help()
|
||||
|
||||
return 0
|
||||
|
||||
def show_help():
|
||||
print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]}
|
||||
sys.exit(0)
|
||||
|
||||
def my_log(txt):
|
||||
if DEBUG == True:
|
||||
print "[PDDF]"+txt
|
||||
return
|
||||
|
||||
def log_os_system(cmd, show):
|
||||
logging.info('Run :'+cmd)
|
||||
status, output = commands.getstatusoutput(cmd)
|
||||
my_log (cmd +"with result:" + str(status))
|
||||
my_log (" output:"+output)
|
||||
if status:
|
||||
logging.info('Failed :'+cmd)
|
||||
if show:
|
||||
print('Failed :'+cmd)
|
||||
return status, output
|
||||
|
||||
def driver_check():
|
||||
ret, lsmod = log_os_system("lsmod| grep pddf", 0)
|
||||
if ret:
|
||||
return False
|
||||
logging.info('mods:'+lsmod)
|
||||
if len(lsmod) ==0:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
# Returns platform and HW SKU
|
||||
def get_platform_and_hwsku():
|
||||
try:
|
||||
proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-H', '-v', PLATFORM_KEY],
|
||||
stdout=subprocess.PIPE,
|
||||
shell=False,
|
||||
stderr=subprocess.STDOUT)
|
||||
stdout = proc.communicate()[0]
|
||||
proc.wait()
|
||||
platform = stdout.rstrip('\n')
|
||||
|
||||
proc = subprocess.Popen([SONIC_CFGGEN_PATH, '-d', '-v', HWSKU_KEY],
|
||||
stdout=subprocess.PIPE,
|
||||
shell=False,
|
||||
stderr=subprocess.STDOUT)
|
||||
stdout = proc.communicate()[0]
|
||||
proc.wait()
|
||||
hwsku = stdout.rstrip('\n')
|
||||
except OSError, e:
|
||||
raise OSError("Cannot detect platform")
|
||||
|
||||
return (platform, hwsku)
|
||||
|
||||
def get_path_to_device():
|
||||
# Get platform and hwsku
|
||||
(platform, hwsku) = get_platform_and_hwsku()
|
||||
|
||||
# Load platform module from source
|
||||
platform_path = "/".join([PLATFORM_ROOT_PATH, platform])
|
||||
|
||||
return platform_path
|
||||
|
||||
def get_path_to_pddf_plugin():
|
||||
pddf_path = "/".join([PLATFORM_ROOT_PATH, "pddf/plugins"])
|
||||
return pddf_path
|
||||
|
||||
def config_pddf_utils():
|
||||
device_path = get_path_to_device()
|
||||
pddf_path = get_path_to_pddf_plugin()
|
||||
|
||||
# ##########################################################################
|
||||
SONIC_PLATFORM_BSP_WHL_PKG = "/".join([device_path, 'sonic_platform-1.0-py2-none-any.whl'])
|
||||
SONIC_PLATFORM_PDDF_WHL_PKG = "/".join([device_path, 'pddf', 'sonic_platform-1.0-py2-none-any.whl'])
|
||||
SONIC_PLATFORM_BSP_WHL_PKG_BK = "/".join([device_path, 'sonic_platform-1.0-py2-none-any.whl.orig'])
|
||||
status, output = log_os_system("pip show sonic-platform > /dev/null 2>&1", 1)
|
||||
if status:
|
||||
if os.path.exists(SONIC_PLATFORM_PDDF_WHL_PKG):
|
||||
# Platform API 2.0 is supported
|
||||
if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG):
|
||||
# bsp whl pkg is present but not installed on host <special case>
|
||||
if not os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_BK):
|
||||
log_os_system('mv '+SONIC_PLATFORM_BSP_WHL_PKG+' '+SONIC_PLATFORM_BSP_WHL_PKG_BK, 1)
|
||||
# PDDF whl package exist ... this must be the whl package created from
|
||||
# PDDF 2.0 ref API classes and some changes on top of it ... install it
|
||||
shutil.copy(SONIC_PLATFORM_PDDF_WHL_PKG, SONIC_PLATFORM_BSP_WHL_PKG)
|
||||
print "Attemting to install the PDDF sonic_platform wheel package ..."
|
||||
status, output = log_os_system("pip install "+ SONIC_PLATFORM_BSP_WHL_PKG, 1)
|
||||
if status:
|
||||
print "Error: Failed to install {}".format(SONIC_PLATFORM_BSP_WHL_PKG)
|
||||
return status
|
||||
else:
|
||||
print "Successfully installed {} package".format(SONIC_PLATFORM_BSP_WHL_PKG)
|
||||
else:
|
||||
# PDDF with platform APIs 1.5 must be supported
|
||||
device_plugin_path = "/".join([device_path, "plugins"])
|
||||
backup_path = "/".join([device_plugin_path, "orig"])
|
||||
print "Loading PDDF generic plugins (1.0)"
|
||||
if os.path.exists(backup_path) is False:
|
||||
os.mkdir(backup_path)
|
||||
log_os_system("mv "+device_plugin_path+"/*.*"+" "+backup_path, 0)
|
||||
|
||||
for item in os.listdir(pddf_path):
|
||||
shutil.copy(pddf_path+"/"+item, device_plugin_path+"/"+item)
|
||||
|
||||
shutil.copy('/usr/local/bin/pddfparse.py', device_plugin_path+"/pddfparse.py")
|
||||
|
||||
else:
|
||||
# sonic_platform whl pkg is installed 2 possibilities, 1) bsp 2.0 classes
|
||||
# are installed, 2) system rebooted and either pddf/bsp 2.0 classes are already installed
|
||||
if os.path.exists(SONIC_PLATFORM_PDDF_WHL_PKG):
|
||||
if not os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_BK):
|
||||
# bsp 2.0 classes are installed. Take a backup and copy pddf 2.0 whl pkg
|
||||
log_os_system('mv '+SONIC_PLATFORM_BSP_WHL_PKG+' '+SONIC_PLATFORM_BSP_WHL_PKG_BK, 1)
|
||||
shutil.copy(SONIC_PLATFORM_PDDF_WHL_PKG, SONIC_PLATFORM_BSP_WHL_PKG)
|
||||
# uninstall the existing bsp whl pkg
|
||||
status, output = log_os_system("pip uninstall sonic-platform -y &> /dev/null", 1)
|
||||
if status:
|
||||
print "Error: Unable to uninstall BSP sonic-platform whl package"
|
||||
return status
|
||||
print "Attemting to install the PDDF sonic_platform wheel package ..."
|
||||
status, output = log_os_system("pip install "+ SONIC_PLATFORM_BSP_WHL_PKG, 1)
|
||||
if status:
|
||||
print "Error: Failed to install {}".format(SONIC_PLATFORM_BSP_WHL_PKG)
|
||||
return status
|
||||
else:
|
||||
print "Successfully installed {} package".format(SONIC_PLATFORM_BSP_WHL_PKG)
|
||||
else:
|
||||
# system rebooted in pddf mode
|
||||
print "System rebooted in PDDF mode, hence keeping the PDDF 2.0 classes"
|
||||
else:
|
||||
# pddf whl package doesnt exist
|
||||
print "Error: PDDF 2.0 classes doesnt exist. PDDF mode can not be enabled"
|
||||
sys.exit(1)
|
||||
|
||||
# ##########################################################################
|
||||
# Take a backup of orig fancontrol
|
||||
if os.path.exists(device_path+"/fancontrol"):
|
||||
log_os_system("mv "+device_path+"/fancontrol"+" "+device_path+"/fancontrol.bak", 0)
|
||||
|
||||
# Create a link to fancontrol of PDDF
|
||||
if os.path.exists(device_path+"/pddf/fancontrol") and not os.path.exists(device_path+"/fancontrol"):
|
||||
shutil.copy(device_path+"/pddf/fancontrol",device_path+"/fancontrol")
|
||||
|
||||
# BMC support
|
||||
f_sensors="/usr/bin/sensors"
|
||||
f_sensors_org="/usr/bin/sensors.org"
|
||||
f_pddf_sensors="/usr/local/bin/pddf_sensors"
|
||||
if os.path.exists(f_pddf_sensors) is True:
|
||||
if os.path.exists(f_sensors_org) is False:
|
||||
shutil.copy(f_sensors, f_sensors_org)
|
||||
shutil.copy(f_pddf_sensors, f_sensors)
|
||||
|
||||
|
||||
return 0
|
||||
|
||||
def cleanup_pddf_utils():
|
||||
device_path = get_path_to_device()
|
||||
SONIC_PLATFORM_BSP_WHL_PKG = "/".join([device_path, 'sonic_platform-1.0-py2-none-any.whl'])
|
||||
SONIC_PLATFORM_PDDF_WHL_PKG = "/".join([device_path, 'pddf', 'sonic_platform-1.0-py2-none-any.whl'])
|
||||
SONIC_PLATFORM_BSP_WHL_PKG_BK = "/".join([device_path, 'sonic_platform-1.0-py2-none-any.whl.orig'])
|
||||
# ##########################################################################
|
||||
status, output = log_os_system("pip show sonic-platform > /dev/null 2>&1", 1)
|
||||
if status:
|
||||
# PDDF Platform API 2.0 is not supported but system is in PDDF mode, hence PDDF 1.0 plugins are present
|
||||
device_plugin_path = "/".join([device_path, "plugins"])
|
||||
backup_path = "/".join([device_plugin_path, "orig"])
|
||||
if os.path.exists(backup_path) is True:
|
||||
for item in os.listdir(device_plugin_path):
|
||||
if os.path.isdir(device_plugin_path+"/"+item) is False:
|
||||
os.remove(device_plugin_path+"/"+item)
|
||||
|
||||
log_os_system("mv "+backup_path+"/*"+" "+device_plugin_path, 1)
|
||||
os.rmdir(backup_path)
|
||||
else:
|
||||
print "\nERR: Unable to locate original device files...\n"
|
||||
|
||||
else:
|
||||
# PDDF 2.0 apis are supported and PDDF whl package is installed
|
||||
if os.path.exists(SONIC_PLATFORM_PDDF_WHL_PKG):
|
||||
if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG_BK):
|
||||
# platform is 2.0 compliant and original bsp 2.0 whl package exist
|
||||
log_os_system('mv '+SONIC_PLATFORM_BSP_WHL_PKG_BK+' '+SONIC_PLATFORM_BSP_WHL_PKG, 1)
|
||||
status, output = log_os_system("pip uninstall sonic-platform -y &> /dev/null", 1)
|
||||
if status:
|
||||
print "Error: Unable to uninstall PDDF sonic-platform whl package"
|
||||
return status
|
||||
print "Attemting to install the BSP sonic_platform wheel package ..."
|
||||
status, output = log_os_system("pip install "+ SONIC_PLATFORM_BSP_WHL_PKG, 1)
|
||||
if status:
|
||||
print "Error: Failed to install {}".format(SONIC_PLATFORM_BSP_WHL_PKG)
|
||||
return status
|
||||
else:
|
||||
print "Successfully installed {} package".format(SONIC_PLATFORM_BSP_WHL_PKG)
|
||||
else:
|
||||
# platform doesnt support 2.0 APIs but PDDF is 2.0 based
|
||||
# remove and uninstall the PDDF whl package
|
||||
if os.path.exists(SONIC_PLATFORM_BSP_WHL_PKG):
|
||||
os.remove(SONIC_PLATFORM_BSP_WHL_PKG)
|
||||
status, output = log_os_system("pip uninstall sonic-platform -y &> /dev/null", 1)
|
||||
if status:
|
||||
print "Error: Unable to uninstall PDDF sonic-platform whl package"
|
||||
return status
|
||||
else:
|
||||
# something seriously wrong. System is in PDDF mode but pddf whl pkg is not present
|
||||
print "Error: Fatal error as the system is in PDDF mode but the pddf .whl original is not present"
|
||||
# ################################################################################################################
|
||||
|
||||
if os.path.exists(device_path+"/fancontrol"):
|
||||
os.remove(device_path+"/fancontrol")
|
||||
|
||||
if os.path.exists(device_path+"/fancontrol.bak"):
|
||||
log_os_system("mv "+device_path+"/fancontrol.bak"+" "+device_path+"/fancontrol", 0)
|
||||
|
||||
# BMC support
|
||||
f_sensors="/usr/bin/sensors"
|
||||
f_sensors_org="/usr/bin/sensors.org"
|
||||
if os.path.exists(f_sensors_org) is True:
|
||||
shutil.copy(f_sensors_org, f_sensors)
|
||||
|
||||
return 0
|
||||
|
||||
def create_pddf_log_files():
|
||||
if not os.path.exists('/var/log/pddf'):
|
||||
log_os_system("sudo mkdir /var/log/pddf", 1)
|
||||
|
||||
log_os_system("sudo touch /var/log/pddf/led.txt", 1)
|
||||
log_os_system("sudo touch /var/log/pddf/psu.txt", 1)
|
||||
log_os_system("sudo touch /var/log/pddf/fan.txt", 1)
|
||||
log_os_system("sudo touch /var/log/pddf/xcvr.txt", 1)
|
||||
log_os_system("sudo touch /var/log/pddf/sysstatus.txt", 1)
|
||||
log_os_system("sudo touch /var/log/pddf/cpld.txt", 1)
|
||||
log_os_system("sudo touch /var/log/pddf/cpldmux.txt", 1)
|
||||
log_os_system("sudo touch /var/log/pddf/client.txt", 1)
|
||||
log_os_system("sudo touch /var/log/pddf/mux.txt", 1)
|
||||
|
||||
def driver_install():
|
||||
global FORCE
|
||||
|
||||
# check for pre_driver_install script
|
||||
if os.path.exists('/usr/local/bin/pddf_pre_driver_install.sh'):
|
||||
status, output = log_os_system('/usr/local/bin/pddf_pre_driver_install.sh', 1)
|
||||
if status:
|
||||
print "Error: pddf_pre_driver_install script failed with error %d"%status
|
||||
return status
|
||||
|
||||
log_os_system("depmod", 1)
|
||||
for i in range(0,len(kos)):
|
||||
status, output = log_os_system(kos[i], 1)
|
||||
if status:
|
||||
print "driver_install() failed with error %d"%status
|
||||
if FORCE == 0:
|
||||
return status
|
||||
|
||||
output = config_pddf_utils()
|
||||
if output:
|
||||
print "config_pddf_utils() failed with error %d"%output
|
||||
# check for post_driver_install script
|
||||
if os.path.exists('/usr/local/bin/pddf_post_driver_install.sh'):
|
||||
status, output = log_os_system('/usr/local/bin/pddf_post_driver_install.sh', 1)
|
||||
if status:
|
||||
print "Error: pddf_post_driver_install script failed with error %d"%status
|
||||
return status
|
||||
|
||||
|
||||
return 0
|
||||
|
||||
def driver_uninstall():
|
||||
global FORCE
|
||||
|
||||
status = cleanup_pddf_utils()
|
||||
if status:
|
||||
print "cleanup_pddf_utils() failed with error %d"%status
|
||||
|
||||
for i in range(0,len(kos)):
|
||||
# if it is in perm_kos, do not remove
|
||||
if (kos[-(i+1)].split())[-1] in perm_kos or 'i2c-i801' in kos[-(i+1)]:
|
||||
continue
|
||||
|
||||
rm = kos[-(i+1)].replace("modprobe", "modprobe -rq")
|
||||
rm = rm.replace("insmod", "rmmod")
|
||||
status, output = log_os_system(rm, 1)
|
||||
if status:
|
||||
print "driver_uninstall() failed with error %d"%status
|
||||
if FORCE == 0:
|
||||
return status
|
||||
return 0
|
||||
|
||||
def device_install():
|
||||
global FORCE
|
||||
|
||||
# check for pre_device_creation script
|
||||
if os.path.exists('/usr/local/bin/pddf_pre_device_create.sh'):
|
||||
status, output = log_os_system('/usr/local/bin/pddf_pre_device_create.sh', 1)
|
||||
if status:
|
||||
print "Error: pddf_pre_device_create script failed with error %d"%status
|
||||
return status
|
||||
|
||||
# trigger the pddf_obj script for FAN, PSU, CPLD, MUX, etc
|
||||
status = pddf_obj.create_pddf_devices()
|
||||
if status:
|
||||
print "Error: create_pddf_devices() failed with error %d"%status
|
||||
if FORCE == 0:
|
||||
return status
|
||||
|
||||
# check for post_device_create script
|
||||
if os.path.exists('/usr/local/bin/pddf_post_device_create.sh'):
|
||||
status, output = log_os_system('/usr/local/bin/pddf_post_device_create.sh', 1)
|
||||
if status:
|
||||
print "Error: pddf_post_device_create script failed with error %d"%status
|
||||
return status
|
||||
|
||||
return
|
||||
|
||||
def device_uninstall():
|
||||
global FORCE
|
||||
# Trigger the paloparse script for deletion of FAN, PSU, OPTICS, CPLD clients
|
||||
status = pddf_obj.delete_pddf_devices()
|
||||
if status:
|
||||
print "Error: delete_pddf_devices() failed with error %d"%status
|
||||
if FORCE == 0:
|
||||
return status
|
||||
return
|
||||
|
||||
def do_install():
|
||||
print "Checking system...."
|
||||
if not os.path.exists('/usr/share/sonic/platform/pddf_support'):
|
||||
print PROJECT_NAME.upper() +" mode is not enabled"
|
||||
return
|
||||
|
||||
if driver_check()== False :
|
||||
print PROJECT_NAME.upper() +" has no PDDF driver installed...."
|
||||
create_pddf_log_files()
|
||||
print "Installing ..."
|
||||
status = driver_install()
|
||||
if status:
|
||||
return status
|
||||
else:
|
||||
print PROJECT_NAME.upper() +" drivers detected...."
|
||||
|
||||
print "Creating devices ..."
|
||||
status = device_install()
|
||||
if status:
|
||||
return status
|
||||
|
||||
return
|
||||
|
||||
def do_uninstall():
|
||||
print "Checking system...."
|
||||
if not os.path.exists('/usr/share/sonic/platform/pddf_support'):
|
||||
print PROJECT_NAME.upper() +" mode is not enabled"
|
||||
return
|
||||
|
||||
|
||||
if os.path.exists('/var/log/pddf'):
|
||||
print "Remove pddf log files....."
|
||||
log_os_system("sudo rm -rf /var/log/pddf", 1)
|
||||
|
||||
print "Remove all the devices..."
|
||||
status = device_uninstall()
|
||||
if status:
|
||||
return status
|
||||
|
||||
|
||||
if driver_check()== False :
|
||||
print PROJECT_NAME.upper() +" has no PDDF driver installed...."
|
||||
else:
|
||||
print "Removing installed driver...."
|
||||
status = driver_uninstall()
|
||||
if status:
|
||||
if FORCE == 0:
|
||||
return status
|
||||
return
|
||||
|
||||
def do_switch_pddf():
|
||||
try:
|
||||
import pddf_switch_svc
|
||||
except ImportError:
|
||||
print "Unable to find pddf_switch_svc.py. PDDF might not be supported on this platform"
|
||||
sys.exit()
|
||||
print "Check the pddf support..."
|
||||
status = pddf_switch_svc.check_pddf_support()
|
||||
if not status:
|
||||
print "PDDF is not supported on this platform"
|
||||
return status
|
||||
|
||||
|
||||
print "Checking system...."
|
||||
if os.path.exists('/usr/share/sonic/platform/pddf_support'):
|
||||
print PROJECT_NAME.upper() +" system is already in pddf mode...."
|
||||
else:
|
||||
print "Check if the native sonic-platform whl package is installed in the pmon docker"
|
||||
status, output = log_os_system("docker exec -it pmon pip show sonic-platform", 1)
|
||||
if not status:
|
||||
# Need to remove this whl module
|
||||
status, output = log_os_system("docker exec -it pmon pip uninstall sonic-platform -y", 1)
|
||||
if not status:
|
||||
print "Successfully uninstalled the native sonic-platform whl pkg from pmon container"
|
||||
else:
|
||||
print "Error: Unable to uninstall the sonic-platform whl pkg from pmon container.\
|
||||
Do it manually before moving to nonpddf mode"
|
||||
return status
|
||||
print "Stopping the pmon service ..."
|
||||
status, output = log_os_system("systemctl stop pmon.service", 1)
|
||||
if status:
|
||||
print "Pmon stop failed"
|
||||
if FORCE==0:
|
||||
return status
|
||||
|
||||
print "Stopping the platform services.."
|
||||
status = pddf_switch_svc.stop_platform_svc()
|
||||
if not status:
|
||||
if FORCE==0:
|
||||
return status
|
||||
|
||||
print "Creating the pddf_support file..."
|
||||
if os.path.exists('/usr/share/sonic/platform'):
|
||||
log_os_system("touch /usr/share/sonic/platform/pddf_support", 1)
|
||||
else:
|
||||
print "/usr/share/sonic/platform path doesn't exist. Unable to set pddf mode"
|
||||
return -1
|
||||
|
||||
print "Starting the PDDF platform service..."
|
||||
status = pddf_switch_svc.start_platform_pddf()
|
||||
if not status:
|
||||
if FORCE==0:
|
||||
return status
|
||||
|
||||
print "Restart the pmon service ..."
|
||||
status, output = log_os_system("systemctl start pmon.service", 1)
|
||||
if status:
|
||||
print "Pmon restart failed"
|
||||
if FORCE==0:
|
||||
return status
|
||||
|
||||
return
|
||||
|
||||
def do_switch_nonpddf():
|
||||
try:
|
||||
import pddf_switch_svc
|
||||
except ImportError:
|
||||
print "Unable to find pddf_switch_svc.py. PDDF might not be supported on this platform"
|
||||
sys.exit()
|
||||
print "Checking system...."
|
||||
if not os.path.exists('/usr/share/sonic/platform/pddf_support'):
|
||||
print PROJECT_NAME.upper() +" system is already in non-pddf mode...."
|
||||
else:
|
||||
print "Check if the sonic-platform whl package is installed in the pmon docker"
|
||||
status, output = log_os_system("docker exec -it pmon pip show sonic-platform", 1)
|
||||
if not status:
|
||||
# Need to remove this whl module
|
||||
status, output = log_os_system("docker exec -it pmon pip uninstall sonic-platform -y", 1)
|
||||
if not status:
|
||||
print "Successfully uninstalled the sonic-platform whl pkg from pmon container"
|
||||
else:
|
||||
print "Error: Unable to uninstall the sonic-platform whl pkg from pmon container.\
|
||||
Do it manually before moving to nonpddf mode"
|
||||
return status
|
||||
print "Stopping the pmon service ..."
|
||||
status, output = log_os_system("systemctl stop pmon.service", 1)
|
||||
if status:
|
||||
print "Stopping pmon service failed"
|
||||
if FORCE==0:
|
||||
return status
|
||||
|
||||
print "Stopping the PDDF platform service..."
|
||||
status = pddf_switch_svc.stop_platform_pddf()
|
||||
if not status:
|
||||
if FORCE==0:
|
||||
return status
|
||||
|
||||
print "Removing the pddf_support file..."
|
||||
if os.path.exists('/usr/share/sonic/platform'):
|
||||
log_os_system("rm -f /usr/share/sonic/platform/pddf_support", 1)
|
||||
else:
|
||||
print "/usr/share/sonic/platform path doesnt exist. Unable to set non-pddf mode"
|
||||
return -1
|
||||
|
||||
print "Starting the platform services..."
|
||||
status = pddf_switch_svc.start_platform_svc()
|
||||
if not status:
|
||||
if FORCE==0:
|
||||
return status
|
||||
|
||||
print "Restart the pmon service ..."
|
||||
status, output = log_os_system("systemctl start pmon.service", 1)
|
||||
if status:
|
||||
print "Restarting pmon service failed"
|
||||
if FORCE==0:
|
||||
return status
|
||||
|
||||
return
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
1949
platform/pddf/i2c/utils/pddfparse.py
Executable file
1949
platform/pddf/i2c/utils/pddfparse.py
Executable file
File diff suppressed because it is too large
Load Diff
67
platform/pddf/i2c/utils/schema/CPLD.schema
Normal file
67
platform/pddf/i2c/utils/schema/CPLD.schema
Normal file
@ -0,0 +1,67 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"CPLD": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_parent": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type",
|
||||
"device_name",
|
||||
"device_parent"
|
||||
]
|
||||
},
|
||||
"i2c": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"topo_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parent_bus": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev_addr": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev_type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"parent_bus",
|
||||
"dev_addr",
|
||||
"dev_type"
|
||||
]
|
||||
},
|
||||
"dev_attr": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"topo_info"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"i2c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"CPLD"
|
||||
]
|
||||
}
|
80
platform/pddf/i2c/utils/schema/CPU.schema
Normal file
80
platform/pddf/i2c/utils/schema/CPU.schema
Normal file
@ -0,0 +1,80 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"CPU": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_parent": {
|
||||
"type": "null"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type",
|
||||
"device_name",
|
||||
"device_parent"
|
||||
]
|
||||
},
|
||||
"i2c": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"CONTROLLERS": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_name",
|
||||
"dev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_name",
|
||||
"dev"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"CONTROLLERS"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"i2c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"CPU"
|
||||
]
|
||||
}
|
93
platform/pddf/i2c/utils/schema/EEPROM.schema
Normal file
93
platform/pddf/i2c/utils/schema/EEPROM.schema
Normal file
@ -0,0 +1,93 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"EEPROM": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_parent": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type",
|
||||
"device_name",
|
||||
"device_parent"
|
||||
]
|
||||
},
|
||||
"i2c": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"topo_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parent_bus": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev_addr": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev_type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"parent_bus",
|
||||
"dev_addr",
|
||||
"dev_type"
|
||||
]
|
||||
},
|
||||
"dev_attr": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"access_mode": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"access_mode"
|
||||
]
|
||||
},
|
||||
"attr_list": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"topo_info",
|
||||
"dev_attr",
|
||||
"attr_list"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"i2c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"EEPROM"
|
||||
]
|
||||
}
|
113
platform/pddf/i2c/utils/schema/FAN.schema
Normal file
113
platform/pddf/i2c/utils/schema/FAN.schema
Normal file
@ -0,0 +1,113 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"FAN": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_parent": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type",
|
||||
"device_name",
|
||||
"device_parent"
|
||||
]
|
||||
},
|
||||
"i2c": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"topo_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parent_bus": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev_addr": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev_type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"parent_bus",
|
||||
"dev_addr",
|
||||
"dev_type"
|
||||
]
|
||||
},
|
||||
"dev_attr": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"num_fantrays": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"num_fantrays"
|
||||
]
|
||||
},
|
||||
"attr_list": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_devtype": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_offset": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_mask": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_cmpval": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_len": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"attr_devtype",
|
||||
"attr_offset",
|
||||
"attr_mask",
|
||||
"attr_cmpval",
|
||||
"attr_len"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"topo_info",
|
||||
"dev_attr",
|
||||
"attr_list"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"i2c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"FAN"
|
||||
]
|
||||
}
|
69
platform/pddf/i2c/utils/schema/FAN_BMC.schema
Normal file
69
platform/pddf/i2c/utils/schema/FAN_BMC.schema
Normal file
@ -0,0 +1,69 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"FAN": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type"
|
||||
]
|
||||
},
|
||||
"bmc": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ipmitool": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_list": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bmc_cmd": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bmc_cmd",
|
||||
"raw"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_list"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"ipmitool"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"bmc"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"FAN"
|
||||
]
|
||||
}
|
120
platform/pddf/i2c/utils/schema/LED.schema
Normal file
120
platform/pddf/i2c/utils/schema/LED.schema
Normal file
@ -0,0 +1,120 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"LED": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type",
|
||||
"device_name"
|
||||
]
|
||||
},
|
||||
"dev_attr": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"index": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"index"
|
||||
]
|
||||
},
|
||||
"i2c": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_list": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bits": {
|
||||
"type": "string"
|
||||
},
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
},
|
||||
"swpld_addr": {
|
||||
"type": "string"
|
||||
},
|
||||
"swpld_addr_offset": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bits",
|
||||
"color",
|
||||
"value",
|
||||
"swpld_addr",
|
||||
"swpld_addr_offset"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bits": {
|
||||
"type": "string"
|
||||
},
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
},
|
||||
"swpld_addr": {
|
||||
"type": "string"
|
||||
},
|
||||
"swpld_addr_offset": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bits",
|
||||
"color",
|
||||
"value",
|
||||
"swpld_addr",
|
||||
"swpld_addr_offset"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_list"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"dev_attr",
|
||||
"i2c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"LED"
|
||||
]
|
||||
}
|
97
platform/pddf/i2c/utils/schema/MUX.schema
Normal file
97
platform/pddf/i2c/utils/schema/MUX.schema
Normal file
@ -0,0 +1,97 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"MUX": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_parent": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type",
|
||||
"device_name",
|
||||
"device_parent"
|
||||
]
|
||||
},
|
||||
"i2c": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"topo_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parent_bus": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev_addr": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev_type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"parent_bus",
|
||||
"dev_addr",
|
||||
"dev_type"
|
||||
]
|
||||
},
|
||||
"dev_attr": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"virt_bus": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"virt_bus"
|
||||
]
|
||||
},
|
||||
"channel": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"chn": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"chn",
|
||||
"dev"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"topo_info",
|
||||
"dev_attr",
|
||||
"channel"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"i2c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"MUX"
|
||||
]
|
||||
}
|
109
platform/pddf/i2c/utils/schema/PSU-PMBUS.schema
Normal file
109
platform/pddf/i2c/utils/schema/PSU-PMBUS.schema
Normal file
@ -0,0 +1,109 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"PSU-PMBUS": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_parent": {
|
||||
"type": "string"
|
||||
},
|
||||
"virt_parent": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type",
|
||||
"device_name",
|
||||
"device_parent",
|
||||
"virt_parent"
|
||||
]
|
||||
},
|
||||
"i2c": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"topo_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parent_bus": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev_addr": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev_type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"parent_bus",
|
||||
"dev_addr",
|
||||
"dev_type"
|
||||
]
|
||||
},
|
||||
"attr_list": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_devaddr": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_devtype": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_offset": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_mask": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_cmpval": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_len": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"attr_devaddr",
|
||||
"attr_devtype",
|
||||
"attr_offset",
|
||||
"attr_mask",
|
||||
"attr_cmpval",
|
||||
"attr_len"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"topo_info",
|
||||
"attr_list"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"i2c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"PSU-PMBUS"
|
||||
]
|
||||
}
|
81
platform/pddf/i2c/utils/schema/PSU.schema
Normal file
81
platform/pddf/i2c/utils/schema/PSU.schema
Normal file
@ -0,0 +1,81 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"PSU": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_parent": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type",
|
||||
"device_name",
|
||||
"device_parent"
|
||||
]
|
||||
},
|
||||
"dev_attr": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_idx": {
|
||||
"type": "string"
|
||||
},
|
||||
"num_psu_fans": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_idx",
|
||||
"num_psu_fans"
|
||||
]
|
||||
},
|
||||
"i2c": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"interface": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"itf": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"itf",
|
||||
"dev"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"interface"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"dev_attr",
|
||||
"i2c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"PSU"
|
||||
]
|
||||
}
|
336
platform/pddf/i2c/utils/schema/PSU_BMC.schema
Normal file
336
platform/pddf/i2c/utils/schema/PSU_BMC.schema
Normal file
@ -0,0 +1,336 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"PSU": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type"
|
||||
]
|
||||
},
|
||||
"dev_attr": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_idx": {
|
||||
"type": "string"
|
||||
},
|
||||
"num_psu_fans": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_idx",
|
||||
"num_psu_fans"
|
||||
]
|
||||
},
|
||||
"bmc": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ipmitool": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_list": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bmc_cmd": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_pos": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bmc_cmd",
|
||||
"raw",
|
||||
"field_name",
|
||||
"field_pos"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bmc_cmd": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"mask": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bmc_cmd",
|
||||
"raw",
|
||||
"type",
|
||||
"mask"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bmc_cmd": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bmc_cmd",
|
||||
"raw",
|
||||
"type"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bmc_cmd": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bmc_cmd",
|
||||
"raw",
|
||||
"type"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bmc_cmd": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bmc_cmd",
|
||||
"raw",
|
||||
"type"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bmc_cmd": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bmc_cmd",
|
||||
"raw",
|
||||
"type"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bmc_cmd": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_pos": {
|
||||
"type": "string"
|
||||
},
|
||||
"mult": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bmc_cmd",
|
||||
"raw",
|
||||
"field_name",
|
||||
"field_pos",
|
||||
"mult"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bmc_cmd": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_pos": {
|
||||
"type": "string"
|
||||
},
|
||||
"mult": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bmc_cmd",
|
||||
"raw",
|
||||
"field_name",
|
||||
"field_pos",
|
||||
"mult"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bmc_cmd": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_pos": {
|
||||
"type": "string"
|
||||
},
|
||||
"mult": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bmc_cmd",
|
||||
"raw",
|
||||
"field_name",
|
||||
"field_pos",
|
||||
"mult"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bmc_cmd": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_pos": {
|
||||
"type": "string"
|
||||
},
|
||||
"mult": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bmc_cmd",
|
||||
"raw",
|
||||
"field_name",
|
||||
"field_pos",
|
||||
"mult"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_list"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"ipmitool"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"dev_attr",
|
||||
"bmc"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"PSU"
|
||||
]
|
||||
}
|
92
platform/pddf/i2c/utils/schema/QSFP.schema
Normal file
92
platform/pddf/i2c/utils/schema/QSFP.schema
Normal file
@ -0,0 +1,92 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"QSFP": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_parent": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type",
|
||||
"device_name",
|
||||
"device_parent"
|
||||
]
|
||||
},
|
||||
"dev_attr": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_idx": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_idx"
|
||||
]
|
||||
},
|
||||
"i2c": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"interface": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"itf": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"itf",
|
||||
"dev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"itf": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"itf",
|
||||
"dev"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"interface"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"dev_attr",
|
||||
"i2c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"QSFP"
|
||||
]
|
||||
}
|
128
platform/pddf/i2c/utils/schema/SMBUS.schema
Normal file
128
platform/pddf/i2c/utils/schema/SMBUS.schema
Normal file
@ -0,0 +1,128 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"SMBUS": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_parent": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type",
|
||||
"device_name",
|
||||
"device_parent"
|
||||
]
|
||||
},
|
||||
"i2c": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"topo_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_addr": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_addr"
|
||||
]
|
||||
},
|
||||
"DEVICES": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"topo_info",
|
||||
"DEVICES"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"i2c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"SMBUS"
|
||||
]
|
||||
}
|
285
platform/pddf/i2c/utils/schema/SYSSTAT.schema
Normal file
285
platform/pddf/i2c/utils/schema/SYSSTAT.schema
Normal file
@ -0,0 +1,285 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"SYSSTAT": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type",
|
||||
"device_name"
|
||||
]
|
||||
},
|
||||
"dev_attr": {
|
||||
"type": "object"
|
||||
},
|
||||
"attr_list": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_devaddr": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_offset": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_mask": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_len": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"attr_devaddr",
|
||||
"attr_offset",
|
||||
"attr_mask",
|
||||
"attr_len"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_devaddr": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_offset": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_mask": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_len": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"attr_devaddr",
|
||||
"attr_offset",
|
||||
"attr_mask",
|
||||
"attr_len"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_devaddr": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_offset": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_mask": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_len": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"attr_devaddr",
|
||||
"attr_offset",
|
||||
"attr_mask",
|
||||
"attr_len"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_devaddr": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_offset": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_mask": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_len": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"attr_devaddr",
|
||||
"attr_offset",
|
||||
"attr_mask",
|
||||
"attr_len"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_devaddr": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_offset": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_mask": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_len": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"attr_devaddr",
|
||||
"attr_offset",
|
||||
"attr_mask",
|
||||
"attr_len"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_devaddr": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_offset": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_mask": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_len": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"attr_devaddr",
|
||||
"attr_offset",
|
||||
"attr_mask",
|
||||
"attr_len"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_devaddr": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_offset": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_mask": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_len": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"attr_devaddr",
|
||||
"attr_offset",
|
||||
"attr_mask",
|
||||
"attr_len"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_devaddr": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_offset": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_mask": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_len": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"attr_devaddr",
|
||||
"attr_offset",
|
||||
"attr_mask",
|
||||
"attr_len"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_devaddr": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_offset": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_mask": {
|
||||
"type": "string"
|
||||
},
|
||||
"attr_len": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"attr_devaddr",
|
||||
"attr_offset",
|
||||
"attr_mask",
|
||||
"attr_len"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"dev_attr",
|
||||
"attr_list"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"SYSSTAT"
|
||||
]
|
||||
}
|
102
platform/pddf/i2c/utils/schema/TEMP_SENSOR.schema
Normal file
102
platform/pddf/i2c/utils/schema/TEMP_SENSOR.schema
Normal file
@ -0,0 +1,102 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"TEMP_SENSOR": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"device_parent": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type",
|
||||
"device_parent"
|
||||
]
|
||||
},
|
||||
"i2c": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"topo_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parent_bus": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev_addr": {
|
||||
"type": "string"
|
||||
},
|
||||
"dev_type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"parent_bus",
|
||||
"dev_addr",
|
||||
"dev_type"
|
||||
]
|
||||
},
|
||||
"attr_list": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"topo_info",
|
||||
"attr_list"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"i2c"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"TEMP_SENSOR"
|
||||
]
|
||||
}
|
143
platform/pddf/i2c/utils/schema/TEMP_SENSOR_BMC.schema
Normal file
143
platform/pddf/i2c/utils/schema/TEMP_SENSOR_BMC.schema
Normal file
@ -0,0 +1,143 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"TEMP_SENSOR": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dev_info": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"device_type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"device_type"
|
||||
]
|
||||
},
|
||||
"dev_attr": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"display_name": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"display_name"
|
||||
]
|
||||
},
|
||||
"bmc": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"ipmitool": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_list": {
|
||||
"type": "array",
|
||||
"items": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bmc_cmd": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_pos": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bmc_cmd",
|
||||
"raw",
|
||||
"field_name",
|
||||
"field_pos"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bmc_cmd": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_pos": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bmc_cmd",
|
||||
"raw",
|
||||
"field_name",
|
||||
"field_pos"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attr_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"bmc_cmd": {
|
||||
"type": "string"
|
||||
},
|
||||
"raw": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"field_pos": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_name",
|
||||
"bmc_cmd",
|
||||
"raw",
|
||||
"field_name",
|
||||
"field_pos"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attr_list"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"ipmitool"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"dev_info",
|
||||
"dev_attr",
|
||||
"bmc"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"TEMP_SENSOR"
|
||||
]
|
||||
}
|
9
platform/pddf/platform-api-pddf-base.dep
Normal file
9
platform/pddf/platform-api-pddf-base.dep
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
MPATH := $($(PDDF_PLATFORM_API_BASE_PY2)_SRC_PATH)
|
||||
DEP_FILES := $(SONIC_COMMON_FILES_LIST) platform/pddf/platform-api-pddf-base.mk platform/pddf/platform-api-pddf-base.dep
|
||||
DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST)
|
||||
DEP_FILES += $(shell git ls-files $(MPATH))
|
||||
|
||||
$(PDDF_PLATFORM_API_BASE_PY2)_CACHE_MODE := GIT_CONTENT_SHA
|
||||
$(PDDF_PLATFORM_API_BASE_PY2)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST)
|
||||
$(PDDF_PLATFORM_API_BASE_PY2)_DEP_FILES := $(DEP_FILES)
|
15
platform/pddf/platform-api-pddf-base.mk
Normal file
15
platform/pddf/platform-api-pddf-base.mk
Normal file
@ -0,0 +1,15 @@
|
||||
####################################################
|
||||
# PDDF Generic 2.0 Platform API base classes
|
||||
####################################################
|
||||
PDDF_PLATFORM_API_BASE_VERSION = 1.0
|
||||
|
||||
export PDDF_PLATFORM_API_BASE_VERSION
|
||||
|
||||
PDDF_PLATFORM_API_BASE_PY2 = sonic_platform_pddf_common-$(PDDF_PLATFORM_API_BASE_VERSION)-py2-none-any.whl
|
||||
$(PDDF_PLATFORM_API_BASE_PY2)_SRC_PATH = $(PLATFORM_PDDF_PATH)/platform-api-pddf-base
|
||||
$(PDDF_PLATFORM_API_BASE_PY2)_PYTHON_VERSION = 2
|
||||
$(PDDF_PLATFORM_API_BASE_PY2)_DEPENDS = $(SONIC_CONFIG_ENGINE)
|
||||
SONIC_PYTHON_WHEELS += $(PDDF_PLATFORM_API_BASE_PY2)
|
||||
|
||||
export pddf_platform_api_base_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(PDDF_PLATFORM_API_BASE_PY2))"
|
||||
export PDDF_PLATFORM_API_BASE_PY2
|
30
platform/pddf/platform-api-pddf-base/setup.py
Executable file
30
platform/pddf/platform-api-pddf-base/setup.py
Executable file
@ -0,0 +1,30 @@
|
||||
|
||||
from setuptools import setup
|
||||
|
||||
setup(
|
||||
name='sonic-platform-pddf-common',
|
||||
version='1.0',
|
||||
description='SONIC platform APIs base (2.0) implementation on PDDF supported platforms',
|
||||
license='Apache 2.0',
|
||||
author='SONiC Team',
|
||||
author_email='linuxnetdev@microsoft.com',
|
||||
url='https://github.com/Azure/sonic-buildimage',
|
||||
maintainer='Fuzail Khan',
|
||||
maintainer_email='fuzail.khan@broadcom.com',
|
||||
packages=[
|
||||
'sonic_platform_pddf_base',
|
||||
],
|
||||
classifiers=[
|
||||
'Development Status :: 3 - Alpha',
|
||||
'Environment :: Plugins',
|
||||
'Intended Audience :: Developers',
|
||||
'Intended Audience :: Information Technology',
|
||||
'Intended Audience :: System Administrators',
|
||||
'License :: OSI Approved :: Apache Software License',
|
||||
'Natural Language :: English',
|
||||
'Operating System :: POSIX :: Linux',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Topic :: Utilities',
|
||||
],
|
||||
keywords='sonic SONiC platform PLATFORM',
|
||||
)
|
516
platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_chassis.py
Executable file
516
platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_chassis.py
Executable file
@ -0,0 +1,516 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# PDDF
|
||||
# Module contains an implementation of SONiC Platform Base API and
|
||||
# provides the platform information
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
try:
|
||||
import sys
|
||||
from sonic_platform_base.chassis_base import ChassisBase
|
||||
from sonic_platform.sfp import Sfp
|
||||
from sonic_platform.psu import Psu
|
||||
from sonic_platform.fan import Fan
|
||||
from sonic_platform.thermal import Thermal
|
||||
from sonic_platform.eeprom import Eeprom
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
class PddfChassis(ChassisBase):
|
||||
"""
|
||||
PDDF Generic Chassis class
|
||||
"""
|
||||
pddf_obj = {}
|
||||
plugin_data = {}
|
||||
|
||||
def __init__(self, pddf_data=None, pddf_plugin_data=None):
|
||||
|
||||
ChassisBase.__init__(self)
|
||||
|
||||
self.pddf_obj = pddf_data if pddf_data else None
|
||||
self.plugin_data = pddf_plugin_data if pddf_plugin_data else None
|
||||
if not self.pddf_obj or not self.plugin_data:
|
||||
try:
|
||||
import pddfparse
|
||||
import json
|
||||
self.pddf_obj = pddfparse.PddfParse()
|
||||
with open('/usr/share/sonic/platform/pddf/pd-plugin.json') as pd:
|
||||
self.plugin_data = json.load(pd)
|
||||
except Exception as e:
|
||||
raise Exception("Error: Unable to load PDDF JSON data - %s" % str(e))
|
||||
|
||||
self.platform_inventory = self.pddf_obj.get_platform()
|
||||
|
||||
# Initialize EEPROM
|
||||
self.sys_eeprom = Eeprom(self.pddf_obj, self.plugin_data)
|
||||
|
||||
# FANs
|
||||
for i in range(self.platform_inventory['num_fantrays']):
|
||||
for j in range(self.platform_inventory['num_fans_pertray']):
|
||||
fan = Fan(i, j, self.pddf_obj, self.plugin_data)
|
||||
self._fan_list.append(fan)
|
||||
|
||||
# PSUs
|
||||
for i in range(self.platform_inventory['num_psus']):
|
||||
psu = Psu(i, self.pddf_obj, self.plugin_data)
|
||||
self._psu_list.append(psu)
|
||||
|
||||
# OPTICs
|
||||
for index in range(self.platform_inventory['num_ports']):
|
||||
sfp = Sfp(index, self.pddf_obj, self.plugin_data)
|
||||
self._sfp_list.append(sfp)
|
||||
|
||||
# THERMALs
|
||||
for i in range(self.platform_inventory['num_temps']):
|
||||
thermal = Thermal(i, self.pddf_obj, self.plugin_data)
|
||||
self._thermal_list.append(thermal)
|
||||
|
||||
# SYSTEM LED Test Cases
|
||||
"""
|
||||
#comment out test cases
|
||||
sys_led_list= { "LOC":0,
|
||||
"DIAG":0,
|
||||
"FAN":0,
|
||||
"SYS":0,
|
||||
"PSU1":0,
|
||||
"PSU2":1
|
||||
}
|
||||
|
||||
for led in sys_led_list:
|
||||
color=self.get_system_led(led, sys_led_list[led])
|
||||
print color
|
||||
|
||||
self.set_system_led("LOC_LED","STATUS_LED_COLOR_GREEN")
|
||||
color=self.get_system_led("LOC_LED")
|
||||
print "Set Green: " + color
|
||||
self.set_system_led("LOC_LED", "STATUS_LED_COLOR_OFF")
|
||||
color=self.get_system_led("LOC_LED")
|
||||
print "Set off: " + color
|
||||
"""
|
||||
|
||||
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the chassis
|
||||
Returns:
|
||||
string: The name of the chassis
|
||||
"""
|
||||
return self.sys_eeprom.modelstr()
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the chassis
|
||||
Returns:
|
||||
bool: True if chassis is present, False if not
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_model(self):
|
||||
"""
|
||||
Retrieves the model number (or part number) of the chassis
|
||||
Returns:
|
||||
string: Model/part number of chassis
|
||||
"""
|
||||
return self.sys_eeprom.part_number_str()
|
||||
|
||||
def get_serial(self):
|
||||
"""
|
||||
Retrieves the serial number of the chassis (Service tag)
|
||||
Returns:
|
||||
string: Serial number of chassis
|
||||
"""
|
||||
return self.sys_eeprom.serial_str()
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the operational status of the chassis
|
||||
Returns:
|
||||
bool: A boolean value, True if chassis is operating properly
|
||||
False if not
|
||||
"""
|
||||
return True
|
||||
|
||||
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'
|
||||
"""
|
||||
return self.sys_eeprom.base_mac_addr()
|
||||
|
||||
def get_serial_number(self):
|
||||
"""
|
||||
Retrieves the hardware serial number for the chassis
|
||||
|
||||
Returns:
|
||||
A string containing the hardware serial number for this
|
||||
chassis.
|
||||
"""
|
||||
return self.sys_eeprom.serial_number_str()
|
||||
|
||||
def get_system_eeprom_info(self):
|
||||
"""
|
||||
Retrieves the full content of system EEPROM information for the chassis
|
||||
Returns:
|
||||
A dictionary where keys are the type code defined in
|
||||
OCP ONIE TlvInfo EEPROM format and values are their corresponding
|
||||
values.
|
||||
"""
|
||||
return self.sys_eeprom.system_eeprom_info()
|
||||
|
||||
def get_reboot_cause(self):
|
||||
"""
|
||||
Retrieves the cause of the previous reboot
|
||||
|
||||
Returns:
|
||||
A tuple (string, string) where the first element is a string
|
||||
containing the cause of the previous reboot. This string must be
|
||||
one of the predefined strings in this class. If the first string
|
||||
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
|
||||
to pass a description of the reboot cause.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_component_name_list(self):
|
||||
"""
|
||||
Retrieves a list of the names of components available on the chassis (e.g., BIOS, CPLD, FPGA, etc.)
|
||||
|
||||
Returns:
|
||||
A list containing the names of components available on the chassis
|
||||
"""
|
||||
return self._component_name_list
|
||||
|
||||
def get_firmware_version(self, component_name):
|
||||
"""
|
||||
Retrieves platform-specific hardware/firmware versions for chassis
|
||||
componenets such as BIOS, CPLD, FPGA, etc.
|
||||
Args:
|
||||
component_name: A string, the component name.
|
||||
|
||||
Returns:
|
||||
A string containing platform-specific component versions
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def install_component_firmware(self, component_name, image_path):
|
||||
"""
|
||||
Install firmware to component
|
||||
Args:
|
||||
component_name: A string, the component name.
|
||||
image_path: A string, path to firmware image.
|
||||
|
||||
Returns:
|
||||
A boolean, True if install was successful, False if not
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
##############################################
|
||||
# Module methods
|
||||
##############################################
|
||||
|
||||
def get_num_modules(self):
|
||||
"""
|
||||
Retrieves the number of modules available on this chassis
|
||||
|
||||
Returns:
|
||||
An integer, the number of modules available on this chassis
|
||||
"""
|
||||
return len(self._module_list)
|
||||
|
||||
def get_all_modules(self):
|
||||
"""
|
||||
Retrieves all modules available on this chassis
|
||||
|
||||
Returns:
|
||||
A list of objects derived from ModuleBase representing all
|
||||
modules available on this chassis
|
||||
"""
|
||||
return self._module_list
|
||||
|
||||
def get_module(self, index):
|
||||
"""
|
||||
Retrieves module represented by (0-based) index <index>
|
||||
|
||||
Args:
|
||||
index: An integer, the index (0-based) of the module to
|
||||
retrieve
|
||||
|
||||
Returns:
|
||||
An object dervied from ModuleBase representing the specified
|
||||
module
|
||||
"""
|
||||
module = None
|
||||
|
||||
try:
|
||||
module = self._module_list[index]
|
||||
except IndexError:
|
||||
sys.stderr.write("Module index {} out of range (0-{})\n".format(
|
||||
index, len(self._module_list)-1))
|
||||
|
||||
return module
|
||||
##############################################
|
||||
# Fan methods
|
||||
##############################################
|
||||
|
||||
def get_num_fans(self):
|
||||
"""
|
||||
Retrieves the number of fans available on this chassis
|
||||
|
||||
Returns:
|
||||
An integer, the number of fan modules available on this chassis
|
||||
"""
|
||||
return len(self._fan_list)
|
||||
|
||||
def get_all_fans(self):
|
||||
"""
|
||||
Retrieves all fan modules available on this chassis
|
||||
|
||||
Returns:
|
||||
A list of objects derived from FanBase representing all fan
|
||||
modules available on this chassis
|
||||
"""
|
||||
return self._fan_list
|
||||
|
||||
def get_fan(self, index):
|
||||
"""
|
||||
Retrieves fan module represented by (0-based) index <index>
|
||||
|
||||
Args:
|
||||
index: An integer, the index (0-based) of the fan module to
|
||||
retrieve
|
||||
|
||||
Returns:
|
||||
An object dervied from FanBase representing the specified fan
|
||||
module
|
||||
"""
|
||||
fan = None
|
||||
|
||||
try:
|
||||
fan = self._fan_list[index]
|
||||
except IndexError:
|
||||
sys.stderr.write("Fan index {} out of range (0-{})\n".format(
|
||||
index, len(self._fan_list)-1))
|
||||
|
||||
return fan
|
||||
|
||||
##############################################
|
||||
# PSU methods
|
||||
##############################################
|
||||
|
||||
def get_num_psus(self):
|
||||
"""
|
||||
Retrieves the number of power supply units available on this chassis
|
||||
|
||||
Returns:
|
||||
An integer, the number of power supply units available on this
|
||||
chassis
|
||||
"""
|
||||
return len(self._psu_list)
|
||||
|
||||
def get_all_psus(self):
|
||||
"""
|
||||
Retrieves all power supply units available on this chassis
|
||||
|
||||
Returns:
|
||||
A list of objects derived from PsuBase representing all power
|
||||
supply units available on this chassis
|
||||
"""
|
||||
return self._psu_list
|
||||
|
||||
def get_psu(self, index):
|
||||
"""
|
||||
Retrieves power supply unit represented by (0-based) index <index>
|
||||
|
||||
Args:
|
||||
index: An integer, the index (0-based) of the power supply unit to
|
||||
retrieve
|
||||
|
||||
Returns:
|
||||
An object dervied from PsuBase representing the specified power
|
||||
supply unit
|
||||
"""
|
||||
psu = None
|
||||
|
||||
try:
|
||||
psu = self._psu_list[index]
|
||||
except IndexError:
|
||||
sys.stderr.write("PSU index {} out of range (0-{})\n".format(
|
||||
index, len(self._psu_list)-1))
|
||||
|
||||
return psu
|
||||
|
||||
##############################################
|
||||
# THERMAL methods
|
||||
##############################################
|
||||
|
||||
def get_num_thermals(self):
|
||||
"""
|
||||
Retrieves the number of thermals available on this chassis
|
||||
|
||||
Returns:
|
||||
An integer, the number of thermals available on this chassis
|
||||
"""
|
||||
return len(self._thermal_list)
|
||||
|
||||
def get_all_thermals(self):
|
||||
"""
|
||||
Retrieves all thermals available on this chassis
|
||||
|
||||
Returns:
|
||||
A list of objects derived from ThermalBase representing all thermals
|
||||
available on this chassis
|
||||
"""
|
||||
return self._thermal_list
|
||||
|
||||
def get_thermal(self, index):
|
||||
"""
|
||||
Retrieves thermal unit represented by (0-based) index <index>
|
||||
|
||||
Args:
|
||||
index: An integer, the index (0-based) of the thermal to
|
||||
retrieve
|
||||
|
||||
Returns:
|
||||
An object dervied from ThermalBase representing the specified thermal
|
||||
"""
|
||||
thermal = None
|
||||
|
||||
try:
|
||||
thermal = self._thermal_list[index]
|
||||
except IndexError:
|
||||
sys.stderr.write("THERMAL index {} out of range (0-{})\n".format(
|
||||
index, len(self._thermal_list)-1))
|
||||
|
||||
return thermal
|
||||
|
||||
##############################################
|
||||
# SFP methods
|
||||
##############################################
|
||||
|
||||
def get_num_sfps(self):
|
||||
"""
|
||||
Retrieves the number of sfps available on this chassis
|
||||
|
||||
Returns:
|
||||
An integer, the number of sfps available on this chassis
|
||||
"""
|
||||
return len(self._sfp_list)
|
||||
|
||||
def get_all_sfps(self):
|
||||
"""
|
||||
Retrieves all sfps available on this chassis
|
||||
|
||||
Returns:
|
||||
A list of objects derived from SfpBase representing all sfps
|
||||
available on this chassis
|
||||
"""
|
||||
return self._sfp_list
|
||||
|
||||
def get_sfp(self, index):
|
||||
"""
|
||||
Retrieves sfp represented by (0-based) index <index>
|
||||
|
||||
Args:
|
||||
index: An integer, the index (0-based) of the sfp to retrieve.
|
||||
The index should be the sequence of a physical port in a chassis,
|
||||
starting from 0.
|
||||
For example, 0 for Ethernet0, 1 for Ethernet4 and so on.
|
||||
|
||||
Returns:
|
||||
An object dervied from SfpBase representing the specified sfp
|
||||
"""
|
||||
sfp = None
|
||||
|
||||
try:
|
||||
sfp = self._sfp_list[index]
|
||||
except IndexError:
|
||||
sys.stderr.write("SFP index {} out of range (0-{})\n".format(
|
||||
index, len(self._sfp_list)-1))
|
||||
|
||||
return sfp
|
||||
|
||||
##############################################
|
||||
# System LED methods
|
||||
##############################################
|
||||
def set_system_led(self, led_device_name, color):
|
||||
result, msg = self.pddf_obj.is_supported_sysled_state(led_device_name, color);
|
||||
if result == False:
|
||||
print msg
|
||||
return (False)
|
||||
|
||||
index=self.pddf_obj.data[led_device_name]['dev_attr']['index']
|
||||
device_name=self.pddf_obj.data[led_device_name]['dev_info']['device_name']
|
||||
self.pddf_obj.create_attr('device_name', device_name, self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('color', color, self.pddf_obj.get_led_cur_state_path())
|
||||
self.pddf_obj.create_attr('dev_ops', 'set_status', self.pddf_obj.get_led_path())
|
||||
return (True)
|
||||
|
||||
|
||||
def get_system_led(self, led_device_name):
|
||||
if (not led_device_name in self.pddf_obj.data.keys()):
|
||||
status= "[FAILED] " + led_device_name + " is not configured"
|
||||
return (status)
|
||||
|
||||
index=self.pddf_obj.data[led_device_name]['dev_attr']['index']
|
||||
device_name=self.pddf_obj.data[led_device_name]['dev_info']['device_name']
|
||||
self.pddf_obj.create_attr('device_name', device_name, self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('dev_ops', 'get_status', self.pddf_obj.get_led_path())
|
||||
color=self.pddf_obj.get_led_color()
|
||||
return (color)
|
||||
|
||||
|
||||
##############################################
|
||||
# Other methods
|
||||
##############################################
|
||||
|
||||
def get_watchdog(self):
|
||||
"""
|
||||
Retreives hardware watchdog device on this chassis
|
||||
|
||||
Returns:
|
||||
An object derived from WatchdogBase representing the hardware
|
||||
watchdog device
|
||||
"""
|
||||
return self._watchdog
|
||||
|
||||
def get_eeprom(self):
|
||||
"""
|
||||
Retreives eeprom device on this chassis
|
||||
|
||||
Returns:
|
||||
An object derived from WatchdogBase representing the hardware
|
||||
eeprom device
|
||||
"""
|
||||
return self.sys_eeprom
|
||||
|
||||
def get_change_event(self, timeout=0):
|
||||
"""
|
||||
Returns a nested dictionary containing all devices which have
|
||||
experienced a change at chassis level
|
||||
|
||||
Args:
|
||||
timeout: Timeout in milliseconds (optional). If timeout == 0,
|
||||
this method will block until a change is detected.
|
||||
Returns:
|
||||
(bool, dict):
|
||||
- True if call successful, False if not;
|
||||
- A nested dictionary where key is a device type,
|
||||
value is a dictionary with key:value pairs in the format of
|
||||
{'device_id':'device_event'},
|
||||
where device_id is the device ID for this device and
|
||||
device_event,
|
||||
status='1' represents device inserted,
|
||||
status='0' represents device removed.
|
||||
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
|
||||
indicates that fan 0 has been removed, fan 2
|
||||
has been inserted and sfp 11 has been removed.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# PDDF
|
||||
#
|
||||
# PDDF syseeprom base class inherited from the base class
|
||||
#############################################################################
|
||||
|
||||
try:
|
||||
from sonic_eeprom import eeprom_tlvinfo
|
||||
import binascii
|
||||
except ImportError, e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class PddfEeprom(eeprom_tlvinfo.TlvInfoDecoder):
|
||||
_TLV_INFO_MAX_LEN = 256
|
||||
pddf_obj = {}
|
||||
plugin_data = {}
|
||||
|
||||
def __init__(self, pddf_data=None, pddf_plugin_data=None):
|
||||
if not pddf_data or not pddf_plugin_data:
|
||||
raise ValueError('PDDF JSON data error')
|
||||
|
||||
self.pddf_obj = pddf_data
|
||||
self.plugin_data = pddf_plugin_data
|
||||
|
||||
# system EEPROM always has device name EEPROM1
|
||||
self.eeprom_path = self.pddf_obj.get_path("EEPROM1", "eeprom")
|
||||
if self.eeprom_path is None:
|
||||
return
|
||||
|
||||
super(PddfEeprom, self).__init__(self.eeprom_path, 0, '', True)
|
||||
self.eeprom_tlv_dict = dict()
|
||||
try:
|
||||
self.eeprom_data = self.read_eeprom()
|
||||
except:
|
||||
self.eeprom_data = "N/A"
|
||||
raise RuntimeError("PddfEeprom is not Programmed")
|
||||
else:
|
||||
eeprom = self.eeprom_data
|
||||
|
||||
if not self.is_valid_tlvinfo_header(eeprom):
|
||||
return
|
||||
|
||||
total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10])
|
||||
tlv_index = self._TLV_INFO_HDR_LEN
|
||||
tlv_end = self._TLV_INFO_HDR_LEN + total_length
|
||||
|
||||
while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end:
|
||||
if not self.is_valid_tlv(eeprom[tlv_index:]):
|
||||
break
|
||||
|
||||
tlv = eeprom[tlv_index:tlv_index + 2
|
||||
+ ord(eeprom[tlv_index + 1])]
|
||||
code = "0x%02X" % (ord(tlv[0]))
|
||||
|
||||
if ord(tlv[0]) == self._TLV_CODE_VENDOR_EXT:
|
||||
value = str((ord(tlv[2]) << 24) | (ord(tlv[3]) << 16) |
|
||||
(ord(tlv[4]) << 8) | ord(tlv[5]))
|
||||
value += str(tlv[6:6 + ord(tlv[1])])
|
||||
else:
|
||||
name, value = self.decoder(None, tlv)
|
||||
|
||||
self.eeprom_tlv_dict[code] = value
|
||||
if ord(eeprom[tlv_index]) == self._TLV_CODE_CRC_32:
|
||||
break
|
||||
|
||||
tlv_index += ord(eeprom[tlv_index+1]) + 2
|
||||
|
||||
def serial_number_str(self):
|
||||
(is_valid, results) = self.get_tlv_field(
|
||||
self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER)
|
||||
if not is_valid:
|
||||
return "N/A"
|
||||
return results[2]
|
||||
|
||||
def base_mac_addr(self):
|
||||
(is_valid, t) = self.get_tlv_field(
|
||||
self.eeprom_data, self._TLV_CODE_MAC_BASE)
|
||||
if not is_valid or t[1] != 6:
|
||||
return super(TlvInfoDecoder, self).switchaddrstr(e)
|
||||
|
||||
return ":".join([binascii.b2a_hex(T) for T in t[2]])
|
||||
|
||||
def modelstr(self):
|
||||
(is_valid, results) = self.get_tlv_field(
|
||||
self.eeprom_data, self._TLV_CODE_PRODUCT_NAME)
|
||||
if not is_valid:
|
||||
return "N/A"
|
||||
|
||||
return results[2]
|
||||
|
||||
def part_number_str(self):
|
||||
(is_valid, results) = self.get_tlv_field(
|
||||
self.eeprom_data, self._TLV_CODE_PART_NUMBER)
|
||||
if not is_valid:
|
||||
return "N/A"
|
||||
|
||||
return results[2]
|
||||
|
||||
def serial_str(self):
|
||||
(is_valid, results) = self.get_tlv_field(
|
||||
self.eeprom_data, self._TLV_CODE_SERVICE_TAG)
|
||||
if not is_valid:
|
||||
return "N/A"
|
||||
|
||||
return results[2]
|
||||
|
||||
def revision_str(self):
|
||||
(is_valid, results) = self.get_tlv_field(
|
||||
self.eeprom_data, self._TLV_CODE_DEVICE_VERSION)
|
||||
if not is_valid:
|
||||
return "N/A"
|
||||
|
||||
return results[2]
|
||||
|
||||
def system_eeprom_info(self):
|
||||
"""
|
||||
Returns a dictionary, where keys are the type code defined in
|
||||
ONIE EEPROM format and values are their corresponding values
|
||||
found in the system EEPROM.
|
||||
"""
|
||||
return self.eeprom_tlv_dict
|
332
platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_fan.py
Executable file
332
platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_fan.py
Executable file
@ -0,0 +1,332 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# All the supported FAN SysFS aattributes are
|
||||
#- fan<idx>_present
|
||||
#- fan<idx>_direction
|
||||
#- fan<idx>_input
|
||||
#- fan<idx>_pwm
|
||||
#- fan<idx>_fault
|
||||
# where idx is in the range [1-32]
|
||||
#
|
||||
|
||||
try:
|
||||
from sonic_platform_base.fan_base import FanBase
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class PddfFan(FanBase):
|
||||
"""PDDF generic Fan class"""
|
||||
|
||||
pddf_obj = {}
|
||||
plugin_data = {}
|
||||
|
||||
def __init__(self, tray_idx, fan_idx=0, pddf_data=None, pddf_plugin_data=None, is_psu_fan=False, psu_index=0):
|
||||
# idx is 0-based
|
||||
if not pddf_data or not pddf_plugin_data:
|
||||
raise ValueError('PDDF JSON data error')
|
||||
|
||||
self.pddf_obj = pddf_data
|
||||
self.plugin_data = pddf_plugin_data
|
||||
self.platform = self.pddf_obj.get_platform()
|
||||
|
||||
if tray_idx<0 or tray_idx>=self.platform['num_fantrays']:
|
||||
print "Invalid fantray index %d\n"%tray_idx
|
||||
return
|
||||
|
||||
if fan_idx<0 or fan_idx>=self.platform['num_fans_pertray']:
|
||||
print "Invalid fan index (within a tray) %d\n"%fan_idx
|
||||
return
|
||||
|
||||
self.fantray_index = tray_idx+1
|
||||
self.fan_index = fan_idx+1
|
||||
self.is_psu_fan = is_psu_fan
|
||||
if self.is_psu_fan:
|
||||
self.fans_psu_index = psu_index
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the fan name
|
||||
Returns: String containing fan-name
|
||||
"""
|
||||
if self.is_psu_fan:
|
||||
return "PSU{}_FAN{}".format(self.fans_psu_index, self.fan_index)
|
||||
else:
|
||||
if 'name' in self.plugin_data['FAN']:
|
||||
return self.plugin_data['FAN']['name'][str(self.fantray_index)]
|
||||
else:
|
||||
return "Fantray{}_{}".format(self.fantray_index, self.fan_index)
|
||||
|
||||
def get_presence(self):
|
||||
if self.is_psu_fan:
|
||||
return True
|
||||
else:
|
||||
idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index
|
||||
attr_name = "fan" + str(idx) + "_present"
|
||||
output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr_name)
|
||||
if not output:
|
||||
return False
|
||||
|
||||
mode = output['mode']
|
||||
presence = output['status'].rstrip()
|
||||
|
||||
vmap = self.plugin_data['FAN']['present'][mode]['valmap']
|
||||
|
||||
if presence in vmap:
|
||||
status = vmap[presence]
|
||||
else:
|
||||
status = False
|
||||
|
||||
return status
|
||||
|
||||
def get_status(self):
|
||||
speed = self.get_speed()
|
||||
status = True if (speed != 0) else False
|
||||
return status
|
||||
|
||||
def get_direction(self):
|
||||
"""
|
||||
Retrieves the direction of fan
|
||||
|
||||
Returns:
|
||||
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
|
||||
depending on fan direction
|
||||
"""
|
||||
if self.is_psu_fan:
|
||||
device = "PSU{}".format(self.fans_psu_index)
|
||||
output = self.pddf_obj.get_attr_name_output(device, "psu_fan_dir")
|
||||
if not output:
|
||||
return False
|
||||
|
||||
mode = output['mode']
|
||||
val = output['status']
|
||||
|
||||
val = val.rstrip()
|
||||
vmap = self.plugin_data['PSU']['psu_fan_dir'][mode]['valmap']
|
||||
|
||||
if val in vmap:
|
||||
direction = vmap[val]
|
||||
else:
|
||||
direction = val
|
||||
|
||||
else:
|
||||
idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index
|
||||
attr = "fan" + str(idx) + "_direction"
|
||||
output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr)
|
||||
if not output:
|
||||
return False
|
||||
|
||||
mode = output['mode']
|
||||
val = output['status']
|
||||
|
||||
val = val.rstrip()
|
||||
vmap = self.plugin_data['FAN']['direction'][mode]['valmap']
|
||||
if val in vmap:
|
||||
direction = vmap[val]
|
||||
else:
|
||||
direction = val
|
||||
|
||||
return direction
|
||||
|
||||
def get_speed(self):
|
||||
"""
|
||||
Retrieves the speed of fan as a percentage of full speed
|
||||
|
||||
Returns:
|
||||
An integer, the percentage of full fan speed, in the range 0 (off)
|
||||
to 100 (full speed)
|
||||
"""
|
||||
if self.is_psu_fan:
|
||||
attr = "psu_fan{}_speed_rpm".format(self.fan_index)
|
||||
device = "PSU{}".format(self.fans_psu_index)
|
||||
output = self.pddf_obj.get_attr_name_output(device, attr)
|
||||
if not output:
|
||||
return 0
|
||||
|
||||
output['status'] = output['status'].rstrip()
|
||||
if output['status'].isalpha():
|
||||
return 0
|
||||
else:
|
||||
speed = int(output['status'])
|
||||
|
||||
max_speed = int(self.plugin_data['PSU']['PSU_FAN_MAX_SPEED'])
|
||||
speed_percentage = (speed*100)/max_speed
|
||||
return speed_percentage
|
||||
else:
|
||||
# TODO This calculation should change based on MAX FAN SPEED
|
||||
idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index
|
||||
attr = "fan" + str(idx) + "_pwm"
|
||||
output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr)
|
||||
|
||||
if not output:
|
||||
return 0
|
||||
|
||||
output['status'] = output['status'].rstrip()
|
||||
if output['status'].isalpha():
|
||||
return 0
|
||||
else:
|
||||
fpwm = int(output['status'])
|
||||
|
||||
pwm_to_dc = eval(self.plugin_data['FAN']['pwm_to_duty_cycle'])
|
||||
speed_percentage = int(round(pwm_to_dc(fpwm)))
|
||||
|
||||
return speed_percentage
|
||||
|
||||
def get_speed_rpm(self):
|
||||
"""
|
||||
Retrieves the speed of fan in RPM
|
||||
|
||||
Returns:
|
||||
An integer, Speed of fan in RPM
|
||||
"""
|
||||
if self.is_psu_fan:
|
||||
attr = "psu_fan{}_speed_rpm".format(self.fan_index)
|
||||
device = "PSU{}".format(self.fans_psu_index)
|
||||
output = self.pddf_obj.get_attr_name_output(device, attr)
|
||||
if not output:
|
||||
return 0
|
||||
|
||||
output['status'] = output['status'].rstrip()
|
||||
if output['status'].isalpha():
|
||||
return 0
|
||||
else:
|
||||
speed = int(float(output['status']))
|
||||
|
||||
rpm_speed = speed
|
||||
return rpm_speed
|
||||
else:
|
||||
idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index
|
||||
attr = "fan" + str(idx) + "_input"
|
||||
output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr)
|
||||
|
||||
if output is None:
|
||||
return 0
|
||||
|
||||
output['status'] = output['status'].rstrip()
|
||||
if output['status'].isalpha():
|
||||
return 0
|
||||
else:
|
||||
rpm_speed = int(float(output['status']))
|
||||
|
||||
return rpm_speed
|
||||
|
||||
def get_target_speed(self):
|
||||
"""
|
||||
Retrieves the target (expected) speed of the fan
|
||||
|
||||
Returns:
|
||||
An integer, the percentage of full fan speed, in the range 0 (off)
|
||||
to 100 (full speed)
|
||||
"""
|
||||
target_speed = 0
|
||||
if self.is_psu_fan:
|
||||
# Target speed not usually supported for PSU fans
|
||||
target_speed = 0
|
||||
else:
|
||||
idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index
|
||||
attr = "fan" + str(idx) + "_pwm"
|
||||
output = self.pddf_obj.get_attr_name_output("FAN-CTRL", attr)
|
||||
|
||||
if not output:
|
||||
return 0
|
||||
|
||||
output['status'] = output['status'].rstrip()
|
||||
if output['status'].isalpha():
|
||||
return 0
|
||||
else:
|
||||
fpwm = int(output['status'])
|
||||
|
||||
pwm_to_dc = eval(self.plugin_data['FAN']['pwm_to_duty_cycle'])
|
||||
speed_percentage = int(round(pwm_to_dc(fpwm)))
|
||||
target_speed = speed_percentage
|
||||
|
||||
return target_speed
|
||||
|
||||
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
|
||||
"""
|
||||
# Fix the speed vairance to 10 percent. If it changes based on platforms, overwrite
|
||||
# this value in derived pddf fan class
|
||||
return 10
|
||||
|
||||
def set_speed(self, speed):
|
||||
"""
|
||||
Sets the fan speed
|
||||
|
||||
Args:
|
||||
speed: An integer, the percentage of full fan speed to set fan to,
|
||||
in the range 0 (off) to 100 (full speed)
|
||||
|
||||
Returns:
|
||||
A boolean, True if speed is set successfully, False if not
|
||||
"""
|
||||
if self.is_psu_fan:
|
||||
print "Setting PSU fan speed is not allowed"
|
||||
return False
|
||||
else:
|
||||
if speed<0 or speed>100:
|
||||
print "Error: Invalid speed %d. Please provide a valid speed percentage"%speed
|
||||
return False
|
||||
|
||||
if 'duty_cycle_to_pwm' not in self.plugin_data['FAN']:
|
||||
print "Setting fan speed is not allowed !"
|
||||
return False
|
||||
else:
|
||||
duty_cycle_to_pwm = eval(self.plugin_data['FAN']['duty_cycle_to_pwm'])
|
||||
pwm = int(round(duty_cycle_to_pwm(speed)))
|
||||
|
||||
|
||||
status = False
|
||||
idx = (self.fantray_index-1)*self.platform['num_fans_pertray'] + self.fan_index
|
||||
attr = "fan" + str(idx) + "_pwm"
|
||||
output = self.pddf_obj.set_attr_name_output("FAN-CTRL", attr, pwm)
|
||||
if not output:
|
||||
return False
|
||||
|
||||
status = output['status']
|
||||
|
||||
return status
|
||||
|
||||
def set_status_led(self, color):
|
||||
index = str(self.fantray_index-1)
|
||||
led_device_name = "FANTRAY{}".format(self.fantray_index) + "_LED"
|
||||
|
||||
result, msg = self.pddf_obj.is_supported_sysled_state(led_device_name, color);
|
||||
if result == False:
|
||||
print msg
|
||||
return (False)
|
||||
|
||||
|
||||
device_name=self.pddf_obj.data[led_device_name]['dev_info']['device_name']
|
||||
self.pddf_obj.create_attr('device_name', device_name, self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('color', color, self.pddf_obj.get_led_cur_state_path())
|
||||
self.pddf_obj.create_attr('dev_ops', 'set_status', self.pddf_obj.get_led_path())
|
||||
return (True)
|
||||
|
||||
|
||||
def get_status_led(self):
|
||||
index = str(self.fantray_index-1)
|
||||
fan_led_device = "FANTRAY{}".format(self.fantray_index) + "_LED"
|
||||
|
||||
if (not fan_led_device in self.pddf_obj.data.keys()):
|
||||
# Implement a generic status_led color scheme
|
||||
if self.get_status():
|
||||
return self.STATUS_LED_COLOR_GREEN
|
||||
else:
|
||||
return self.STATUS_LED_COLOR_OFF
|
||||
|
||||
device_name=self.pddf_obj.data[fan_led_device]['dev_info']['device_name']
|
||||
self.pddf_obj.create_attr('device_name', device_name, self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('dev_ops', 'get_status', self.pddf_obj.get_led_path())
|
||||
color=self.pddf_obj.get_led_color()
|
||||
return (color)
|
||||
|
||||
def dump_sysfs(self):
|
||||
return self.pddf_obj.cli_dump_dsysfs('fan')
|
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# PDDF
|
||||
# Module contains an implementation of SONiC Platform API and
|
||||
# provides the platform information
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
|
||||
try:
|
||||
import json
|
||||
import pddfparse
|
||||
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 PddfPlatform(PlatformBase):
|
||||
"""
|
||||
PDDF Generic Platform class
|
||||
"""
|
||||
pddf_data = {}
|
||||
pddf_plugin_data = {}
|
||||
def __init__(self):
|
||||
# Initialize the JSON data
|
||||
self.pddf_data = pddfparse.PddfParse()
|
||||
with open('/usr/share/sonic/platform/pddf/pd-plugin.json') as pd:
|
||||
self.pddf_plugin_data = json.load(pd)
|
||||
|
||||
if not self.pddf_data or not self.pddf_plugin_data:
|
||||
print "Error: PDDF JSON data is not loaded properly ... Exiting"
|
||||
raise ValueError
|
||||
|
||||
PlatformBase.__init__(self)
|
||||
self._chassis = Chassis(self.pddf_data, self.pddf_plugin_data)
|
298
platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_psu.py
Executable file
298
platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_psu.py
Executable file
@ -0,0 +1,298 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# All the supported PSU SysFS aattributes are
|
||||
#- psu_present
|
||||
#- psu_model_name
|
||||
#- psu_power_good
|
||||
#- psu_mfr_id
|
||||
#- psu_serial_num
|
||||
#- psu_fan_dir
|
||||
#- psu_v_out
|
||||
#- psu_i_out
|
||||
#- psu_p_out
|
||||
#- psu_fan1_speed_rpm
|
||||
#
|
||||
|
||||
|
||||
try:
|
||||
from sonic_platform_base.psu_base import PsuBase
|
||||
from sonic_platform.fan import Fan
|
||||
except ImportError as e:
|
||||
raise ImportError (str(e) + "- required module not found")
|
||||
|
||||
|
||||
class PddfPsu(PsuBase):
|
||||
"""PDDF generic PSU class"""
|
||||
|
||||
pddf_obj = {}
|
||||
plugin_data = {}
|
||||
|
||||
|
||||
def __init__(self, index, pddf_data=None, pddf_plugin_data=None):
|
||||
PsuBase.__init__(self)
|
||||
if not pddf_data or not pddf_plugin_data:
|
||||
raise ValueError('PDDF JSON data error')
|
||||
|
||||
self.pddf_obj = pddf_data
|
||||
self.plugin_data = pddf_plugin_data
|
||||
self.platform = self.pddf_obj.get_platform()
|
||||
self.psu_index = index + 1
|
||||
|
||||
self._fan_list = [] # _fan_list under PsuBase class is a global variable, hence we need to use _fan_list per class instatiation
|
||||
self.num_psu_fans = int(self.pddf_obj.get_num_psu_fans('PSU{}'.format(index+1)))
|
||||
for psu_fan_idx in range(self.num_psu_fans):
|
||||
psu_fan = Fan(0, psu_fan_idx, pddf_data, pddf_plugin_data, True, self.psu_index)
|
||||
self._fan_list.append(psu_fan)
|
||||
|
||||
def get_num_fans(self):
|
||||
"""
|
||||
Retrieves the number of fan modules available on this PSU
|
||||
|
||||
Returns:
|
||||
An integer, the number of fan modules available on this PSU
|
||||
"""
|
||||
return len(self._fan_list)
|
||||
|
||||
def get_name(self):
|
||||
"""
|
||||
Retrieves the name of the device
|
||||
|
||||
Returns:
|
||||
string: The name of the device
|
||||
"""
|
||||
if 'name' in self.plugin_data['PSU']:
|
||||
return self.plugin_data['PSU']['name'][str(self.psu_index)]
|
||||
else:
|
||||
return "PSU{}".format(self.psu_index)
|
||||
|
||||
def get_presence(self):
|
||||
"""
|
||||
Retrieves the presence of the device
|
||||
|
||||
Returns:
|
||||
bool: True if device is present, False if not
|
||||
"""
|
||||
status = 0
|
||||
device = "PSU{}".format(self.psu_index)
|
||||
output = self.pddf_obj.get_attr_name_output(device, "psu_present")
|
||||
if not output:
|
||||
return False
|
||||
|
||||
mode = output['mode']
|
||||
status = output['status']
|
||||
|
||||
vmap = self.plugin_data['PSU']['psu_present'][mode]['valmap']
|
||||
|
||||
if status.rstrip('\n') in vmap:
|
||||
return vmap[status.rstrip('\n')]
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_model(self):
|
||||
"""
|
||||
Retrieves the model number (or part number) of the device
|
||||
|
||||
Returns:
|
||||
string: Model/part number of device
|
||||
"""
|
||||
device = "PSU{}".format(self.psu_index)
|
||||
output = self.pddf_obj.get_attr_name_output(device, "psu_model_name")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
model = output['status']
|
||||
|
||||
# strip_non_ascii
|
||||
stripped = (c for c in model if 0 < ord(c) < 127)
|
||||
model = ''.join(stripped)
|
||||
|
||||
return model.rstrip('\n')
|
||||
|
||||
def get_serial(self):
|
||||
"""
|
||||
Retrieves the serial number of the device
|
||||
|
||||
Returns:
|
||||
string: Serial number of device
|
||||
"""
|
||||
device = "PSU{}".format(self.psu_index)
|
||||
output = self.pddf_obj.get_attr_name_output(device, "psu_serial_num")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
serial = output['status']
|
||||
|
||||
return serial.rstrip('\n')
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the operational status of the device
|
||||
|
||||
Returns:
|
||||
A boolean value, True if device is operating properly, False if not
|
||||
"""
|
||||
device = "PSU{}".format(self.psu_index)
|
||||
|
||||
output = self.pddf_obj.get_attr_name_output(device, "psu_power_good")
|
||||
if not output:
|
||||
return False
|
||||
|
||||
mode = output['mode']
|
||||
status = output ['status']
|
||||
|
||||
vmap = self.plugin_data['PSU']['psu_power_good'][mode]['valmap']
|
||||
|
||||
if status.rstrip('\n') in vmap:
|
||||
return vmap[status.rstrip('\n')]
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_mfr_id(self):
|
||||
"""
|
||||
Retrieves the manufacturer id of the device
|
||||
|
||||
Returns:
|
||||
string: Manufacturer Id of device
|
||||
"""
|
||||
device = "PSU{}".format(self.psu_index)
|
||||
output = self.pddf_obj.get_attr_name_output(device, "psu_mfr_id")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
mfr = output['status']
|
||||
|
||||
return mfr.rstrip('\n')
|
||||
|
||||
def get_voltage(self):
|
||||
"""
|
||||
Retrieves current PSU voltage output
|
||||
|
||||
Returns:
|
||||
A float number, the output voltage in volts,
|
||||
e.g. 12.1
|
||||
"""
|
||||
device = "PSU{}".format(self.psu_index)
|
||||
output = self.pddf_obj.get_attr_name_output(device, "psu_v_out")
|
||||
if not output:
|
||||
return 0.0
|
||||
|
||||
v_out = output['status']
|
||||
|
||||
return float(v_out)/1000
|
||||
|
||||
def get_current(self):
|
||||
"""
|
||||
Retrieves present electric current supplied by PSU
|
||||
|
||||
Returns:
|
||||
A float number, electric current in amperes,
|
||||
e.g. 15.4
|
||||
"""
|
||||
device = "PSU{}".format(self.psu_index)
|
||||
output = self.pddf_obj.get_attr_name_output(device, "psu_i_out")
|
||||
if not output:
|
||||
return 0.0
|
||||
|
||||
i_out = output['status']
|
||||
|
||||
# current in mA
|
||||
return float(i_out)/1000
|
||||
|
||||
def get_power(self):
|
||||
"""
|
||||
Retrieves current energy supplied by PSU
|
||||
|
||||
Returns:
|
||||
A float number, the power in watts,
|
||||
e.g. 302.6
|
||||
"""
|
||||
device = "PSU{}".format(self.psu_index)
|
||||
output = self.pddf_obj.get_attr_name_output(device, "psu_p_out")
|
||||
if not output:
|
||||
return 0.0
|
||||
|
||||
p_out = output['status']
|
||||
|
||||
# power is returned in micro watts
|
||||
return float(p_out)/1000000
|
||||
|
||||
def get_powergood_status(self):
|
||||
"""
|
||||
Retrieves the powergood status of PSU
|
||||
|
||||
Returns:
|
||||
A boolean, True if PSU has stablized its output voltages and
|
||||
passed all its internal self-tests, False if not.
|
||||
"""
|
||||
return self.get_status()
|
||||
|
||||
def set_status_led(self, color):
|
||||
index = str(self.psu_index-1)
|
||||
led_device_name = "PSU{}".format(self.psu_index) + "_LED"
|
||||
|
||||
result, msg = self.pddf_obj.is_supported_sysled_state(led_device_name, color);
|
||||
if result == False:
|
||||
print msg
|
||||
return (False)
|
||||
|
||||
device_name=self.pddf_obj.data[led_device_name]['dev_info']['device_name']
|
||||
self.pddf_obj.create_attr('device_name', device_name, self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('color', color, self.pddf_obj.get_led_cur_state_path())
|
||||
self.pddf_obj.create_attr('dev_ops', 'set_status', self.pddf_obj.get_led_path())
|
||||
return (True)
|
||||
|
||||
def get_status_led(self):
|
||||
index = str(self.psu_index-1)
|
||||
psu_led_device = "PSU{}_LED".format(self.psu_index)
|
||||
if (not psu_led_device in self.pddf_obj.data.keys()):
|
||||
# Implement a generic status_led color scheme
|
||||
if self.get_powergood_status():
|
||||
return self.STATUS_LED_COLOR_GREEN
|
||||
else:
|
||||
return self.STATUS_LED_COLOR_OFF
|
||||
|
||||
device_name=self.pddf_obj.data[psu_led_device]['dev_info']['device_name']
|
||||
self.pddf_obj.create_attr('device_name', device_name, self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('index', index, self.pddf_obj.get_led_path())
|
||||
self.pddf_obj.create_attr('dev_ops', 'get_status', self.pddf_obj.get_led_path())
|
||||
color=self.pddf_obj.get_led_color()
|
||||
return (color)
|
||||
|
||||
def get_input_voltage(self):
|
||||
"""
|
||||
Retrieves current PSU input voltage
|
||||
|
||||
Returns:
|
||||
A float number, the input voltage in volts,
|
||||
e.g. 12.1
|
||||
"""
|
||||
device = "PSU{}".format(self.psu_index)
|
||||
output = self.pddf_obj.get_attr_name_output(device, "psu_v_in")
|
||||
if not output:
|
||||
return 0.0
|
||||
|
||||
v_in = output['status']
|
||||
|
||||
return float(v_in)/1000
|
||||
|
||||
def get_input_current(self):
|
||||
"""
|
||||
Retrieves present electric current supplied to the PSU
|
||||
|
||||
Returns:
|
||||
A float number, electric current in amperes,
|
||||
e.g. 15.4
|
||||
"""
|
||||
device = "PSU{}".format(self.psu_index)
|
||||
output = self.pddf_obj.get_attr_name_output(device, "psu_i_in")
|
||||
if not output:
|
||||
return 0.0
|
||||
|
||||
i_in = output['status']
|
||||
|
||||
# current in mA
|
||||
return float(i_in)/1000
|
||||
|
||||
def dump_sysfs(self):
|
||||
return self.pddf_obj.cli_dump_dsysfs('psu')
|
1390
platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_sfp.py
Executable file
1390
platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_sfp.py
Executable file
File diff suppressed because it is too large
Load Diff
174
platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_thermal.py
Executable file
174
platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddf_thermal.py
Executable file
@ -0,0 +1,174 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# All the supported Temperature Sensor SysFS aattributes are
|
||||
#- temp1_high_crit_threshold
|
||||
#- temp1_high_threshold
|
||||
#- temp1_input
|
||||
#- temp_low_threshold
|
||||
#- temp1_low_crit_threshold
|
||||
|
||||
try:
|
||||
from sonic_platform_base.thermal_base import ThermalBase
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
|
||||
class PddfThermal(ThermalBase):
|
||||
"""PDDF generic Thermal class"""
|
||||
pddf_obj = {}
|
||||
plugin_data = {}
|
||||
|
||||
def __init__(self, index, pddf_data=None, pddf_plugin_data=None):
|
||||
if not pddf_data or not pddf_plugin_data:
|
||||
raise ValueError('PDDF JSON data error')
|
||||
|
||||
self.pddf_obj = pddf_data
|
||||
self.plugin_data = pddf_plugin_data
|
||||
|
||||
self.platform = self.pddf_obj.get_platform()
|
||||
|
||||
self.thermal_index = index + 1
|
||||
self.thermal_obj_name = "TEMP{}".format(self.thermal_index)
|
||||
self.thermal_obj = self.pddf_obj.data[self.thermal_obj_name]
|
||||
|
||||
def get_name(self):
|
||||
if 'dev_attr' in self.thermal_obj.keys():
|
||||
if 'display_name' in self.thermal_obj['dev_attr']:
|
||||
return str(self.thermal_obj['dev_attr']['display_name'])
|
||||
# In case of errors
|
||||
return (self.thermal_obj_name)
|
||||
|
||||
def get_temperature(self):
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_input")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
|
||||
if output['mode']=='bmc':
|
||||
return attr_value
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
|
||||
|
||||
def get_high_threshold(self):
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_high_threshold")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
|
||||
if output['mode']=='bmc':
|
||||
return attr_value
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
|
||||
|
||||
def get_low_threshold(self):
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_low_threshold")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
|
||||
if output['mode']=='bmc':
|
||||
return attr_value
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
|
||||
|
||||
def set_high_threshold(self, temperature):
|
||||
node = self.pddf_obj.get_path(self.thermal_obj_name, "temp1_high_threshold")
|
||||
if node is None:
|
||||
print "ERROR %s does not exist"%node
|
||||
return None
|
||||
|
||||
cmd = "echo '%d' > %s"%(temperature * 1000, node)
|
||||
os.system(cmd)
|
||||
|
||||
return (True)
|
||||
|
||||
|
||||
def set_low_threshold(self, temperature):
|
||||
node = self.pddf_obj.get_path(self.thermal_obj_name, "temp1_low_threshold")
|
||||
if node is None:
|
||||
print "ERROR %s does not exist"%node
|
||||
return None
|
||||
cmd = "echo '%d' > %s"%(temperature * 1000, node)
|
||||
os.system(cmd)
|
||||
|
||||
return (True)
|
||||
|
||||
def get_high_critical_threshold(self):
|
||||
"""
|
||||
Retrieves the high critical threshold temperature of thermal
|
||||
|
||||
Returns:
|
||||
A float number, the high critical threshold temperature of thermal in Celsius
|
||||
up to nearest thousandth of one degree Celsius, e.g. 30.125
|
||||
"""
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_high_crit_threshold")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
|
||||
if output['mode']=='bmc':
|
||||
return attr_value
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
|
||||
|
||||
def get_low_critical_threshold(self):
|
||||
"""
|
||||
Retrieves the low critical threshold temperature of thermal
|
||||
|
||||
Returns:
|
||||
A float number, the low critical threshold temperature of thermal in Celsius
|
||||
up to nearest thousandth of one degree Celsius, e.g. 30.125
|
||||
"""
|
||||
output = self.pddf_obj.get_attr_name_output(self.thermal_obj_name, "temp1_low_crit_threshold")
|
||||
if not output:
|
||||
return None
|
||||
|
||||
if output['status'].isalpha():
|
||||
attr_value = None
|
||||
else:
|
||||
attr_value = float(output['status'])
|
||||
|
||||
if output['mode']=='bmc':
|
||||
return attr_value
|
||||
else:
|
||||
return (attr_value/float(1000))
|
||||
|
||||
|
||||
# Helper Functions
|
||||
def get_temp_label(self):
|
||||
if 'bmc' in self.pddf_obj.data[self.thermal_obj_name].keys():
|
||||
return None
|
||||
else:
|
||||
if self.thermal_obj_name in self.pddf_obj.data.keys():
|
||||
dev= self.pddf_obj.data[self.thermal_obj_name]
|
||||
topo_info = dev['i2c']['topo_info']
|
||||
label="%s-i2c-%d-%x" % (topo_info['dev_type'], int(topo_info['parent_bus'], 0),
|
||||
int(topo_info['dev_addr'], 0))
|
||||
return (label)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def dump_sysfs(self):
|
||||
return self.pddf_obj.cli_dump_dsysfs('temp-sensors')
|
1508
platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddfparse.py
Executable file
1508
platform/pddf/platform-api-pddf-base/sonic_platform_pddf_base/pddfparse.py
Executable file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,7 @@
|
||||
# All the derived classes for PDDF
|
||||
__all__ = ["platform", "chassis", "sfp", "psu", "thermal"]
|
||||
|
||||
# Commenting the below code as this just for the reference for the ODMs.
|
||||
# It can be uncommented when this reference code is used
|
||||
|
||||
#from sonic_platform import *
|
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#############################################################################
|
||||
# PDDF
|
||||
# Module contains an implementation of SONiC Chassis API
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
try:
|
||||
from sonic_platform_pddf_base.pddf_chassis import PddfChassis
|
||||
except ImportError as e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
class Chassis(PddfChassis):
|
||||
"""
|
||||
PDDF Platform-specific Chassis class
|
||||
"""
|
||||
|
||||
def __init__(self, pddf_data=None, pddf_plugin_data=None):
|
||||
PddfChassis.__init__(self, pddf_data, pddf_plugin_data)
|
||||
|
||||
# Provide the functions/variables below for which implementation is to be overwritten
|
@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
try:
|
||||
from sonic_platform_pddf_base.pddf_eeprom import PddfEeprom
|
||||
except ImportError, e:
|
||||
raise ImportError(str(e) + "- required module not found")
|
||||
|
||||
|
||||
class Eeprom(PddfEeprom):
|
||||
|
||||
def __init__(self, pddf_data=None, pddf_plugin_data=None):
|
||||
PddfEeprom.__init__(self, pddf_data, pddf_plugin_data)
|
||||
|
||||
# Provide the functions/variables below for which implementation is to be overwritten
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user