diff --git a/device/celestica/x86_64-cel_e1031-r0/Celestica-E1031-T48S4/port_config.ini b/device/celestica/x86_64-cel_e1031-r0/Celestica-E1031-T48S4/port_config.ini index 6a7debfa45..a2b64ea155 100644 --- a/device/celestica/x86_64-cel_e1031-r0/Celestica-E1031-T48S4/port_config.ini +++ b/device/celestica/x86_64-cel_e1031-r0/Celestica-E1031-T48S4/port_config.ini @@ -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 diff --git a/device/celestica/x86_64-cel_e1031-r0/fancontrol b/device/celestica/x86_64-cel_e1031-r0/fancontrol index a94c63055f..27c6dcb78e 100644 --- a/device/celestica/x86_64-cel_e1031-r0/fancontrol +++ b/device/celestica/x86_64-cel_e1031-r0/fancontrol @@ -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 diff --git a/device/celestica/x86_64-cel_e1031-r0/plugins/psuutil.py b/device/celestica/x86_64-cel_e1031-r0/plugins/psuutil.py new file mode 100644 index 0000000000..71b8d4ad3c --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/plugins/psuutil.py @@ -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 + + :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 + + :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 diff --git a/device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py b/device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py new file mode 100644 index 0000000000..851fb9ccc0 --- /dev/null +++ b/device/celestica/x86_64-cel_e1031-r0/plugins/sfputil.py @@ -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 diff --git a/device/celestica/x86_64-cel_e1031-r0/sensors.conf b/device/celestica/x86_64-cel_e1031-r0/sensors.conf index 1874548cff..25c6047137 100644 --- a/device/celestica/x86_64-cel_e1031-r0/sensors.conf +++ b/device/celestica/x86_64-cel_e1031-r0/sensors.conf @@ -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 :" + diff --git a/platform/broadcom/platform-modules-cel.mk b/platform/broadcom/platform-modules-cel.mk index 9226d92463..1224faaa67 100644 --- a/platform/broadcom/platform-modules-cel.mk +++ b/platform/broadcom/platform-modules-cel.mk @@ -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 diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/changelog b/platform/broadcom/sonic-platform-modules-cel/debian/changelog index 64f2decf26..843b028e43 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/changelog +++ b/platform/broadcom/sonic-platform-modules-cel/debian/changelog @@ -1,8 +1,15 @@ +sonic-cel-platform-modules (0.9) unstable; urgency=low + + * Add haliburton platform module. + + -- Wirut Getbamrung 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 Thu, 5 Apr 2018 09:09:09 +0700 + -- Pradchaya Phucharoen Mon, 1 Jul 2018 11:09:13 +0700 sonic-cel-platform-modules (0.7) unstable; urgency=low diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init index 08770d1d64..66f1ee5529 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.init @@ -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." ;; diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.install b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.install index 464b77855f..93b2eed633 100644 --- a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.install +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.install @@ -1 +1,2 @@ haliburton/cfg/haliburton-modules.conf etc/modules-load.d +haliburton/systemd/platform-modules-haliburton.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.postinst b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.postinst new file mode 100644 index 0000000000..bdc23c66d5 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/debian/platform-modules-haliburton.postinst @@ -0,0 +1,3 @@ +depmod -a +systemctl enable platform-modules-haliburton.service +systemctl start platform-modules-haliburton.service diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/Makefile b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/Makefile index 6d0c489154..58e2b0bf2d 100644 --- a/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/Makefile +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/Makefile @@ -1 +1 @@ -obj-m := mc24lc64t.o emc2305.o +obj-m := mc24lc64t.o emc2305.o smc.o diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/smc.c b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/smc.c new file mode 100644 index 0000000000..82abc9e8ea --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/modules/smc.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#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"); diff --git a/platform/broadcom/sonic-platform-modules-cel/haliburton/systemd/platform-modules-haliburton.service b/platform/broadcom/sonic-platform-modules-cel/haliburton/systemd/platform-modules-haliburton.service new file mode 100644 index 0000000000..bf12950388 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/haliburton/systemd/platform-modules-haliburton.service @@ -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 \ No newline at end of file