[platform/device] - Update Haliburton platform modules and device configuration (#1975)
* Add psuutil and sfputil support * Fixed fancontrol issue * Add sensor's label * Update haliburton platform modules
This commit is contained in:
parent
a99008356b
commit
27bdc00be3
@ -1,53 +1,53 @@
|
|||||||
# name lanes speed alias autoneg
|
# name lanes index speed alias autoneg
|
||||||
Ethernet0 2 1000 etp1 1
|
Ethernet0 2 1 1000 etp1 1
|
||||||
Ethernet1 1 1000 etp2 1
|
Ethernet1 1 2 1000 etp2 1
|
||||||
Ethernet2 4 1000 etp3 1
|
Ethernet2 4 3 1000 etp3 1
|
||||||
Ethernet3 3 1000 etp4 1
|
Ethernet3 3 4 1000 etp4 1
|
||||||
Ethernet4 6 1000 etp5 1
|
Ethernet4 6 5 1000 etp5 1
|
||||||
Ethernet5 5 1000 etp6 1
|
Ethernet5 5 6 1000 etp6 1
|
||||||
Ethernet6 8 1000 etp7 1
|
Ethernet6 8 7 1000 etp7 1
|
||||||
Ethernet7 7 1000 etp8 1
|
Ethernet7 7 8 1000 etp8 1
|
||||||
Ethernet8 10 1000 etp9 1
|
Ethernet8 10 9 1000 etp9 1
|
||||||
Ethernet9 9 1000 etp10 1
|
Ethernet9 9 10 1000 etp10 1
|
||||||
Ethernet10 12 1000 etp11 1
|
Ethernet10 12 11 1000 etp11 1
|
||||||
Ethernet11 11 1000 etp12 1
|
Ethernet11 11 12 1000 etp12 1
|
||||||
Ethernet12 14 1000 etp13 1
|
Ethernet12 14 13 1000 etp13 1
|
||||||
Ethernet13 13 1000 etp14 1
|
Ethernet13 13 14 1000 etp14 1
|
||||||
Ethernet14 16 1000 etp15 1
|
Ethernet14 16 15 1000 etp15 1
|
||||||
Ethernet15 15 1000 etp16 1
|
Ethernet15 15 16 1000 etp16 1
|
||||||
Ethernet16 18 1000 etp17 1
|
Ethernet16 18 17 1000 etp17 1
|
||||||
Ethernet17 17 1000 etp18 1
|
Ethernet17 17 18 1000 etp18 1
|
||||||
Ethernet18 20 1000 etp19 1
|
Ethernet18 20 19 1000 etp19 1
|
||||||
Ethernet19 19 1000 etp20 1
|
Ethernet19 19 20 1000 etp20 1
|
||||||
Ethernet20 22 1000 etp21 1
|
Ethernet20 22 21 1000 etp21 1
|
||||||
Ethernet21 21 1000 etp22 1
|
Ethernet21 21 22 1000 etp22 1
|
||||||
Ethernet22 24 1000 etp23 1
|
Ethernet22 24 23 1000 etp23 1
|
||||||
Ethernet23 23 1000 etp24 1
|
Ethernet23 23 24 1000 etp24 1
|
||||||
Ethernet24 26 1000 etp25 1
|
Ethernet24 26 25 1000 etp25 1
|
||||||
Ethernet25 25 1000 etp26 1
|
Ethernet25 25 26 1000 etp26 1
|
||||||
Ethernet26 28 1000 etp27 1
|
Ethernet26 28 27 1000 etp27 1
|
||||||
Ethernet27 27 1000 etp28 1
|
Ethernet27 27 28 1000 etp28 1
|
||||||
Ethernet28 30 1000 etp29 1
|
Ethernet28 30 29 1000 etp29 1
|
||||||
Ethernet29 29 1000 etp30 1
|
Ethernet29 29 30 1000 etp30 1
|
||||||
Ethernet30 32 1000 etp31 1
|
Ethernet30 32 31 1000 etp31 1
|
||||||
Ethernet31 31 1000 etp32 1
|
Ethernet31 31 32 1000 etp32 1
|
||||||
Ethernet32 34 1000 etp33 1
|
Ethernet32 34 33 1000 etp33 1
|
||||||
Ethernet33 33 1000 etp34 1
|
Ethernet33 33 34 1000 etp34 1
|
||||||
Ethernet34 36 1000 etp35 1
|
Ethernet34 36 35 1000 etp35 1
|
||||||
Ethernet35 35 1000 etp36 1
|
Ethernet35 35 36 1000 etp36 1
|
||||||
Ethernet36 38 1000 etp37 1
|
Ethernet36 38 37 1000 etp37 1
|
||||||
Ethernet37 37 1000 etp38 1
|
Ethernet37 37 38 1000 etp38 1
|
||||||
Ethernet38 40 1000 etp39 1
|
Ethernet38 40 39 1000 etp39 1
|
||||||
Ethernet39 39 1000 etp40 1
|
Ethernet39 39 40 1000 etp40 1
|
||||||
Ethernet40 42 1000 etp41 1
|
Ethernet40 42 41 1000 etp41 1
|
||||||
Ethernet41 41 1000 etp42 1
|
Ethernet41 41 42 1000 etp42 1
|
||||||
Ethernet42 44 1000 etp43 1
|
Ethernet42 44 43 1000 etp43 1
|
||||||
Ethernet43 43 1000 etp44 1
|
Ethernet43 43 44 1000 etp44 1
|
||||||
Ethernet44 46 1000 etp45 1
|
Ethernet44 46 45 1000 etp45 1
|
||||||
Ethernet45 45 1000 etp46 1
|
Ethernet45 45 46 1000 etp46 1
|
||||||
Ethernet46 48 1000 etp47 1
|
Ethernet46 48 47 1000 etp47 1
|
||||||
Ethernet47 47 1000 etp48 1
|
Ethernet47 47 48 1000 etp48 1
|
||||||
Ethernet48 54 10000 etp49 0
|
Ethernet48 54 49 10000 etp49 0
|
||||||
Ethernet49 53 10000 etp50 0
|
Ethernet49 53 50 10000 etp50 0
|
||||||
Ethernet50 56 10000 etp51 0
|
Ethernet50 56 51 10000 etp51 0
|
||||||
Ethernet51 55 10000 etp52 0
|
Ethernet51 55 52 10000 etp52 0
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
# Configuration file generated by pwmconfig, changes will be lost
|
# Configuration file generated by pwmconfig, changes will be lost
|
||||||
INTERVAL=2
|
INTERVAL=2
|
||||||
DEVPATH=hwmon3=devices/pci0000:00/0000:00:13.0/i2c-0/i2c-8/i2c-23/23-004d/ hwmon2=devices/pci0000:00/0000:00:13.0/i2c-0/i2c-8/i2c-11/11-001a/hwmon/hwmon2
|
DEVPATH=hwmon3=devices/pci0000:00/0000:00:13.0/i2c-0/i2c-8/i2c-23/23-004d hwmon2=devices/pci0000:00/0000:00:13.0/i2c-0/i2c-8/i2c-11/11-001a
|
||||||
DEVNAME=hwmon3=emc2305 hwmon2=max6697
|
DEVNAME=hwmon3=emc2305 hwmon2=max6697
|
||||||
FCTEMPS=hwmon3/pwm1=hwmon2/temp2_input hwmon3/pwm2=hwmon2/temp2_input hwmon3/pwm4=hwmon2/temp2_input
|
FCTEMPS=hwmon3/device/pwm1=hwmon2/temp2_input hwmon3/device/pwm2=hwmon2/temp2_input hwmon3/device/pwm4=hwmon2/temp2_input
|
||||||
FCFANS=hwmon3/device/pwm1=hwmon3/device/fan1_input hwmon3/device/pwm2=hwmon3/device/fan2_input hwmon3/device/pwm4=hwmon3/device/fan4_input
|
FCFANS=hwmon3/device/pwm1=hwmon3/device/fan1_input hwmon3/device/pwm2=hwmon3/device/fan2_input hwmon3/device/pwm4=hwmon3/device/fan4_input
|
||||||
MINTEMP=hwmon3/device/pwm1=29 hwmon3/device/pwm2=29 hwmon3/device/pwm4=29
|
MINTEMP=hwmon3/device/pwm1=29 hwmon3/device/pwm2=29 hwmon3/device/pwm4=29
|
||||||
MAXTEMP=hwmon3/device/pwm1=44 hwmon3/device/pwm2=44 hwmon3/device/pwm4=44
|
MAXTEMP=hwmon3/device/pwm1=44 hwmon3/device/pwm2=44 hwmon3/device/pwm4=44
|
||||||
MINSTART=hwmon3/device/pwm1=102 hwmon3/device/pwm2=102 hwmon3/device/pwm4=102
|
MINSTART=hwmon3/device/pwm1=102 hwmon3/device/pwm2=102 hwmon3/device/pwm4=102
|
||||||
MINSTOP=hwmon3/device/pwm1=102 hwmon3/device/pwm2=102 hwmon3/device/pwm4=102
|
MINSTOP=hwmon3/device/pwm1=102 hwmon3/device/pwm2=102 hwmon3/device/pwm4=102
|
||||||
MINPWM=hwmon3/device/pwm1=102 hwmon3/device/pwm2=102 hwmon3/device/pwm4=102
|
MINPWM=hwmon3/device/pwm1=102 hwmon3/device/pwm2=102 hwmon3/device/pwm4=102
|
||||||
MAXPWM=hwmon3/device/pwm1=255 hwmon3/device/pwm2=255 hwmon3/device/pwm4=255
|
MAXPWM=hwmon3/device/pwm1=255 hwmon3/device/pwm2=255 hwmon3/device/pwm4=255
|
||||||
|
61
device/celestica/x86_64-cel_e1031-r0/plugins/psuutil.py
Normal file
61
device/celestica/x86_64-cel_e1031-r0/plugins/psuutil.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
try:
|
||||||
|
from sonic_psu.psu_base import PsuBase
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
|
||||||
|
class PsuUtil(PsuBase):
|
||||||
|
"""Platform-specific PSUutil class"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
PsuBase.__init__(self)
|
||||||
|
|
||||||
|
self.psu_path = "/sys/devices/platform/e1031.smc/"
|
||||||
|
self.psu_presence = "psu{}_prs"
|
||||||
|
self.psu_oper_status = "psu{}_status"
|
||||||
|
|
||||||
|
def get_num_psus(self):
|
||||||
|
"""
|
||||||
|
Retrieves the number of PSUs available on the device
|
||||||
|
|
||||||
|
:return: An integer, the number of PSUs available on the device
|
||||||
|
"""
|
||||||
|
return 2
|
||||||
|
|
||||||
|
def get_psu_status(self, index):
|
||||||
|
"""
|
||||||
|
Retrieves the oprational status of power supply unit (PSU) defined by 1-based index <index>
|
||||||
|
|
||||||
|
:param index: An integer, 1-based index of the PSU of which to query status
|
||||||
|
:return: Boolean, True if PSU is operating properly, False if PSU is faulty
|
||||||
|
"""
|
||||||
|
psu_location = ["R", "L"]
|
||||||
|
status = 0
|
||||||
|
try:
|
||||||
|
with open(self.psu_path + self.psu_oper_status.format(psu_location[index - 1]), 'r') as power_status:
|
||||||
|
status = int(power_status.read())
|
||||||
|
except IOError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return status == 1
|
||||||
|
|
||||||
|
def get_psu_presence(self, index):
|
||||||
|
"""
|
||||||
|
Retrieves the presence status of power supply unit (PSU) defined by 1-based index <index>
|
||||||
|
|
||||||
|
:param index: An integer, 1-based index of the PSU of which to query status
|
||||||
|
:return: Boolean, True if PSU is plugged, False if not
|
||||||
|
"""
|
||||||
|
psu_location = ["R", "L"]
|
||||||
|
status = 0
|
||||||
|
try:
|
||||||
|
with open(self.psu_path + self.psu_presence.format(psu_location[index - 1]), 'r') as psu_prs:
|
||||||
|
status = int(psu_prs.read())
|
||||||
|
except IOError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return status == 1
|
123
device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py
Normal file
123
device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
try:
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
from sonic_sfp.sfputilbase import SfpUtilBase
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError("%s - required module not found" % str(e))
|
||||||
|
|
||||||
|
|
||||||
|
class SfpUtil(SfpUtilBase):
|
||||||
|
"""Platform-specific SfpUtil class"""
|
||||||
|
|
||||||
|
PORT_START = 1
|
||||||
|
PORT_END = 52
|
||||||
|
port_to_i2c_mapping = {
|
||||||
|
1 : None,
|
||||||
|
2 : None,
|
||||||
|
3 : None,
|
||||||
|
4 : None,
|
||||||
|
5 : None,
|
||||||
|
6 : None,
|
||||||
|
7 : None,
|
||||||
|
8 : None,
|
||||||
|
9 : None,
|
||||||
|
10 : None,
|
||||||
|
11 : None,
|
||||||
|
12 : None,
|
||||||
|
13 : None,
|
||||||
|
14 : None,
|
||||||
|
15 : None,
|
||||||
|
16 : None,
|
||||||
|
17 : None,
|
||||||
|
18 : None,
|
||||||
|
19 : None,
|
||||||
|
20 : None,
|
||||||
|
21 : None,
|
||||||
|
22 : None,
|
||||||
|
23 : None,
|
||||||
|
24 : None,
|
||||||
|
25 : None,
|
||||||
|
26 : None,
|
||||||
|
27 : None,
|
||||||
|
28 : None,
|
||||||
|
29 : None,
|
||||||
|
30 : None,
|
||||||
|
31 : None,
|
||||||
|
32 : None,
|
||||||
|
33 : None,
|
||||||
|
34 : None,
|
||||||
|
35 : None,
|
||||||
|
36 : None,
|
||||||
|
37 : None,
|
||||||
|
38 : None,
|
||||||
|
39 : None,
|
||||||
|
40 : None,
|
||||||
|
41 : None,
|
||||||
|
42 : None,
|
||||||
|
43 : None,
|
||||||
|
44 : None,
|
||||||
|
45 : None,
|
||||||
|
46 : None,
|
||||||
|
47 : None,
|
||||||
|
48 : None,
|
||||||
|
49 : 15,
|
||||||
|
50 : 14,
|
||||||
|
51 : 17,
|
||||||
|
52 : 16
|
||||||
|
}
|
||||||
|
_port_to_eeprom_mapping = {}
|
||||||
|
_sfp_port = range(49, PORT_END + 1)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def port_start(self):
|
||||||
|
return self.PORT_START
|
||||||
|
|
||||||
|
@property
|
||||||
|
def port_end(self):
|
||||||
|
return self.PORT_END
|
||||||
|
|
||||||
|
@property
|
||||||
|
def qsfp_ports(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def port_to_eeprom_mapping(self):
|
||||||
|
return self._port_to_eeprom_mapping
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
# Override port_to_eeprom_mapping for class initialization
|
||||||
|
eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'
|
||||||
|
for x in range(self.PORT_START, self.PORT_END + 1):
|
||||||
|
port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x])
|
||||||
|
self.port_to_eeprom_mapping[x] = port_eeprom_path
|
||||||
|
SfpUtilBase.__init__(self)
|
||||||
|
|
||||||
|
def get_presence(self, port_num):
|
||||||
|
sfp_modabs_path = '/sys/devices/platform/e1031.smc/SFP/SFP{0}/sfp_modabs'
|
||||||
|
|
||||||
|
if port_num not in self._sfp_port:
|
||||||
|
return False
|
||||||
|
|
||||||
|
status = 1
|
||||||
|
try:
|
||||||
|
with open(sfp_modabs_path.format(port_num - 48), 'r') as port_status:
|
||||||
|
status = int(port_status.read())
|
||||||
|
except IOError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return status == 0
|
||||||
|
|
||||||
|
|
||||||
|
def get_low_power_mode(self, port_num):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def set_low_power_mode(self, port_num, lpmode):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def reset(self, port_num):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_transceiver_change_event(self):
|
||||||
|
raise NotImplementedError
|
@ -1,12 +1,33 @@
|
|||||||
# libsensors configuration file for Celestica DX010.
|
# libsensors configuration file for Celestica E1031.
|
||||||
# The i2c bus portion is omit because adapter name
|
# The i2c bus portion is omit because adapter name
|
||||||
# changes every time when system boot up.
|
# changes every time when system boot up.
|
||||||
|
|
||||||
chip "max6697-i2c-*-1a"
|
bus "i2c-3" "i2c-0-mux (chan_id 1)"
|
||||||
label temp1 "temp sensor 1"
|
bus "i2c-11" "i2c-8-mux (chan_id 1)"
|
||||||
label temp2 "temp sensor 2"
|
|
||||||
label temp3 "temp sensor 3"
|
chip "max6697-i2c-3-1a"
|
||||||
label temp4 "temp sensor 4"
|
label temp1 "CPU board temperature sensor : 1"
|
||||||
label temp5 "temp sensor 5"
|
label temp2 "CPU board temperature sensor : 2"
|
||||||
ignore temp6
|
label temp3 "CPU board temperature sensor : 3"
|
||||||
ignore temp7
|
ignore temp4
|
||||||
|
ignore temp5
|
||||||
|
ignore temp6
|
||||||
|
ignore temp7
|
||||||
|
|
||||||
|
chip "max6697-i2c-11-1a"
|
||||||
|
label temp1 "Main board temperature sensor : 1"
|
||||||
|
label temp2 "Main board temperature sensor : 2"
|
||||||
|
label temp3 "Main board temperature sensor : 3"
|
||||||
|
label temp4 "Main board temperature sensor : 4"
|
||||||
|
label temp5 "Main board temperature sensor : 5"
|
||||||
|
ignore temp6
|
||||||
|
ignore temp7
|
||||||
|
|
||||||
|
|
||||||
|
chip "emc2305-i2c-*-4d"
|
||||||
|
ignore fan3
|
||||||
|
ignore fan5
|
||||||
|
label fan4 "Fan 1 :"
|
||||||
|
label fan2 "Fan 2 :"
|
||||||
|
label fan1 "Fan 3 :"
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Celestica DX010 and Haliburton Platform modules
|
# Celestica DX010 and Haliburton Platform modules
|
||||||
|
|
||||||
CEL_DX010_PLATFORM_MODULE_VERSION = 0.8
|
CEL_DX010_PLATFORM_MODULE_VERSION = 0.9
|
||||||
CEL_HALIBURTON_PLATFORM_MODULE_VERSION = 0.8
|
CEL_HALIBURTON_PLATFORM_MODULE_VERSION = 0.9
|
||||||
|
|
||||||
export CEL_DX010_PLATFORM_MODULE_VERSION
|
export CEL_DX010_PLATFORM_MODULE_VERSION
|
||||||
export CEL_HALIBURTON_PLATFORM_MODULE_VERSION
|
export CEL_HALIBURTON_PLATFORM_MODULE_VERSION
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
|
sonic-cel-platform-modules (0.9) unstable; urgency=low
|
||||||
|
|
||||||
|
* Add haliburton platform module.
|
||||||
|
|
||||||
|
-- Wirut Getbamrung <wgetbumr@celestica.com> Fri, 17 Aug 2018 10:10:10 +0700
|
||||||
|
|
||||||
sonic-cel-platform-modules (0.8) unstable; urgency=low
|
sonic-cel-platform-modules (0.8) unstable; urgency=low
|
||||||
|
|
||||||
* Add haliburton platform
|
* Add dx010 platform fan led control.
|
||||||
|
* The platform gpio init moved to kernel space.
|
||||||
|
|
||||||
-- Supakit Fuangkaew <sfuangk@celestica.com> Thu, 5 Apr 2018 09:09:09 +0700
|
-- Pradchaya Phucharoen <pphuchar@celestica.com> Mon, 1 Jul 2018 11:09:13 +0700
|
||||||
|
|
||||||
sonic-cel-platform-modules (0.7) unstable; urgency=low
|
sonic-cel-platform-modules (0.7) unstable; urgency=low
|
||||||
|
|
||||||
|
@ -15,10 +15,8 @@ case "$1" in
|
|||||||
start)
|
start)
|
||||||
echo -n "Setting up board... "
|
echo -n "Setting up board... "
|
||||||
|
|
||||||
depmod -a
|
modprobe smc
|
||||||
modprobe i2c-dev
|
|
||||||
modprobe i2c-mux-pca954x
|
|
||||||
|
|
||||||
found=0
|
found=0
|
||||||
for devnum in 0 1; do
|
for devnum in 0 1; do
|
||||||
devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name`
|
devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name`
|
||||||
@ -56,15 +54,11 @@ start)
|
|||||||
# Attach fans
|
# Attach fans
|
||||||
echo emc2305 0x4d > /sys/bus/i2c/devices/i2c-23/new_device
|
echo emc2305 0x4d > /sys/bus/i2c/devices/i2c-23/new_device
|
||||||
|
|
||||||
# Attach PSUs
|
# Attach 4 SFP+ Uplink
|
||||||
echo dps200 0x5a > /sys/bus/i2c/devices/i2c-12/new_device
|
echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-14/new_device
|
||||||
echo dps200 0x5b > /sys/bus/i2c/devices/i2c-13/new_device
|
echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-15/new_device
|
||||||
|
echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-16/new_device
|
||||||
# Attach 4 SFP+ Uplink
|
echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-17/new_device
|
||||||
echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-14/new_device
|
|
||||||
echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-15/new_device
|
|
||||||
echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-16/new_device
|
|
||||||
echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-17/new_device
|
|
||||||
|
|
||||||
echo "done."
|
echo "done."
|
||||||
;;
|
;;
|
||||||
|
@ -1 +1,2 @@
|
|||||||
haliburton/cfg/haliburton-modules.conf etc/modules-load.d
|
haliburton/cfg/haliburton-modules.conf etc/modules-load.d
|
||||||
|
haliburton/systemd/platform-modules-haliburton.service lib/systemd/system
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
depmod -a
|
||||||
|
systemctl enable platform-modules-haliburton.service
|
||||||
|
systemctl start platform-modules-haliburton.service
|
@ -1 +1 @@
|
|||||||
obj-m := mc24lc64t.o emc2305.o
|
obj-m := mc24lc64t.o emc2305.o smc.o
|
||||||
|
@ -0,0 +1,777 @@
|
|||||||
|
/*
|
||||||
|
* smc.c - The CPLD driver for E1031 System Management.
|
||||||
|
* The driver implement sysfs to access CPLD register on the E1031 via LPC bus.
|
||||||
|
* Copyright (C) 2018 Celestica Corp.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/dmi.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/hwmon-sysfs.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/leds.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/stddef.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <uapi/linux/stat.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define DRIVER_NAME "e1031.smc"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CPLD register address for read and write.
|
||||||
|
*/
|
||||||
|
#define VERSION 0x0200
|
||||||
|
#define SCRATCH 0x0201
|
||||||
|
#define BROAD_ID 0x0202
|
||||||
|
|
||||||
|
/* SEPERATE RESET
|
||||||
|
* [7:5] RESERVED
|
||||||
|
* [4] RESET PCIE
|
||||||
|
* [3] RESET USBHUB
|
||||||
|
* [2] RESET B50282
|
||||||
|
* [1] RESET PCA9548
|
||||||
|
* [0] RESET BCM54616
|
||||||
|
* 1: not reset, 0: reset
|
||||||
|
*/
|
||||||
|
#define SPR_RESET 0x0222
|
||||||
|
|
||||||
|
/* PSU STATUS
|
||||||
|
* [7] PSUR_ACOK
|
||||||
|
* [6] PSUR_PWOK
|
||||||
|
* [5] PSUR_ALRT
|
||||||
|
* [4] PSUR_PRS
|
||||||
|
* [3] PSUL_ACOK
|
||||||
|
* [2] PSUL_PWOK
|
||||||
|
* [1] PSUL_ALRT
|
||||||
|
* [0] PSUL_PRS
|
||||||
|
*/
|
||||||
|
#define PSU_STAT 0x0204
|
||||||
|
#define PSUR_ACOK 7
|
||||||
|
#define PSUR_PWOK 6
|
||||||
|
#define PSUR_ALRT 5
|
||||||
|
#define PSUR_PRS 4
|
||||||
|
#define PSUL_ACOK 3
|
||||||
|
#define PSUL_PWOK 2
|
||||||
|
#define PSUL_ALRT 1
|
||||||
|
#define PSUL_PRS 0
|
||||||
|
|
||||||
|
/* FAN LED CTRL
|
||||||
|
* [7:3] RESERVED
|
||||||
|
* [2:0] LED CTRL
|
||||||
|
*/
|
||||||
|
#define FAN_LED_1 0x0205
|
||||||
|
#define FAN_LED_2 0x0206
|
||||||
|
#define FAN_LED_3 0x0207
|
||||||
|
|
||||||
|
enum FAN_LED {
|
||||||
|
fan_led_grn = 0,
|
||||||
|
fan_led_grn_bnk,
|
||||||
|
fan_led_amb,
|
||||||
|
fan_led_amb_bnk,
|
||||||
|
fan_led_off
|
||||||
|
} fan_led;
|
||||||
|
|
||||||
|
#define LED_OPMOD 0x0208
|
||||||
|
#define LED_TEST 0x0209
|
||||||
|
|
||||||
|
/* SYSTEM LED
|
||||||
|
* [7:4] RESERVED
|
||||||
|
* [3:2] STATUS LED
|
||||||
|
* [1:0] MASTER LED
|
||||||
|
*/
|
||||||
|
#define LED_FPS 0x020a
|
||||||
|
|
||||||
|
enum STAT_LED {
|
||||||
|
stat_led_off = 0,
|
||||||
|
stat_led_grn,
|
||||||
|
stat_led_grn_bnk
|
||||||
|
} stat_led;
|
||||||
|
|
||||||
|
enum MASTER_LED {
|
||||||
|
master_led_off = 0,
|
||||||
|
master_led_grn,
|
||||||
|
master_led_amb
|
||||||
|
} master_led;
|
||||||
|
|
||||||
|
/* FAN DIRECTION STAT
|
||||||
|
* [7:4] RESERVED
|
||||||
|
* [3] USB HUB STAT
|
||||||
|
* [2:0] FAN_DIR
|
||||||
|
*/
|
||||||
|
#define DEV_STAT 0x020c
|
||||||
|
#define FAN_3 2
|
||||||
|
#define FAN_2 1
|
||||||
|
#define FAN_1 0
|
||||||
|
|
||||||
|
/* SFP PORT STATUS
|
||||||
|
* [7:4] RESERVED
|
||||||
|
* [3:0] TX_FAULT / MODABS / RXLOS
|
||||||
|
*/
|
||||||
|
#define SFP_TXFAULT 0x0242
|
||||||
|
#define SFP_MODABS 0x0243
|
||||||
|
#define SFP_RXLOS 0x0244
|
||||||
|
|
||||||
|
/* SFP PORT CTRL
|
||||||
|
* [7:4] RATE SEL (RS0/RS1)
|
||||||
|
* [3:0] TX_DIS
|
||||||
|
*/
|
||||||
|
#define SFP_TXCTRL 0x0255
|
||||||
|
|
||||||
|
struct cpld_data {
|
||||||
|
struct mutex cpld_lock;
|
||||||
|
uint16_t read_addr;
|
||||||
|
struct device *fpp_node;
|
||||||
|
struct device *sfp_devices[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sfp_device_data {
|
||||||
|
int portid;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct class *celplatform;
|
||||||
|
struct cpld_data *cpld_data;
|
||||||
|
|
||||||
|
struct index_device_attribute {
|
||||||
|
struct device_attribute dev_attr;
|
||||||
|
int index;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t scratch_show(struct device *dev, struct device_attribute *devattr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
unsigned char data = 0;
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(SCRATCH);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return sprintf(buf, "0x%2.2x\n", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t scratch_store(struct device *dev, struct device_attribute *devattr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
unsigned long data;
|
||||||
|
char *last;
|
||||||
|
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = (uint16_t)strtoul(buf, &last, 16);
|
||||||
|
if (data == 0 && buf == last) {
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
outb(data, SCRATCH);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
len = sprintf(buf, "0x%2.2x\n", inb(VERSION));
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t getreg_store(struct device *dev, struct device_attribute *devattr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
uint16_t addr;
|
||||||
|
char *last;
|
||||||
|
|
||||||
|
addr = (uint16_t)strtoul(buf, &last, 16);
|
||||||
|
if (addr == 0 && buf == last) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
cpld_data->read_addr = addr;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t getreg_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
len = sprintf(buf, "0x%2.2x\n", inb(cpld_data->read_addr));
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t setreg_store(struct device *dev, struct device_attribute *devattr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
uint16_t addr;
|
||||||
|
uint8_t value;
|
||||||
|
char *tok;
|
||||||
|
char clone[count];
|
||||||
|
char *pclone = clone;
|
||||||
|
char *last;
|
||||||
|
|
||||||
|
strcpy(clone, buf);
|
||||||
|
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
tok = strsep((char**)&pclone, " ");
|
||||||
|
if (tok == NULL) {
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
addr = (uint16_t)strtoul(tok, &last, 16);
|
||||||
|
if (addr == 0 && tok == last) {
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tok = strsep((char**)&pclone, " ");
|
||||||
|
if (tok == NULL) {
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
value = (uint8_t)strtoul(tok, &last, 16);
|
||||||
|
if (value == 0 && tok == last) {
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
outb(value, addr);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show status led
|
||||||
|
* @param dev kernel device
|
||||||
|
* @param devattr kernel device attribute
|
||||||
|
* @param buf buffer for get value
|
||||||
|
* @return led state - off/on/blink
|
||||||
|
*/
|
||||||
|
static ssize_t status_led_show(struct device *dev, struct device_attribute *devattr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
unsigned char data = 0;
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(LED_FPS);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
data = data & 0xc;
|
||||||
|
return sprintf(buf, "%s\n",
|
||||||
|
data == stat_led_grn ? "on" : data == stat_led_grn_bnk ? "blink" : "off");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the status led
|
||||||
|
* @param dev kernel device
|
||||||
|
* @param devattr kernel device attribute
|
||||||
|
* @param buf buffer of set value - off/on/blink
|
||||||
|
* @param count number of bytes in buffer
|
||||||
|
* @return number of bytes written, or error code < 0.
|
||||||
|
*/
|
||||||
|
static ssize_t status_led_store(struct device *dev, struct device_attribute *devattr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
unsigned char led_status, data;
|
||||||
|
|
||||||
|
if (sysfs_streq(buf, "off")) {
|
||||||
|
led_status = stat_led_off;
|
||||||
|
} else if (sysfs_streq(buf, "on")) {
|
||||||
|
led_status = stat_led_grn;
|
||||||
|
} else if (sysfs_streq(buf, "blink")) {
|
||||||
|
led_status = stat_led_grn_bnk;
|
||||||
|
} else {
|
||||||
|
count = -EINVAL;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(LED_FPS);
|
||||||
|
data = data & ~(0xc);
|
||||||
|
data = data | ( led_status << 2 );
|
||||||
|
outb(data, LED_FPS);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show master led
|
||||||
|
* @param dev kernel device
|
||||||
|
* @param devattr kernel device attribute
|
||||||
|
* @param buf buffer for get value
|
||||||
|
* @return led state - off/green/amber
|
||||||
|
*/
|
||||||
|
static ssize_t master_led_show(struct device *dev, struct device_attribute *devattr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
unsigned char data = 0;
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(LED_FPS);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
data = data & 0x3;
|
||||||
|
return sprintf(buf, "%s\n",
|
||||||
|
data == master_led_grn ? "on" : data == master_led_amb ? "amber" : "off");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the master led
|
||||||
|
* @param dev kernel device
|
||||||
|
* @param devattr kernel device attribute
|
||||||
|
* @param buf buffer of set value - off/green/amber
|
||||||
|
* @param count number of bytes in buffer
|
||||||
|
* @return number of bytes written, or error code < 0.
|
||||||
|
*/
|
||||||
|
static ssize_t master_led_store(struct device *dev, struct device_attribute *devattr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
unsigned char led_status, data;
|
||||||
|
|
||||||
|
if (sysfs_streq(buf, "off")) {
|
||||||
|
led_status = master_led_off;
|
||||||
|
} else if (sysfs_streq(buf, "green")) {
|
||||||
|
led_status = master_led_grn;
|
||||||
|
} else if (sysfs_streq(buf, "amber")) {
|
||||||
|
led_status = master_led_amb;
|
||||||
|
} else {
|
||||||
|
count = -EINVAL;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(LED_FPS);
|
||||||
|
data = data & ~(0x3);
|
||||||
|
data = data | led_status;
|
||||||
|
outb(data, LED_FPS);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t psuL_prs_show(struct device *dev, struct device_attribute *devattr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
unsigned char data = 0;
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(PSU_STAT);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return sprintf(buf, "%d\n", ~(data >> PSUL_PRS) & 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t psuR_prs_show(struct device *dev, struct device_attribute *devattr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
unsigned char data = 0;
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(PSU_STAT);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return sprintf(buf, "%d\n", ~(data >> PSUR_PRS) & 1U);
|
||||||
|
}
|
||||||
|
static DEVICE_ATTR_RO(psuR_prs);
|
||||||
|
|
||||||
|
static ssize_t psuL_status_show(struct device *dev, struct device_attribute *devattr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
unsigned char data = 0;
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(PSU_STAT);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
data = ( data >> PSUL_PWOK ) & 0x3;
|
||||||
|
return sprintf(buf, "%d\n", data == 0x3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t psuR_status_show(struct device *dev, struct device_attribute *devattr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
unsigned char data = 0;
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(PSU_STAT);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
data = ( data >> PSUR_PWOK ) & 0x3;
|
||||||
|
return sprintf(buf, "%d\n", data == 0x3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ssize_t fan_dir_show(struct device *dev, struct device_attribute *devattr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr);
|
||||||
|
int index = sa->index;
|
||||||
|
unsigned char data = 0;
|
||||||
|
|
||||||
|
// Use index to determind the status bit
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(DEV_STAT);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
data = ( data >> index ) & 1U;
|
||||||
|
return sprintf(buf, "%s\n", data ? "B2F" : "F2B" );
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t sfp_txfault_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned char data;
|
||||||
|
struct sfp_device_data *dev_data = dev_get_drvdata(dev);
|
||||||
|
unsigned int port_bit = dev_data->portid - 1;
|
||||||
|
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(SFP_TXFAULT);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return sprintf(buf, "%d\n", (data >> port_bit ) & 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t sfp_modabs_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned char data;
|
||||||
|
struct sfp_device_data *dev_data = dev_get_drvdata(dev);
|
||||||
|
unsigned int port_bit = dev_data->portid - 1;
|
||||||
|
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(SFP_MODABS);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return sprintf(buf, "%d\n", (data >> port_bit ) & 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t sfp_rxlos_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned char data;
|
||||||
|
struct sfp_device_data *dev_data = dev_get_drvdata(dev);
|
||||||
|
unsigned int port_bit = dev_data->portid - 1;
|
||||||
|
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(SFP_RXLOS);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return sprintf(buf, "%d\n", (data >> port_bit ) & 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t sfp_txdis_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned char data;
|
||||||
|
struct sfp_device_data *dev_data = dev_get_drvdata(dev);
|
||||||
|
unsigned int port_bit = dev_data->portid - 1;
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(SFP_TXCTRL);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return sprintf(buf, "%d\n", (data >> port_bit ) & 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t sfp_txdis_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||||
|
{
|
||||||
|
long value;
|
||||||
|
ssize_t status;
|
||||||
|
unsigned char data;
|
||||||
|
struct sfp_device_data *dev_data = dev_get_drvdata(dev);
|
||||||
|
unsigned int port_bit = dev_data->portid - 1;
|
||||||
|
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
status = kstrtol(buf, 0, &value);
|
||||||
|
if (status == 0) {
|
||||||
|
// check if value is 0, clear
|
||||||
|
data = inb(SFP_TXCTRL);
|
||||||
|
if (!value)
|
||||||
|
data = data & ~( 1U << port_bit);
|
||||||
|
else
|
||||||
|
data = data | ( 1U << port_bit);
|
||||||
|
outb(data, SFP_TXCTRL);
|
||||||
|
status = size;
|
||||||
|
}
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t sfp_rs_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
unsigned char data;
|
||||||
|
struct sfp_device_data *dev_data = dev_get_drvdata(dev);
|
||||||
|
unsigned int port_bit = dev_data->portid - 1;
|
||||||
|
|
||||||
|
// High nibble
|
||||||
|
port_bit = port_bit + 4;
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(SFP_TXCTRL);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return sprintf(buf, "%d\n", (data >> port_bit ) & 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t sfp_rs_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
|
||||||
|
{
|
||||||
|
long value;
|
||||||
|
ssize_t status;
|
||||||
|
unsigned char data;
|
||||||
|
struct sfp_device_data *dev_data = dev_get_drvdata(dev);
|
||||||
|
unsigned int port_bit = dev_data->portid - 1;
|
||||||
|
|
||||||
|
// High nibble
|
||||||
|
port_bit = port_bit + 4;
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
status = kstrtol(buf, 0, &value);
|
||||||
|
if (status == 0) {
|
||||||
|
// check if value is 0, clear
|
||||||
|
data = inb(SFP_TXCTRL);
|
||||||
|
if (!value)
|
||||||
|
data = data & ~( 1U << port_bit);
|
||||||
|
else
|
||||||
|
data = data | ( 1U << port_bit);
|
||||||
|
outb(data, SFP_TXCTRL);
|
||||||
|
status = size;
|
||||||
|
}
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t fan_led_show(struct device *dev, struct device_attribute *devattr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr);
|
||||||
|
int index = sa->index;
|
||||||
|
unsigned char data = 0;
|
||||||
|
char *led_str[5] = {"green", "green-blink", "amber", "amber-blink", "off"};
|
||||||
|
|
||||||
|
// Use index to determind the status bit
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
data = inb(FAN_LED_1 + index);
|
||||||
|
data = data & 0x7;
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return sprintf(buf, "%s\n", led_str[data]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t fan_led_store(struct device *dev, struct device_attribute *devattr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct sensor_device_attribute *sa = to_sensor_dev_attr(devattr);
|
||||||
|
int index = sa->index;
|
||||||
|
unsigned char led_status = 0;
|
||||||
|
|
||||||
|
if (sysfs_streq(buf, "off")) {
|
||||||
|
led_status = fan_led_off;
|
||||||
|
} else if (sysfs_streq(buf, "green")) {
|
||||||
|
led_status = fan_led_grn;
|
||||||
|
} else if (sysfs_streq(buf, "amber")) {
|
||||||
|
led_status = fan_led_amb;
|
||||||
|
} else if (sysfs_streq(buf, "green-blink")) {
|
||||||
|
led_status = fan_led_grn_bnk;
|
||||||
|
} else if (sysfs_streq(buf, "amber-blink")) {
|
||||||
|
led_status = fan_led_amb_bnk;
|
||||||
|
} else {
|
||||||
|
count = -EINVAL;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
mutex_lock(&cpld_data->cpld_lock);
|
||||||
|
outb(led_status, FAN_LED_1 + index);
|
||||||
|
mutex_unlock(&cpld_data->cpld_lock);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR_RO(version);
|
||||||
|
static DEVICE_ATTR_RW(scratch);
|
||||||
|
static DEVICE_ATTR_RW(getreg);
|
||||||
|
static DEVICE_ATTR_WO(setreg);
|
||||||
|
static DEVICE_ATTR_RW(status_led);
|
||||||
|
static DEVICE_ATTR_RW(master_led);
|
||||||
|
static DEVICE_ATTR_RO(psuL_prs);
|
||||||
|
static DEVICE_ATTR_RO(psuL_status);
|
||||||
|
static DEVICE_ATTR_RO(psuR_status);
|
||||||
|
static DEVICE_ATTR_RO(sfp_txfault);
|
||||||
|
static DEVICE_ATTR_RO(sfp_modabs);
|
||||||
|
static DEVICE_ATTR_RO(sfp_rxlos);
|
||||||
|
static DEVICE_ATTR_RW(sfp_txdis);
|
||||||
|
static DEVICE_ATTR_RW(sfp_rs);
|
||||||
|
static SENSOR_DEVICE_ATTR(fan1_dir, S_IRUGO, fan_dir_show, NULL, FAN_1);
|
||||||
|
static SENSOR_DEVICE_ATTR(fan2_dir, S_IRUGO, fan_dir_show, NULL, FAN_2);
|
||||||
|
static SENSOR_DEVICE_ATTR(fan3_dir, S_IRUGO, fan_dir_show, NULL, FAN_3);
|
||||||
|
static SENSOR_DEVICE_ATTR(fan1_led, S_IWUSR | S_IRUGO, fan_led_show, fan_led_store, FAN_1);
|
||||||
|
static SENSOR_DEVICE_ATTR(fan2_led, S_IWUSR | S_IRUGO, fan_led_show, fan_led_store, FAN_2);
|
||||||
|
static SENSOR_DEVICE_ATTR(fan3_led, S_IWUSR | S_IRUGO, fan_led_show, fan_led_store, FAN_3);
|
||||||
|
|
||||||
|
static struct attribute *cpld_attrs[] = {
|
||||||
|
&dev_attr_version.attr,
|
||||||
|
&dev_attr_scratch.attr,
|
||||||
|
&dev_attr_getreg.attr,
|
||||||
|
&dev_attr_setreg.attr,
|
||||||
|
// LEDs
|
||||||
|
&dev_attr_status_led.attr,
|
||||||
|
&dev_attr_master_led.attr,
|
||||||
|
// PSUs
|
||||||
|
&dev_attr_psuL_prs.attr,
|
||||||
|
&dev_attr_psuR_prs.attr,
|
||||||
|
&dev_attr_psuL_status.attr,
|
||||||
|
&dev_attr_psuR_status.attr,
|
||||||
|
// FANs
|
||||||
|
&sensor_dev_attr_fan1_dir.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_fan2_dir.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_fan3_dir.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_fan1_led.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_fan2_led.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_fan3_led.dev_attr.attr,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute_group cpld_group = {
|
||||||
|
.attrs = cpld_attrs,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute *sfp_attrs[] = {
|
||||||
|
// SFP
|
||||||
|
&dev_attr_sfp_txfault.attr,
|
||||||
|
&dev_attr_sfp_modabs.attr,
|
||||||
|
&dev_attr_sfp_rxlos.attr,
|
||||||
|
&dev_attr_sfp_txdis.attr,
|
||||||
|
&dev_attr_sfp_rs.attr,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
ATTRIBUTE_GROUPS(sfp);
|
||||||
|
|
||||||
|
static struct resource cpld_resources[] = {
|
||||||
|
{
|
||||||
|
.start = 0x0200,
|
||||||
|
.end = 0x0255,
|
||||||
|
.flags = IORESOURCE_IO,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct device * sfp_init(int portid) {
|
||||||
|
struct sfp_device_data *new_data;
|
||||||
|
struct device *new_device;
|
||||||
|
|
||||||
|
new_data = kzalloc(sizeof(*new_data), GFP_KERNEL);
|
||||||
|
if (!new_data) {
|
||||||
|
printk(KERN_ALERT "Cannot alloc sff device data @port%d", portid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* Front panel port ID start from 1 */
|
||||||
|
new_data->portid = portid + 1;
|
||||||
|
new_device = device_create_with_groups(celplatform, cpld_data->fpp_node, MKDEV(0, 0), new_data, sfp_groups, "SFP%d", new_data->portid);
|
||||||
|
if (IS_ERR(new_device)) {
|
||||||
|
printk(KERN_ALERT "Cannot create sff device @port%d", portid);
|
||||||
|
kfree(new_data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return new_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpld_dev_release( struct device * dev)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_device cpld_dev = {
|
||||||
|
.name = DRIVER_NAME,
|
||||||
|
.id = -1,
|
||||||
|
.num_resources = ARRAY_SIZE(cpld_resources),
|
||||||
|
.resource = cpld_resources,
|
||||||
|
.dev = {
|
||||||
|
.release = cpld_dev_release,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int cpld_drv_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct resource *res;
|
||||||
|
int err, i = 0;
|
||||||
|
|
||||||
|
cpld_data = devm_kzalloc(&pdev->dev, sizeof(struct cpld_data),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!cpld_data)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
mutex_init(&cpld_data->cpld_lock);
|
||||||
|
|
||||||
|
cpld_data->read_addr = VERSION;
|
||||||
|
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||||
|
if (unlikely(!res)) {
|
||||||
|
printk(KERN_ERR "Specified Resource Not Available...\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sysfs_create_group(&pdev->dev.kobj, &cpld_group);
|
||||||
|
if (err) {
|
||||||
|
printk(KERN_ERR "Cannot create sysfs for SMC.\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
celplatform = class_create(THIS_MODULE, "celplatform");
|
||||||
|
if (IS_ERR(celplatform)) {
|
||||||
|
printk(KERN_ERR "Failed to register device class\n");
|
||||||
|
sysfs_remove_group(&pdev->dev.kobj, &cpld_group);
|
||||||
|
return PTR_ERR(celplatform);
|
||||||
|
}
|
||||||
|
|
||||||
|
cpld_data->fpp_node = device_create(celplatform, NULL, MKDEV(0, 0), NULL, "optical_ports");
|
||||||
|
if (IS_ERR(cpld_data->fpp_node)) {
|
||||||
|
class_destroy(celplatform);
|
||||||
|
sysfs_remove_group(&pdev->dev.kobj, &cpld_group);
|
||||||
|
return PTR_ERR(cpld_data->fpp_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sysfs_create_link(&pdev->dev.kobj, &cpld_data->fpp_node->kobj, "SFP");
|
||||||
|
if (err != 0) {
|
||||||
|
put_device(cpld_data->fpp_node);
|
||||||
|
device_unregister(cpld_data->fpp_node);
|
||||||
|
class_destroy(celplatform);
|
||||||
|
sysfs_remove_group(&pdev->dev.kobj, &cpld_group);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creae SFP devices
|
||||||
|
for ( i = 0; i < 4; i++) {
|
||||||
|
cpld_data->sfp_devices[i] = sfp_init(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all reset signals
|
||||||
|
outb(0xFF, SPR_RESET);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpld_drv_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct sfp_device_data *rem_data;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for ( i = 0; i < 4; i++ ) {
|
||||||
|
rem_data = dev_get_drvdata(cpld_data->sfp_devices[i]);
|
||||||
|
put_device(cpld_data->sfp_devices[i]);
|
||||||
|
device_unregister(cpld_data->sfp_devices[i]);
|
||||||
|
kzfree(rem_data);
|
||||||
|
}
|
||||||
|
put_device(cpld_data->fpp_node);
|
||||||
|
device_unregister(cpld_data->fpp_node);
|
||||||
|
sysfs_remove_group(&pdev->dev.kobj, &cpld_group);
|
||||||
|
class_destroy(celplatform);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver cpld_drv = {
|
||||||
|
.probe = cpld_drv_probe,
|
||||||
|
.remove = __exit_p(cpld_drv_remove),
|
||||||
|
.driver = {
|
||||||
|
.name = DRIVER_NAME,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
int cpld_init(void)
|
||||||
|
{
|
||||||
|
// Register platform device and platform driver
|
||||||
|
platform_device_register(&cpld_dev);
|
||||||
|
platform_driver_register(&cpld_drv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpld_exit(void)
|
||||||
|
{
|
||||||
|
// Unregister platform device and platform driver
|
||||||
|
platform_driver_unregister(&cpld_drv);
|
||||||
|
platform_device_unregister(&cpld_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(cpld_init);
|
||||||
|
module_exit(cpld_exit);
|
||||||
|
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Celestica Inc.");
|
||||||
|
MODULE_DESCRIPTION("Celestica E1031 SMC driver");
|
||||||
|
MODULE_VERSION("0.0.3");
|
||||||
|
MODULE_LICENSE("GPL");
|
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Celestica haliburton platform modules
|
||||||
|
After=local-fs.target
|
||||||
|
Before=pmon.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=-/etc/init.d/platform-modules-haliburton start
|
||||||
|
ExecStop=-/etc/init.d/platform-modules-haliburton stop
|
||||||
|
RemainAfterExit=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
Reference in New Issue
Block a user