[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
|
||||
Ethernet0 2 1000 etp1 1
|
||||
Ethernet1 1 1000 etp2 1
|
||||
Ethernet2 4 1000 etp3 1
|
||||
Ethernet3 3 1000 etp4 1
|
||||
Ethernet4 6 1000 etp5 1
|
||||
Ethernet5 5 1000 etp6 1
|
||||
Ethernet6 8 1000 etp7 1
|
||||
Ethernet7 7 1000 etp8 1
|
||||
Ethernet8 10 1000 etp9 1
|
||||
Ethernet9 9 1000 etp10 1
|
||||
Ethernet10 12 1000 etp11 1
|
||||
Ethernet11 11 1000 etp12 1
|
||||
Ethernet12 14 1000 etp13 1
|
||||
Ethernet13 13 1000 etp14 1
|
||||
Ethernet14 16 1000 etp15 1
|
||||
Ethernet15 15 1000 etp16 1
|
||||
Ethernet16 18 1000 etp17 1
|
||||
Ethernet17 17 1000 etp18 1
|
||||
Ethernet18 20 1000 etp19 1
|
||||
Ethernet19 19 1000 etp20 1
|
||||
Ethernet20 22 1000 etp21 1
|
||||
Ethernet21 21 1000 etp22 1
|
||||
Ethernet22 24 1000 etp23 1
|
||||
Ethernet23 23 1000 etp24 1
|
||||
Ethernet24 26 1000 etp25 1
|
||||
Ethernet25 25 1000 etp26 1
|
||||
Ethernet26 28 1000 etp27 1
|
||||
Ethernet27 27 1000 etp28 1
|
||||
Ethernet28 30 1000 etp29 1
|
||||
Ethernet29 29 1000 etp30 1
|
||||
Ethernet30 32 1000 etp31 1
|
||||
Ethernet31 31 1000 etp32 1
|
||||
Ethernet32 34 1000 etp33 1
|
||||
Ethernet33 33 1000 etp34 1
|
||||
Ethernet34 36 1000 etp35 1
|
||||
Ethernet35 35 1000 etp36 1
|
||||
Ethernet36 38 1000 etp37 1
|
||||
Ethernet37 37 1000 etp38 1
|
||||
Ethernet38 40 1000 etp39 1
|
||||
Ethernet39 39 1000 etp40 1
|
||||
Ethernet40 42 1000 etp41 1
|
||||
Ethernet41 41 1000 etp42 1
|
||||
Ethernet42 44 1000 etp43 1
|
||||
Ethernet43 43 1000 etp44 1
|
||||
Ethernet44 46 1000 etp45 1
|
||||
Ethernet45 45 1000 etp46 1
|
||||
Ethernet46 48 1000 etp47 1
|
||||
Ethernet47 47 1000 etp48 1
|
||||
Ethernet48 54 10000 etp49 0
|
||||
Ethernet49 53 10000 etp50 0
|
||||
Ethernet50 56 10000 etp51 0
|
||||
Ethernet51 55 10000 etp52 0
|
||||
# name lanes index speed alias autoneg
|
||||
Ethernet0 2 1 1000 etp1 1
|
||||
Ethernet1 1 2 1000 etp2 1
|
||||
Ethernet2 4 3 1000 etp3 1
|
||||
Ethernet3 3 4 1000 etp4 1
|
||||
Ethernet4 6 5 1000 etp5 1
|
||||
Ethernet5 5 6 1000 etp6 1
|
||||
Ethernet6 8 7 1000 etp7 1
|
||||
Ethernet7 7 8 1000 etp8 1
|
||||
Ethernet8 10 9 1000 etp9 1
|
||||
Ethernet9 9 10 1000 etp10 1
|
||||
Ethernet10 12 11 1000 etp11 1
|
||||
Ethernet11 11 12 1000 etp12 1
|
||||
Ethernet12 14 13 1000 etp13 1
|
||||
Ethernet13 13 14 1000 etp14 1
|
||||
Ethernet14 16 15 1000 etp15 1
|
||||
Ethernet15 15 16 1000 etp16 1
|
||||
Ethernet16 18 17 1000 etp17 1
|
||||
Ethernet17 17 18 1000 etp18 1
|
||||
Ethernet18 20 19 1000 etp19 1
|
||||
Ethernet19 19 20 1000 etp20 1
|
||||
Ethernet20 22 21 1000 etp21 1
|
||||
Ethernet21 21 22 1000 etp22 1
|
||||
Ethernet22 24 23 1000 etp23 1
|
||||
Ethernet23 23 24 1000 etp24 1
|
||||
Ethernet24 26 25 1000 etp25 1
|
||||
Ethernet25 25 26 1000 etp26 1
|
||||
Ethernet26 28 27 1000 etp27 1
|
||||
Ethernet27 27 28 1000 etp28 1
|
||||
Ethernet28 30 29 1000 etp29 1
|
||||
Ethernet29 29 30 1000 etp30 1
|
||||
Ethernet30 32 31 1000 etp31 1
|
||||
Ethernet31 31 32 1000 etp32 1
|
||||
Ethernet32 34 33 1000 etp33 1
|
||||
Ethernet33 33 34 1000 etp34 1
|
||||
Ethernet34 36 35 1000 etp35 1
|
||||
Ethernet35 35 36 1000 etp36 1
|
||||
Ethernet36 38 37 1000 etp37 1
|
||||
Ethernet37 37 38 1000 etp38 1
|
||||
Ethernet38 40 39 1000 etp39 1
|
||||
Ethernet39 39 40 1000 etp40 1
|
||||
Ethernet40 42 41 1000 etp41 1
|
||||
Ethernet41 41 42 1000 etp42 1
|
||||
Ethernet42 44 43 1000 etp43 1
|
||||
Ethernet43 43 44 1000 etp44 1
|
||||
Ethernet44 46 45 1000 etp45 1
|
||||
Ethernet45 45 46 1000 etp46 1
|
||||
Ethernet46 48 47 1000 etp47 1
|
||||
Ethernet47 47 48 1000 etp48 1
|
||||
Ethernet48 54 49 10000 etp49 0
|
||||
Ethernet49 53 50 10000 etp50 0
|
||||
Ethernet50 56 51 10000 etp51 0
|
||||
Ethernet51 55 52 10000 etp52 0
|
||||
|
@ -1,12 +1,12 @@
|
||||
# Configuration file generated by pwmconfig, changes will be lost
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
MINPWM=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
|
||||
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
|
||||
|
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
|
||||
# changes every time when system boot up.
|
||||
|
||||
chip "max6697-i2c-*-1a"
|
||||
label temp1 "temp sensor 1"
|
||||
label temp2 "temp sensor 2"
|
||||
label temp3 "temp sensor 3"
|
||||
label temp4 "temp sensor 4"
|
||||
label temp5 "temp sensor 5"
|
||||
ignore temp6
|
||||
ignore temp7
|
||||
bus "i2c-3" "i2c-0-mux (chan_id 1)"
|
||||
bus "i2c-11" "i2c-8-mux (chan_id 1)"
|
||||
|
||||
chip "max6697-i2c-3-1a"
|
||||
label temp1 "CPU board temperature sensor : 1"
|
||||
label temp2 "CPU board temperature sensor : 2"
|
||||
label temp3 "CPU board temperature sensor : 3"
|
||||
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
|
||||
|
||||
CEL_DX010_PLATFORM_MODULE_VERSION = 0.8
|
||||
CEL_HALIBURTON_PLATFORM_MODULE_VERSION = 0.8
|
||||
CEL_DX010_PLATFORM_MODULE_VERSION = 0.9
|
||||
CEL_HALIBURTON_PLATFORM_MODULE_VERSION = 0.9
|
||||
|
||||
export CEL_DX010_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
|
||||
|
||||
* 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
|
||||
|
||||
|
@ -15,10 +15,8 @@ case "$1" in
|
||||
start)
|
||||
echo -n "Setting up board... "
|
||||
|
||||
depmod -a
|
||||
modprobe i2c-dev
|
||||
modprobe i2c-mux-pca954x
|
||||
|
||||
modprobe smc
|
||||
|
||||
found=0
|
||||
for devnum in 0 1; do
|
||||
devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name`
|
||||
@ -56,15 +54,11 @@ start)
|
||||
# Attach fans
|
||||
echo emc2305 0x4d > /sys/bus/i2c/devices/i2c-23/new_device
|
||||
|
||||
# Attach PSUs
|
||||
echo dps200 0x5a > /sys/bus/i2c/devices/i2c-12/new_device
|
||||
echo dps200 0x5b > /sys/bus/i2c/devices/i2c-13/new_device
|
||||
|
||||
# Attach 4 SFP+ Uplink
|
||||
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
|
||||
# Attach 4 SFP+ Uplink
|
||||
echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-14/new_device
|
||||
echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-15/new_device
|
||||
echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-16/new_device
|
||||
echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-17/new_device
|
||||
|
||||
echo "done."
|
||||
;;
|
||||
|
@ -1 +1,2 @@
|
||||
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
|
Loading…
Reference in New Issue
Block a user