diff --git a/.gitmodules b/.gitmodules index ca8b4b0098a8..4be19b7d3c6a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,7 +3,7 @@ url = https://github.com/Azure/sonic-swss-common [submodule "sonic-linux-kernel"] path = src/sonic-linux-kernel - url = https://github.com/Azure/sonic-linux-kernel + url = https://github.com/CentecNetworks/sonic-linux-kernel [submodule "sonic-sairedis"] path = src/sonic-sairedis url = https://github.com/Azure/sonic-sairedis diff --git a/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/buffers.json.j2 b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/buffers.json.j2 new file mode 100644 index 000000000000..08e21e428b6c --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/buffers.json.j2 @@ -0,0 +1,70 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '40m' %} +{% set default_ports_num = 54 -%} + +{# Port configuration to cable length look-up table #} +{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #} +{# Roles described in the minigraph #} +{% set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- macro cable_length(port_name) -%} + {%- set cable_len = [] -%} + {%- for local_port in DEVICE_NEIGHBOR -%} + {%- if local_port == port_name -%} + {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor_role = neighbor.type -%} + {%- set roles1 = switch_role + '_' + neighbor_role %} + {%- set roles2 = neighbor_role + '_' + switch_role -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- if roles1 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%} + {%- elif roles2 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endfor -%} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(1,default_ports_num+1) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + } +} + diff --git a/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/pg_profile_lookup.ini b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/pg_profile_lookup.ini new file mode 100644 index 000000000000..a65244e69b5b --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/pg_profile_lookup.ini @@ -0,0 +1,21 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 1000 5m 34816 18432 16384 0 + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 1000 40m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 1000 300m 49152 18432 30720 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 + diff --git a/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/port_config.ini b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/port_config.ini new file mode 100644 index 000000000000..27d43a0abd0d --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/port_config.ini @@ -0,0 +1,27 @@ +# name lanes alias speed +Ethernet1 0 eth-0-1 10000 +Ethernet2 1 eth-0-2 10000 +Ethernet3 2 eth-0-3 10000 +Ethernet4 3 eth-0-4 10000 +Ethernet5 8 eth-0-5 10000 +Ethernet6 9 eth-0-6 10000 +Ethernet7 10 eth-0-7 10000 +Ethernet8 11 eth-0-8 10000 +Ethernet9 20 eth-0-9 10000 +Ethernet10 21 eth-0-10 10000 +Ethernet11 22 eth-0-11 10000 +Ethernet12 23 eth-0-12 10000 +Ethernet13 12 eth-0-13 10000 +Ethernet14 13 eth-0-14 10000 +Ethernet15 14 eth-0-15 10000 +Ethernet16 15 eth-0-16 10000 +Ethernet17 24 eth-0-17 10000 +Ethernet18 25 eth-0-18 10000 +Ethernet19 26 eth-0-19 10000 +Ethernet20 27 eth-0-20 10000 +Ethernet21 28 eth-0-21 10000 +Ethernet22 29 eth-0-22 10000 +Ethernet23 30 eth-0-23 10000 +Ethernet24 31 eth-0-24 10000 +Ethernet25 61,60,63,62 eth-0-25 100000 +Ethernet26 45,44,47,46 eth-0-26 100000 diff --git a/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/qos.json.j2 b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/sai.profile b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/sai.profile new file mode 100644 index 000000000000..09efce07c613 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/E530-24x2c/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/etc/centec/E530-24x2c-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/E530-24x2c-datapath-cfg.txt diff --git a/device/centec/arm64-centec_e530_24x2c-r0/default_sku b/device/centec/arm64-centec_e530_24x2c-r0/default_sku new file mode 100644 index 000000000000..c714e6c18dbb --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/default_sku @@ -0,0 +1 @@ +E530-24x2c l2 diff --git a/device/centec/arm64-centec_e530_24x2c-r0/fancontrol b/device/centec/arm64-centec_e530_24x2c-r0/fancontrol new file mode 100644 index 000000000000..e3775297128e --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/fancontrol @@ -0,0 +1 @@ +# Configuration file generated by pwmconfig, changes will be lost diff --git a/device/centec/arm64-centec_e530_24x2c-r0/installer.conf b/device/centec/arm64-centec_e530_24x2c-r0/installer.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/device/centec/arm64-centec_e530_24x2c-r0/plugins/eeprom.py b/device/centec/arm64-centec_e530_24x2c-r0/plugins/eeprom.py new file mode 100644 index 000000000000..5eefc2b8ca0f --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/plugins/eeprom.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +############################################################################# +# Centec E550-24X8Y2C +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + import subprocess + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/dev/mtd3" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/centec/arm64-centec_e530_24x2c-r0/plugins/led_control.py b/device/centec/arm64-centec_e530_24x2c-r0/plugins/led_control.py new file mode 100644 index 000000000000..5a60cd82f5f4 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/plugins/led_control.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +try: + from sonic_led.led_control_base import LedControlBase + import swsssdk + import threading + import os + import logging + import struct + import time + import syslog + from socket import * + from select import * +except ImportError, e: + raise ImportError(str(e) + " - required module not found") + + +def DBG_PRINT(str): + syslog.openlog("centec-led") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + + +class LedControl(LedControlBase): + """Platform specific LED control class""" + + + # Helper method to map SONiC port name to index + def _port_name_to_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + return port_idx + + def _port_state_to_mode(self, port_idx, state): + if state == "up": + return self.LED_MODE_UP[0] if (port_idx < 25) else self.LED_MODE_UP[1] + else: + return self.LED_MODE_DOWN[0] if (port_idx < 25) else self.LED_MODE_DOWN[1] + + def _port_led_mode_update(self, port_idx, ledMode): + with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file: + led_file.write(str(ledMode)) + + def _initSystemLed(self): + try: + with open(self.f_led.format("system"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init system led to normal") + with open(self.f_led.format("idn"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init idn led to off") + except IOError as e: + DBG_PRINT(str(e)) + + def _initPanelLed(self): + with open(self.f_led.format("port1"), 'r') as led_file: + shouldInit = (int(led_file.read()) == 0) + + if shouldInit == True: + for idx in range(1, 27): + defmode = self._port_state_to_mode(idx, "down") + with open(self.f_led.format("port{}".format(idx)), 'w') as led_file: + led_file.write(str(defmode)) + DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) + + def _initDefaultConfig(self): + DBG_PRINT("start init led") + + self._initSystemLed() + self._initPanelLed() + + DBG_PRINT("init led done") + + + # Concrete implementation of port_link_state_change() method + def port_link_state_change(self, portname, state): + port_idx = self._port_name_to_index(portname) + ledMode = self._port_state_to_mode(port_idx, state) + with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file: + saveMode = int(led_file.read()) + + if ledMode == saveMode: + return + + self._port_led_mode_update(port_idx, ledMode) + DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) + + + # Constructor + def __init__(self): + self.SONIC_PORT_NAME_PREFIX = "Ethernet" + self.LED_MODE_UP = [11, 11] + self.LED_MODE_DOWN = [7, 7] + + self.f_led = "/sys/class/leds/{}/brightness" + self._initDefaultConfig() diff --git a/device/centec/arm64-centec_e530_24x2c-r0/plugins/psuutil.py b/device/centec/arm64-centec_e530_24x2c-r0/plugins/psuutil.py new file mode 100644 index 000000000000..30255f7bfb48 --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/plugins/psuutil.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python + +############################################################################# +# Centec +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +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/class/psu/psu{}/" + self.psu_presence = "psu_presence" + 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 + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_oper_status, '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 + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_presence, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/centec/arm64-centec_e530_24x2c-r0/plugins/sfputil.py b/device/centec/arm64-centec_e530_24x2c-r0/plugins/sfputil.py new file mode 100644 index 000000000000..108c74cbdb2f --- /dev/null +++ b/device/centec/arm64-centec_e530_24x2c-r0/plugins/sfputil.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python + +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import os + import logging + import struct + import syslog + from socket import * + from select import * + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +def DBG_PRINT(str): + print str + "\n" + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def sfp_base(self): + return self.SFP_BASE + + @property + def qsfp_ports(self): + return range(25, self.PORTS_IN_BLOCK + 1) + + @property + def port_to_eeprom_mapping(self): + return self.eeprom_mapping + + def is_logical_port(self, port_name): + return True + + def get_logical_to_physical(self, port_name): + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return None + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + + return [port_idx] + + def get_eeprom_data(self, port): + ret = None + port_num = self.get_logical_to_physical(port)[0] + if port_num < self.port_start or port_num > self.port_end: + return ret + if port_num < self.sfp_base: + return ret + try: + with open(self.eeprom_mapping[port_num], 'r') as eeprom_file: + ret = eeprom_file.read() + except IOError as e: + DBG_PRINT(str(e)) + + return ret + + # todo + #def _get_port_eeprom_path(self, port_num, devid): + # pass + + def __init__(self): + self.SONIC_PORT_NAME_PREFIX = "Ethernet" + self.PORT_START = 1 + self.PORT_END = 26 + self.SFP_BASE = 1 + self.PORTS_IN_BLOCK = 26 + + self.eeprom_mapping = {} + self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" + self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable" + for x in range(self.port_start, self.sfp_base): + self.eeprom_mapping[x] = None + for x in range(self.sfp_base, self.port_end + 1): + self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(x - self.sfp_base + 1) + self.presence = {} + for x in range(self.sfp_base, self.port_end + 1): + self.presence[x] = False; + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.sfp_base: + return False + try: + with open(self.f_sfp_present.format(port_num - self.sfp_base + 1), 'r') as sfp_file: + return 1 == int(sfp_file.read()) + except IOError as e: + DBG_PRINT(str(e)) + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def get_transceiver_change_event(self, timeout=0): + port_dict = {} + while True: + for x in range(self.sfp_base, self.port_end + 1): + presence = self.get_presence(x) + if presence != self.presence[x]: + self.presence[x] = presence + port_dict[x] = presence + return True, port_dict + time.sleep(0.5) + return False, {} diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/buffers.json.j2 b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/buffers.json.j2 new file mode 100644 index 000000000000..08e21e428b6c --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/buffers.json.j2 @@ -0,0 +1,70 @@ +{# Default values which will be used if no actual configura available #} +{% set default_cable = '40m' %} +{% set default_ports_num = 54 -%} + +{# Port configuration to cable length look-up table #} +{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #} +{# Roles described in the minigraph #} +{% set ports2cable = { + 'torrouter_server' : '5m', + 'leafrouter_torrouter' : '40m', + 'spinerouter_leafrouter' : '300m' + } +%} + +{%- macro cable_length(port_name) -%} + {%- set cable_len = [] -%} + {%- for local_port in DEVICE_NEIGHBOR -%} + {%- if local_port == port_name -%} + {%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%} + {%- set neighbor_role = neighbor.type -%} + {%- set roles1 = switch_role + '_' + neighbor_role %} + {%- set roles2 = neighbor_role + '_' + switch_role -%} + {%- set roles1 = roles1 | lower -%} + {%- set roles2 = roles2 | lower -%} + {%- if roles1 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%} + {%- elif roles2 in ports2cable -%} + {%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endif -%} + {%- endfor -%} + {%- if cable_len -%} + {{ cable_len.0 }} + {%- else -%} + {{ default_cable }} + {%- endif -%} +{% endmacro %} + +{%- if DEVICE_METADATA is defined %} +{%- set switch_role = DEVICE_METADATA['localhost']['type'] %} +{%- endif -%} + +{# Generate list of ports if not defined #} +{% if PORT is not defined %} + {% set PORT = [] %} + {% for port_idx in range(1,default_ports_num+1) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} +{% endif -%} + +{% set port_names_list = [] %} +{% for port in PORT %} + {%- if port_names_list.append(port) %}{% endif %} +{% endfor %} +{% set port_names = port_names_list | join(',') -%} + +{ + "CABLE_LENGTH": { + "AZURE": { + {% for port in PORT %} + {% set cable = cable_length(port) -%} + "{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %} + + {% endfor %} + } + } +} + diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/pg_profile_lookup.ini b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/pg_profile_lookup.ini new file mode 100644 index 000000000000..a65244e69b5b --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/pg_profile_lookup.ini @@ -0,0 +1,21 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold + 1000 5m 34816 18432 16384 0 + 10000 5m 34816 18432 16384 0 + 25000 5m 34816 18432 16384 0 + 40000 5m 34816 18432 16384 0 + 50000 5m 34816 18432 16384 0 + 100000 5m 36864 18432 18432 0 + 1000 40m 36864 18432 18432 0 + 10000 40m 36864 18432 18432 0 + 25000 40m 39936 18432 21504 0 + 40000 40m 41984 18432 23552 0 + 50000 40m 41984 18432 23552 0 + 100000 40m 54272 18432 35840 0 + 1000 300m 49152 18432 30720 0 + 10000 300m 49152 18432 30720 0 + 25000 300m 71680 18432 53248 0 + 40000 300m 94208 18432 75776 0 + 50000 300m 94208 18432 75776 0 + 100000 300m 184320 18432 165888 0 + diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/port_config.ini b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/port_config.ini new file mode 100644 index 000000000000..c904ece72ea0 --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/port_config.ini @@ -0,0 +1,53 @@ +# name lanes alias speed +Ethernet1 1 eth-0-1 1000 +Ethernet2 0 eth-0-2 1000 +Ethernet3 3 eth-0-3 1000 +Ethernet4 2 eth-0-4 1000 +Ethernet5 5 eth-0-5 1000 +Ethernet6 4 eth-0-6 1000 +Ethernet7 7 eth-0-7 1000 +Ethernet8 6 eth-0-8 1000 +Ethernet9 17 eth-0-9 1000 +Ethernet10 16 eth-0-10 1000 +Ethernet11 19 eth-0-11 1000 +Ethernet12 18 eth-0-12 1000 +Ethernet13 21 eth-0-13 1000 +Ethernet14 20 eth-0-14 1000 +Ethernet15 23 eth-0-15 1000 +Ethernet16 22 eth-0-16 1000 +Ethernet17 9 eth-0-17 1000 +Ethernet18 8 eth-0-18 1000 +Ethernet19 11 eth-0-19 1000 +Ethernet20 10 eth-0-20 1000 +Ethernet21 33 eth-0-21 1000 +Ethernet22 32 eth-0-22 1000 +Ethernet23 35 eth-0-23 1000 +Ethernet24 34 eth-0-24 1000 +Ethernet25 37 eth-0-25 1000 +Ethernet26 36 eth-0-26 1000 +Ethernet27 39 eth-0-27 1000 +Ethernet28 38 eth-0-28 1000 +Ethernet29 41 eth-0-29 1000 +Ethernet30 40 eth-0-30 1000 +Ethernet31 43 eth-0-31 1000 +Ethernet32 42 eth-0-32 1000 +Ethernet33 25 eth-0-33 1000 +Ethernet34 24 eth-0-34 1000 +Ethernet35 27 eth-0-35 1000 +Ethernet36 26 eth-0-36 1000 +Ethernet37 49 eth-0-37 1000 +Ethernet38 48 eth-0-38 1000 +Ethernet39 51 eth-0-39 1000 +Ethernet40 50 eth-0-40 1000 +Ethernet41 53 eth-0-41 1000 +Ethernet42 52 eth-0-42 1000 +Ethernet43 55 eth-0-43 1000 +Ethernet44 54 eth-0-44 1000 +Ethernet45 57 eth-0-45 1000 +Ethernet46 56 eth-0-46 1000 +Ethernet47 59 eth-0-47 1000 +Ethernet48 58 eth-0-48 1000 +Ethernet49 13 eth-0-49 10000 +Ethernet50 12 eth-0-50 10000 +Ethernet51 15 eth-0-51 10000 +Ethernet52 14 eth-0-52 10000 diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/qos.json.j2 b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/qos.json.j2 new file mode 100644 index 000000000000..3e548325ea30 --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/qos.json.j2 @@ -0,0 +1 @@ +{%- include 'qos_config.j2' %} diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/sai.profile b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/sai.profile new file mode 100644 index 000000000000..e026761f7b8a --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/E530-48t4x-p/sai.profile @@ -0,0 +1,2 @@ +SAI_INIT_CONFIG_FILE=/etc/centec/E530-48t4x-p-chip-profile.txt +SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/E530-48t4x-p-datapath.txt diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/default_sku b/device/centec/arm64-centec_e530_48t4x_p-r0/default_sku new file mode 100644 index 000000000000..03b04aaf1b0d --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/default_sku @@ -0,0 +1 @@ +E530-48t4x-p l2 diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/fancontrol b/device/centec/arm64-centec_e530_48t4x_p-r0/fancontrol new file mode 100644 index 000000000000..e3775297128e --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/fancontrol @@ -0,0 +1 @@ +# Configuration file generated by pwmconfig, changes will be lost diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/installer.conf b/device/centec/arm64-centec_e530_48t4x_p-r0/installer.conf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/eeprom.py b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/eeprom.py new file mode 100644 index 000000000000..5eefc2b8ca0f --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/eeprom.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +############################################################################# +# Centec E550-24X8Y2C +# +# Platform and model specific eeprom subclass, inherits from the base class, +# and provides the followings: +# - the eeprom format definition +# - specific encoder/decoder if there is special need +############################################################################# + +try: + import exceptions + import binascii + import time + import optparse + import warnings + import os + import sys + import subprocess + from sonic_eeprom import eeprom_base + from sonic_eeprom import eeprom_tlvinfo +except ImportError, e: + raise ImportError (str(e) + "- required module not found") + + +class board(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self, name, path, cpld_root, ro): + self.eeprom_path = "/dev/mtd3" + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/led_control.py b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/led_control.py new file mode 100644 index 000000000000..9d18f4198b4e --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/led_control.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# +# led_control.py +# +# Platform-specific LED control functionality for SONiC +# + +try: + from sonic_led.led_control_base import LedControlBase + import swsssdk + import threading + import os + import logging + import struct + import time + import syslog + from socket import * + from select import * +except ImportError, e: + raise ImportError(str(e) + " - required module not found") + + +def DBG_PRINT(str): + syslog.openlog("centec-led") + syslog.syslog(syslog.LOG_INFO, str) + syslog.closelog() + + +class LedControl(LedControlBase): + """Platform specific LED control class""" + + + # Helper method to map SONiC port name to index + def _port_name_to_index(self, port_name): + # Strip "Ethernet" off port name + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return -1 + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + return port_idx + + def _port_state_to_mode(self, port_idx, state): + if state == "up": + return self.LED_MODE_UP[0] if (port_idx < 49) else self.LED_MODE_UP[1] + else: + return self.LED_MODE_DOWN[0] if (port_idx < 49) else self.LED_MODE_DOWN[1] + + def _port_led_mode_update(self, port_idx, ledMode): + with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file: + led_file.write(str(ledMode)) + + def _initSystemLed(self): + try: + with open(self.f_led.format("system"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init system led to normal") + with open(self.f_led.format("idn"), 'w') as led_file: + led_file.write("1") + DBG_PRINT("init idn led to off") + except IOError as e: + DBG_PRINT(str(e)) + + def _initPanelLed(self): + with open(self.f_led.format("port1"), 'r') as led_file: + shouldInit = (int(led_file.read()) == 0) + + if shouldInit == True: + for idx in range(1, 53): + defmode = self._port_state_to_mode(idx, "down") + with open(self.f_led.format("port{}".format(idx)), 'w') as led_file: + led_file.write(str(defmode)) + DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) + + def _initDefaultConfig(self): + DBG_PRINT("start init led") + + self._initSystemLed() + self._initPanelLed() + + DBG_PRINT("init led done") + + + # Concrete implementation of port_link_state_change() method + def port_link_state_change(self, portname, state): + port_idx = self._port_name_to_index(portname) + ledMode = self._port_state_to_mode(port_idx, state) + with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file: + saveMode = int(led_file.read()) + + if ledMode == saveMode: + return + + self._port_led_mode_update(port_idx, ledMode) + DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) + + + # Constructor + def __init__(self): + self.SONIC_PORT_NAME_PREFIX = "Ethernet" + self.LED_MODE_UP = [2, 11] + self.LED_MODE_DOWN = [1, 7] + + self.f_led = "/sys/class/leds/{}/brightness" + self._initDefaultConfig() diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/psuutil.py b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/psuutil.py new file mode 100644 index 000000000000..30255f7bfb48 --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/psuutil.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python + +############################################################################# +# Centec +# +# Module contains an implementation of SONiC PSU Base API and +# provides the PSUs status which are available in the platform +# +############################################################################# + +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/class/psu/psu{}/" + self.psu_presence = "psu_presence" + 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 + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_oper_status, '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 + """ + if index is None: + return False + + status = 0 + try: + with open(self.psu_path.format(index) + self.psu_presence, 'r') as presence_status: + status = int(presence_status.read()) + except IOError: + return False + + return status == 1 diff --git a/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/sfputil.py b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/sfputil.py new file mode 100644 index 000000000000..f78fb8aaec3f --- /dev/null +++ b/device/centec/arm64-centec_e530_48t4x_p-r0/plugins/sfputil.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python + +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import time + import os + import logging + import struct + import syslog + from socket import * + from select import * + from sonic_sfp.sfputilbase import SfpUtilBase +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + + +def DBG_PRINT(str): + print str + "\n" + + +class SfpUtil(SfpUtilBase): + """Platform-specific SfpUtil class""" + + @property + def port_start(self): + return self.PORT_START + + @property + def port_end(self): + return self.PORT_END + + @property + def sfp_base(self): + return self.SFP_BASE + + @property + def qsfp_ports(self): + return () + + @property + def port_to_eeprom_mapping(self): + return self.eeprom_mapping + + def is_logical_port(self, port_name): + return True + + def get_logical_to_physical(self, port_name): + if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): + return None + + port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) + + return [port_idx] + + def get_eeprom_data(self, port): + ret = None + port_num = self.get_logical_to_physical(port)[0] + if port_num < self.port_start or port_num > self.port_end: + return ret + if port_num < self.sfp_base: + return ret + try: + with open(self.eeprom_mapping[port_num], 'r') as eeprom_file: + ret = eeprom_file.read() + except IOError as e: + DBG_PRINT(str(e)) + + return ret + + # todo + #def _get_port_eeprom_path(self, port_num, devid): + # pass + + def __init__(self): + self.SONIC_PORT_NAME_PREFIX = "Ethernet" + self.PORT_START = 1 + self.PORT_END = 52 + self.SFP_BASE = 49 + self.PORTS_IN_BLOCK = 52 + + self.eeprom_mapping = {} + self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" + self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable" + for x in range(self.port_start, self.sfp_base): + self.eeprom_mapping[x] = None + for x in range(self.sfp_base, self.port_end + 1): + self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(x - self.sfp_base + 1) + self.presence = {} + for x in range(self.sfp_base, self.port_end + 1): + self.presence[x] = False; + + SfpUtilBase.__init__(self) + + def get_presence(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + if port_num < self.sfp_base: + return False + try: + with open(self.f_sfp_present.format(port_num - self.sfp_base + 1), 'r') as sfp_file: + return 1 == int(sfp_file.read()) + except IOError as e: + DBG_PRINT(str(e)) + + return False + + def get_low_power_mode(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def set_low_power_mode(self, port_num, lpmode): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def reset(self, port_num): + # Check for invalid port_num + if port_num < self.port_start or port_num > self.port_end: + return False + + return False + + def get_transceiver_change_event(self, timeout=0): + port_dict = {} + while True: + for x in range(self.sfp_base, self.port_end + 1): + presence = self.get_presence(x) + if presence != self.presence[x]: + self.presence[x] = presence + port_dict[x] = presence + return True, port_dict + time.sleep(0.5) + return False, {} diff --git a/platform/centec-arm64/docker-ptf-centec.mk b/platform/centec-arm64/docker-ptf-centec.mk new file mode 100755 index 000000000000..3d4fe50e5f1f --- /dev/null +++ b/platform/centec-arm64/docker-ptf-centec.mk @@ -0,0 +1,7 @@ +# docker image for docker-ptf-centec + +DOCKER_PTF_CENTEC = docker-ptf-centec.gz +$(DOCKER_PTF_CENTEC)_PATH = $(DOCKERS_PATH)/docker-ptf-saithrift +$(DOCKER_PTF_CENTEC)_DEPENDS += $(PYTHON_SAITHRIFT) +$(DOCKER_PTF_CENTEC)_LOAD_DOCKERS += $(DOCKER_PTF) +SONIC_DOCKER_IMAGES += $(DOCKER_PTF_CENTEC) diff --git a/platform/centec-arm64/docker-saiserver-centec.mk b/platform/centec-arm64/docker-saiserver-centec.mk new file mode 100755 index 000000000000..770b66b83233 --- /dev/null +++ b/platform/centec-arm64/docker-saiserver-centec.mk @@ -0,0 +1,15 @@ +# docker image for centec saiserver + +DOCKER_SAISERVER_CENTEC = docker-saiserver-centec.gz +$(DOCKER_SAISERVER_CENTEC)_PATH = $(PLATFORM_PATH)/docker-saiserver-centec +$(DOCKER_SAISERVER_CENTEC)_DEPENDS += $(SAISERVER) +$(DOCKER_SAISERVER_CENTEC)_FILES += $(DSSERVE) $(BCMCMD) +$(DOCKER_SAISERVER_CENTEC)_LOAD_DOCKERS += $(DOCKER_CONFIG_ENGINE_STRETCH) +SONIC_DOCKER_IMAGES += $(DOCKER_SAISERVER_CENTEC) + +$(DOCKER_SAISERVER_CENTEC)_CONTAINER_NAME = saiserver +$(DOCKER_SAISERVER_CENTEC)_RUN_OPT += --privileged -t +$(DOCKER_SAISERVER_CENTEC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SAISERVER_CENTEC)_RUN_OPT += -v /var/run/docker-saiserver:/var/run/sswsyncd +$(DOCKER_SAISERVER_CENTEC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SAISERVER_CENTEC)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/centec-arm64/docker-syncd-centec-rpc.mk b/platform/centec-arm64/docker-syncd-centec-rpc.mk new file mode 100755 index 000000000000..8d699c91347f --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec-rpc.mk @@ -0,0 +1,24 @@ +# docker image for centec syncd with rpc + +DOCKER_SYNCD_CENTEC_RPC = docker-syncd-centec-rpc.gz +$(DOCKER_SYNCD_CENTEC_RPC)_PATH = $(PLATFORM_PATH)/docker-syncd-centec-rpc +$(DOCKER_SYNCD_CENTEC_RPC)_DEPENDS += $(SYNCD_RPC) $(LIBTHRIFT) +$(DOCKER_SYNCD_CENTEC_RPC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +ifeq ($(INSTALL_DEBUG_TOOLS), y) +$(DOCKER_SYNCD_CENTEC_RPC)_DEPENDS += $(SYNCD_RPC_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) +endif +$(DOCKER_SYNCD_CENTEC_RPC)_LOAD_DOCKERS += $(DOCKER_SYNCD_BASE) +SONIC_DOCKER_IMAGES += $(DOCKER_SYNCD_CENTEC_RPC) +SONIC_STRETCH_DOCKERS += $(DOCKER_SYNCD_CENTEC_RPC) +ifeq ($(ENABLE_SYNCD_RPC),y) +SONIC_INSTALL_DOCKER_IMAGES += $(DOCKER_SYNCD_CENTEC_RPC) +endif + +$(DOCKER_SYNCD_CENTEC_RPC)_CONTAINER_NAME = syncd +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += --privileged -t +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro +$(DOCKER_SYNCD_CENTEC_RPC)_RUN_OPT += -v /host/warmboot:/var/warmboot diff --git a/platform/centec-arm64/docker-syncd-centec-rpc/Dockerfile.j2 b/platform/centec-arm64/docker-syncd-centec-rpc/Dockerfile.j2 new file mode 100755 index 000000000000..2174fd91f919 --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec-rpc/Dockerfile.j2 @@ -0,0 +1,51 @@ +FROM docker-syncd-centec + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +COPY \ +{% for deb in docker_syncd_centec_rpc_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get purge -y syncd + +RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; } ; \ +{% for deb in docker_syncd_centec_rpc_debs.split(' ') -%} +dpkg_apt debs/{{ deb }}{{'; '}} +{%- endfor %} + +## Pre-install the fundamental packages +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + python-pip \ + build-essential \ + libssl-dev \ + libffi-dev \ + python-dev \ + wget \ + cmake \ + && wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \ + && tar xvfz 1.0.0.tar.gz \ + && cd nanomsg-1.0.0 \ + && mkdir -p build \ + && cmake . \ + && make install \ + && ldconfig \ + && cd .. \ + && rm -fr nanomsg-1.0.0 \ + && rm -f 1.0.0.tar.gz \ + && pip install cffi==1.7.0 \ + && pip install --upgrade cffi==1.7.0 \ + && pip install nnpy \ + && mkdir -p /opt \ + && cd /opt \ + && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py \ + && apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y \ + && rm -rf /root/deps + +COPY ["ptf_nn_agent.conf", "/etc/supervisor/conf.d/"] + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/centec-arm64/docker-syncd-centec-rpc/ptf_nn_agent.conf b/platform/centec-arm64/docker-syncd-centec-rpc/ptf_nn_agent.conf new file mode 100755 index 000000000000..fa1ed0eb1622 --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec-rpc/ptf_nn_agent.conf @@ -0,0 +1,10 @@ +[program:ptf_nn_agent] +command=/usr/bin/python /opt/ptf_nn_agent.py --device-socket 1@tcp://0.0.0.0:10900 -i 1-3@Ethernet12 --set-iface-rcv-buffer=109430400 +process_name=ptf_nn_agent +stdout_logfile=/tmp/ptf_nn_agent.out.log +stderr_logfile=/tmp/ptf_nn_agent.err.log +redirect_stderr=false +autostart=true +autorestart=true +startsecs=1 +numprocs=1 diff --git a/platform/centec-arm64/docker-syncd-centec.mk b/platform/centec-arm64/docker-syncd-centec.mk new file mode 100755 index 000000000000..9c3d1b1aff75 --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec.mk @@ -0,0 +1,17 @@ +# docker image for centec syncd + +DOCKER_SYNCD_PLATFORM_CODE = centec +include $(PLATFORM_PATH)/../template/docker-syncd-base.mk + +$(DOCKER_SYNCD_BASE)_DEPENDS += $(SYNCD) $(PYTHON_SDK_API) +$(DOCKER_SYNCD_CENTEC)_FILES += $(SUPERVISOR_PROC_EXIT_LISTENER_SCRIPT) +$(DOCKER_SYNCD_BASE)_DBG_DEPENDS += $(SYNCD_DBG) \ + $(LIBSWSSCOMMON_DBG) \ + $(LIBSAIMETADATA_DBG) \ + $(LIBSAIREDIS_DBG) + +$(DOCKER_SYNCD_BASE)_RUN_OPT += -v /host/warmboot:/var/warmboot +$(DOCKER_SYNCD_CENTEC)_RUN_OPT += --privileged -t +$(DOCKER_SYNCD_CENTEC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf +$(DOCKER_SYNCD_CENTEC)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd +$(DOCKER_SYNCD_CENTEC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro diff --git a/platform/centec-arm64/docker-syncd-centec/Dockerfile.j2 b/platform/centec-arm64/docker-syncd-centec/Dockerfile.j2 new file mode 100755 index 000000000000..5f516d8334ef --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec/Dockerfile.j2 @@ -0,0 +1,38 @@ +FROM docker-config-engine-stretch + +ARG docker_container_name +RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name#%syslogtag%/;" /etc/rsyslog.conf + +## Make apt-get non-interactive +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update + +COPY \ +{% for deb in docker_syncd_centec_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor -%} +debs/ + +RUN apt-get update \ + && apt-get -y install \ + net-tools \ + iputils-ping + +RUN apt-get -y install libpcap-dev libxml2-dev python-dev swig libsensors4-dev libjemalloc1 nfs-common + +RUN dpkg -i \ +{% for deb in docker_syncd_centec_debs.split(' ') -%} +debs/{{ deb }}{{' '}} +{%- endfor %} + +COPY ["start.sh", "syncd.sh", "/usr/bin/"] +COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] +COPY ["files/supervisor-proc-exit-listener", "/usr/bin"] +COPY ["critical_processes", "/etc/supervisor/"] + +## Clean up +RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y +RUN rm -rf /debs + +ENTRYPOINT ["/usr/bin/supervisord"] diff --git a/platform/centec-arm64/docker-syncd-centec/critical_processes b/platform/centec-arm64/docker-syncd-centec/critical_processes new file mode 100644 index 000000000000..6082f242b872 --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec/critical_processes @@ -0,0 +1 @@ +syncd diff --git a/platform/centec-arm64/docker-syncd-centec/start.sh b/platform/centec-arm64/docker-syncd-centec/start.sh new file mode 100755 index 000000000000..623316050475 --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec/start.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +rm -f /var/run/rsyslogd.pid + +supervisorctl start rsyslogd + +supervisorctl start syncd diff --git a/platform/centec-arm64/docker-syncd-centec/supervisord.conf b/platform/centec-arm64/docker-syncd-centec/supervisord.conf new file mode 100755 index 000000000000..1af5d70a1d0c --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec/supervisord.conf @@ -0,0 +1,28 @@ +[supervisord] +logfile_maxbytes=1MB +logfile_backups=2 +nodaemon=true + +[program:start.sh] +command=/usr/bin/start.sh +priority=1 +autostart=true +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:rsyslogd] +command=/usr/sbin/rsyslogd -n +priority=2 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog + +[program:syncd] +command=/usr/bin/syncd_start.sh +priority=3 +autostart=false +autorestart=false +stdout_logfile=syslog +stderr_logfile=syslog diff --git a/platform/centec-arm64/docker-syncd-centec/syncd.sh b/platform/centec-arm64/docker-syncd-centec/syncd.sh new file mode 100755 index 000000000000..993cf100f2f0 --- /dev/null +++ b/platform/centec-arm64/docker-syncd-centec/syncd.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +function clean_up { + service syncd stop + exit +} + +trap clean_up SIGTERM SIGKILL + +service syncd start + +read diff --git a/platform/centec-arm64/libsaithrift-dev.mk b/platform/centec-arm64/libsaithrift-dev.mk new file mode 100755 index 000000000000..5b63dbbf7a29 --- /dev/null +++ b/platform/centec-arm64/libsaithrift-dev.mk @@ -0,0 +1,20 @@ +# libsaithrift-dev package + +SAI_VER = 0.9.4 + +LIBSAITHRIFT_DEV = libsaithrift-dev_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(LIBSAITHRIFT_DEV)_SRC_PATH = $(SRC_PATH)/sonic-sairedis/SAI +$(LIBSAITHRIFT_DEV)_DEPENDS += $(LIBTHRIFT) $(LIBTHRIFT_DEV) $(PYTHON_THRIFT) $(THRIFT_COMPILER) $(CENTEC_SAI) +$(LIBSAITHRIFT_DEV)_RDEPENDS += $(LIBTHRIFT) $(CENTEC_SAI) +SONIC_DPKG_DEBS += $(LIBSAITHRIFT_DEV) + +PYTHON_SAITHRIFT = python-saithrift_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(PYTHON_SAITHRIFT))) + +SAISERVER = saiserver_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(SAISERVER)_RDEPENDS += $(LIBTHRIFT) $(CENTEC_SAI) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER))) + +SAISERVER_DBG = saiserver-dbg_$(SAI_VER)_$(CONFIGURED_ARCH).deb +$(SAISERVER_DBG)_RDEPENDS += $(SAISERVER) +$(eval $(call add_extra_package,$(LIBSAITHRIFT_DEV),$(SAISERVER_DBG))) diff --git a/platform/centec-arm64/linux-kernel-arm64.mk b/platform/centec-arm64/linux-kernel-arm64.mk new file mode 100755 index 000000000000..de1371ce27b9 --- /dev/null +++ b/platform/centec-arm64/linux-kernel-arm64.mk @@ -0,0 +1,6 @@ +# linux kernel package for centec arm64 + +LINUX_KERNEL_DTB_INITRAMFS = linux-dtb-initramfs.deb +$(LINUX_KERNEL_DTB_INITRAMFS)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/$(PLATFORM_ARCH)/kernel/$(LINUX_KERNEL_DTB_INITRAMFS) +SONIC_ONLINE_DEBS += $(LINUX_KERNEL_DTB_INITRAMFS) +SONIC_STRETCH_DEBS += $(LINUX_KERNEL_DTB_INITRAMFS) diff --git a/platform/centec-arm64/one-image.mk b/platform/centec-arm64/one-image.mk new file mode 100755 index 000000000000..72ffc135997e --- /dev/null +++ b/platform/centec-arm64/one-image.mk @@ -0,0 +1,18 @@ +# sonic centec one image installer + +SONIC_ONE_IMAGE = sonic-centec-arm64.bin +$(SONIC_ONE_IMAGE)_MACHINE = centec-arm64 +$(SONIC_ONE_IMAGE)_IMAGE_TYPE = onie + +$(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR) +$(SONIC_ONE_IMAGE)_INSTALLS += $(LINUX_KERNEL_DTB_INITRAMFS) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_48T4X_P_PLATFORM_MODULE) +$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_24X2C_PLATFORM_MODULE) + +ifeq ($(INSTALL_DEBUG_TOOLS),y) +$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) +$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES)) +else +$(SONIC_ONE_IMAGE)_DOCKERS = $(SONIC_INSTALL_DOCKER_IMAGES) +endif +SONIC_INSTALLERS += $(SONIC_ONE_IMAGE) diff --git a/platform/centec-arm64/platform-modules-centec-e530.mk b/platform/centec-arm64/platform-modules-centec-e530.mk new file mode 100644 index 000000000000..861105d47956 --- /dev/null +++ b/platform/centec-arm64/platform-modules-centec-e530.mk @@ -0,0 +1,19 @@ +# Centec E530-48T4X-P Platform modules + + +CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION =1.1 +CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION =1.1 + +export CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION + +CENTEC_E530_48T4X_P_PLATFORM_MODULE = platform-modules-e530-48t4x-p_$(CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION)_arm64.deb + +$(CENTEC_E530_48T4X_P_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-e530 +$(CENTEC_E530_48T4X_P_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_48t4x_p-r0 +$(CENTEC_E530_48T4X_P_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON) +SONIC_STRETCH_DEBS += $(CENTEC_E530_48T4X_P_PLATFORM_MODULE) +SONIC_DPKG_DEBS += $(CENTEC_E530_48T4X_P_PLATFORM_MODULE) + +CENTEC_E530_24X2C_PLATFORM_MODULE = platform-modules-e530-24x2c_$(CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION)_arm64.deb +$(CENTEC_E530_24X2C_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_24x2c-r0 +$(eval $(call add_extra_package,$(CENTEC_E530_48T4X_P_PLATFORM_MODULE),$(CENTEC_E530_24X2C_PLATFORM_MODULE))) diff --git a/platform/centec-arm64/platform.conf b/platform/centec-arm64/platform.conf new file mode 100755 index 000000000000..10aaa84b383c --- /dev/null +++ b/platform/centec-arm64/platform.conf @@ -0,0 +1,128 @@ +# Copyright (C) Centec Inc + +# over ride default behaviour + +echo "Preparing for installation ... " + +demo_mount=/mnt/flash/debian + +install_uimage() { + if [ ! -d /mnt/flash ]; then + mkdir /mnt/flash + fi + + echo "mount /mnt/flash" + mount -t ext4 /dev/mmcblk0p1 /mnt/flash + + rm /mnt/flash/debian -rf + + if [ ! -d /mnt/flash/debian ]; then + mkdir /mnt/flash/debian + fi + if [ ! -d /mnt/flash/boot ]; then + mkdir /mnt/flash/boot + fi + + echo "mount /mnt/flash/boot" + mount -t ext4 /dev/mmcblk0p2 /mnt/flash/boot + + # Build debian rootfs install environment + if [ ! -d $demo_mount/.overlay_ro ]; then + mkdir $demo_mount/.overlay_ro + fi + if [ ! -d $demo_mount/.overlay_rw ]; then + mkdir $demo_mount/.overlay_rw + fi + if [ ! -d $demo_mount/.overlay_work ]; then + mkdir $demo_mount/.overlay_work + fi + if [ ! -d $demo_mount/.rootfs_dir ]; then + mkdir $demo_mount/.rootfs_dir + fi + if [ ! -d $demo_mount/.docker ]; then + mkdir $demo_mount/.docker + fi + + # Decompress the file for the file system directly to the partition + unzip -o $ONIE_INSTALLER_PAYLOAD -x "$FILESYSTEM_DOCKERFS" -d $demo_mount + + ## Install mini uImage to boot sonic debian OS + board_type="`fw_printenv | grep ^onie_platform= | awk -F = '{print $2}'`" + if [ "$board_type" == "arm64-centec_e530_48t4x_p-r0" ] || [ "$board_type" == "arm64-centec_e530_24x2c-r0" ]; then + rm /mnt/flash/boot/centec-e530.itb -rf + #cd $demo_mount/boot/ + #mv vmlinuz* Image + #gzip -c Image > Image.gz + #mkimage -f centec-e530.its centec-e530.itb + #cd - + cp $demo_mount/boot/sonic_arm64.fit /mnt/flash/boot/centec-e530.itb + cd /mnt/flash/boot + rm onie_uimage -rf + ln -s centec-e530.itb onie_uimage + cd - + fi + + # Mount debian rootfs + losetup /dev/loop0 $demo_mount/fs.squashfs + mount /dev/loop0 $demo_mount/.overlay_ro + mount -t overlay overlay -o lowerdir=/mnt/flash/debian/.overlay_ro,upperdir=/mnt/flash/debian/.overlay_rw,workdir=/mnt/flash/debian/.overlay_work /mnt/flash/debian/.rootfs_dir + + # unzip dockerfs to sonic debian roootfs + if [ ! -d $demo_mount/.rootfs_dir/var/lib/$DOCKERFS_DIR ]; then + mkdir $demo_mount/.rootfs_dir/var/lib/$DOCKERFS_DIR + fi + mount --bind $demo_mount/.docker /mnt/flash/debian/.rootfs_dir/var/lib/$DOCKERFS_DIR + unzip -op $ONIE_INSTALLER_PAYLOAD "$FILESYSTEM_DOCKERFS" | tar -xpz -f - -C $demo_mount/.docker + + # copy config files to rootfs + echo 'machine=centec-arm64' > /mnt/flash/debian/.rootfs_dir/host/machine.conf + fw_printenv | grep '^onie_platform=' >> /mnt/flash/debian/.rootfs_dir/host/machine.conf + SONIC_VERSION=`chroot /mnt/flash/debian/.rootfs_dir /usr/local/bin/sonic-cfggen -y /etc/sonic/sonic_version.yml -v build_version` + chroot /mnt/flash/debian/.rootfs_dir mkdir -p /host/image-$SONIC_VERSION/ + cp $demo_mount/platform /mnt/flash/debian/.rootfs_dir/host/image-$SONIC_VERSION/ -rf + + # install centec platform modules + #PKG_NAME="platform-modules-"`fw_printenv | grep ^onie_machine= | awk -F _ '{print $3 "-" $4}'` + #PKG_DIR="/platform/arm64-"`fw_printenv | grep ^onie_machine= | awk -F = '{print $2}'`"-r0" + #DEB_NAME=$PKG_NAME"_1.1_arm64.deb" + #chroot /mnt/flash/debian/.rootfs_dir dpkg -i $PKG_DIR/$DEB_NAME + + # sync filesystem + sync + umount -l /mnt/flash/boot + umount -l /mnt/flash + sync + sync + + echo "Reboot board to boot from installed OS" +} + +hw_load() { + echo "ext4load mmc 0:2 \$loadaddr onie_uimage && run onie_args && bootm" +} + + +install_uimage + +hw_load_str="$(hw_load)" + +echo "Updating U-Boot environment variables" +(cat < /tmp/env.txt + +fw_setenv -f -s /tmp/env.txt + +cd / + +# Set NOS mode if available. For manufacturing diag installers, you +# probably want to skip this step so that the system remains in ONIE +# "installer" mode for installing a true NOS later. +if [ -x /bin/onie-nos-mode ] ; then + /bin/onie-nos-mode -s +fi + +exit 0 diff --git a/platform/centec-arm64/rules.mk b/platform/centec-arm64/rules.mk new file mode 100755 index 000000000000..71586513f21c --- /dev/null +++ b/platform/centec-arm64/rules.mk @@ -0,0 +1,18 @@ +include $(PLATFORM_PATH)/sai.mk +include $(PLATFORM_PATH)/docker-syncd-centec.mk +include $(PLATFORM_PATH)/docker-syncd-centec-rpc.mk +include $(PLATFORM_PATH)/one-image.mk +include $(PLATFORM_PATH)/libsaithrift-dev.mk +include $(PLATFORM_PATH)/docker-ptf-centec.mk +include $(PLATFORM_PATH)/linux-kernel-arm64.mk +include $(PLATFORM_PATH)/platform-modules-centec-e530.mk + +SONIC_ALL += $(SONIC_ONE_IMAGE) \ + $(DOCKER_FPM) +# $(DOCKER_SYNCD_CENTEC_RPC) + +# Inject centec sai into sairedis +$(LIBSAIREDIS)_DEPENDS += $(CENTEC_SAI) $(LIBSAITHRIFT_DEV_CENTEC) + +# Runtime dependency on centec sai is set only for syncd +$(SYNCD)_RDEPENDS += $(CENTEC_SAI) diff --git a/platform/centec-arm64/sai.mk b/platform/centec-arm64/sai.mk new file mode 100755 index 000000000000..096b3954a890 --- /dev/null +++ b/platform/centec-arm64/sai.mk @@ -0,0 +1,8 @@ +# Centec SAI + +export CENTEC_SAI_VERSION = 1.5.1-1.0 +export CENTEC_SAI = libsai_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb + +$(CENTEC_SAI)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI) +SONIC_ONLINE_DEBS += $(CENTEC_SAI) +SONIC_STRETCH_DEBS += $(CENTEC_SAI) \ No newline at end of file diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/classes/__init__.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/modules/Makefile b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/modules/Makefile new file mode 100644 index 000000000000..c1beeaa15c68 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/modules/Makefile @@ -0,0 +1 @@ +obj-m := centec_e530_24x2c_platform.o diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/modules/centec_e530_24x2c_platform.c b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/modules/centec_e530_24x2c_platform.c new file mode 100644 index 000000000000..a357b90313f3 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/modules/centec_e530_24x2c_platform.c @@ -0,0 +1,1111 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SEP(XXX) 1 +#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_)) +#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_)) + +#if SEP("defines") +#define SFP_NUM 24 +#define QSFP_NUM 2 +#define PORT_NUM (SFP_NUM + QSFP_NUM) +#endif + +#if SEP("i2c:smbus") +static int e530_24x2c_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret >= 0) { + *value = (unsigned char)ret; + } + else + { + *value = 0; + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} + +static int e530_24x2c_smbus_write_reg(struct i2c_client *client, unsigned char reg, unsigned char value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_write_byte_data(client, reg, value); + if (ret != 0) + { + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} +#endif + +#if SEP("i2c:master") +static struct i2c_adapter *i2c_adp_master = NULL; /* i2c-1-cpu */ + +static int e530_24x2c_init_i2c_master(void) +{ + /* find i2c-core master */ + i2c_adp_master = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_master)) + { + i2c_adp_master = NULL; + printk(KERN_CRIT "e530_24x2c_init_i2c_master can't find i2c-core bus\n"); + return -1; + } + + return 0; +} + +static int e530_24x2c_exit_i2c_master(void) +{ + /* uninstall i2c-core master */ + if(IS_VALID_PTR(i2c_adp_master)) { + i2c_put_adapter(i2c_adp_master); + i2c_adp_master = NULL; + } + + return 0; +} +#endif + +#if SEP("i2c:gpio") +static struct i2c_adapter *i2c_adp_gpio0 = NULL; /* gpio0 */ +static struct i2c_adapter *i2c_adp_gpio1 = NULL; /* gpio1 */ +static struct i2c_adapter *i2c_adp_gpio2 = NULL; /* gpio2 */ +static struct i2c_board_info i2c_dev_gpio0 = { + I2C_BOARD_INFO("i2c-gpio0", 0x21), +}; +static struct i2c_board_info i2c_dev_gpio1 = { + I2C_BOARD_INFO("i2c-gpio1", 0x22), +}; +static struct i2c_board_info i2c_dev_gpio2 = { + I2C_BOARD_INFO("i2c-gpio2", 0x23), +}; +static struct i2c_client *i2c_client_gpio0 = NULL; +static struct i2c_client *i2c_client_gpio1 = NULL; +static struct i2c_client *i2c_client_gpio2 = NULL; + +static int e530_24x2c_init_i2c_gpio(void) +{ + int ret = 0; + + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e530_24x2c_init_i2c_gpio can't find i2c-core bus\n"); + return -1; + } + + i2c_adp_gpio0 = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_gpio0)) + { + i2c_adp_gpio0 = NULL; + printk(KERN_CRIT "get e530_24x2c gpio0 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio0 = i2c_new_device(i2c_adp_gpio0, &i2c_dev_gpio0); + if(IS_INVALID_PTR(i2c_client_gpio0)) + { + i2c_client_gpio0 = NULL; + printk(KERN_CRIT "create e530_24x2c board i2c client gpio0 failed\n"); + return -1; + } + + i2c_adp_gpio1 = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_gpio1)) + { + i2c_adp_gpio1 = NULL; + printk(KERN_CRIT "get e530_24x2c gpio1 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio1 = i2c_new_device(i2c_adp_gpio1, &i2c_dev_gpio1); + if(IS_INVALID_PTR(i2c_client_gpio1)) + { + i2c_client_gpio1 = NULL; + printk(KERN_CRIT "create e530_24x2c board i2c client gpio1 failed\n"); + return -1; + } + + i2c_adp_gpio2 = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_gpio2)) + { + i2c_adp_gpio2 = NULL; + printk(KERN_CRIT "get e530_24x2c gpio2 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio2 = i2c_new_device(i2c_adp_gpio2, &i2c_dev_gpio2); + if(IS_INVALID_PTR(i2c_client_gpio2)) + { + i2c_client_gpio2 = NULL; + printk(KERN_CRIT "create e530_24x2c board i2c client gpio2 failed\n"); + return -1; + } + + /* gpio0 */ + ret = e530_24x2c_smbus_write_reg(i2c_client_gpio0, 0x02, 0x00); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio0, 0x03, 0x00); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio0, 0x06, 0x00); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio0, 0x07, 0x00); + /* gpio1 */ + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio1, 0x02, 0xbf); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio1, 0x03, 0xff); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio1, 0x06, 0x0c); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio1, 0x07, 0xff); + /* gpio2 */ + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio2, 0x02, 0x00); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio2, 0x03, 0xff); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio2, 0x06, 0x00); + ret += e530_24x2c_smbus_write_reg(i2c_client_gpio2, 0x07, 0xff); + + if (ret) + { + printk(KERN_CRIT "init e530_24x2c board i2c gpio config failed\n"); + return -1; + } + + return 0; +} + +static int e530_24x2c_exit_i2c_gpio(void) +{ + if(IS_VALID_PTR(i2c_client_gpio0)) { + i2c_unregister_device(i2c_client_gpio0); + i2c_client_gpio0 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio0)) + { + i2c_put_adapter(i2c_adp_gpio0); + i2c_adp_gpio0 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio1)) { + i2c_unregister_device(i2c_client_gpio1); + i2c_client_gpio1 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio1)) + { + i2c_put_adapter(i2c_adp_gpio1); + i2c_adp_gpio1 = NULL; + } + + if(IS_VALID_PTR(i2c_client_gpio2)) { + i2c_unregister_device(i2c_client_gpio2); + i2c_client_gpio2 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio2)) + { + i2c_put_adapter(i2c_adp_gpio2); + i2c_adp_gpio2 = NULL; + } + + return 0; +} +#endif + + +#if SEP("drivers:psu") +static struct class* psu_class = NULL; +static struct device* psu_dev_psu1 = NULL; +static struct device* psu_dev_psu2 = NULL; + +static ssize_t e530_24x2c_psu_read_presence(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char present_no = 0; + unsigned char present = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio1; + present_no = 9; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio1; + present_no = 13; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e530_24x2c_smbus_read_reg(i2c_psu_client, present_no/8, &present); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((present & (1<<(present_no%8))) ? 1 : 0 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e530_24x2c_psu_read_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char workstate_no = 0; + unsigned char workstate = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio1; + workstate_no = 11; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio1; + workstate_no = 15; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e530_24x2c_smbus_read_reg(i2c_psu_client, workstate_no/8, &workstate); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((workstate & (1<<(workstate_no%8))) ? 0 : 1 ); + + return sprintf(buf, "%d\n", value); +} + +static DEVICE_ATTR(psu_presence, S_IRUGO, e530_24x2c_psu_read_presence, NULL); +static DEVICE_ATTR(psu_status, S_IRUGO, e530_24x2c_psu_read_status, NULL); + +static int e530_24x2c_init_psu(void) +{ + int ret = 0; + + psu_class = class_create(THIS_MODULE, "psu"); + if (IS_INVALID_PTR(psu_class)) + { + psu_class = NULL; + printk(KERN_CRIT "create e530_24x2c class psu failed\n"); + return -1; + } + + psu_dev_psu1 = device_create(psu_class, NULL, MKDEV(222,0), NULL, "psu1"); + if (IS_INVALID_PTR(psu_dev_psu1)) + { + psu_dev_psu1 = NULL; + printk(KERN_CRIT "create e530_24x2c psu1 device failed\n"); + return -1; + } + + psu_dev_psu2 = device_create(psu_class, NULL, MKDEV(222,1), NULL, "psu2"); + if (IS_INVALID_PTR(psu_dev_psu2)) + { + psu_dev_psu2 = NULL; + printk(KERN_CRIT "create e530_24x2c psu2 device failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c psu1 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c psu1 device attr:status failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c psu2 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c psu2 device attr:status failed\n"); + return -1; + } + + return 0; +} + +static int e530_24x2c_exit_psu(void) +{ + if (IS_VALID_PTR(psu_dev_psu1)) + { + device_remove_file(psu_dev_psu1, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu1, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,0)); + } + + if (IS_VALID_PTR(psu_dev_psu2)) + { + device_remove_file(psu_dev_psu2, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu2, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,1)); + } + + if (IS_VALID_PTR(psu_class)) + { + class_destroy(psu_class); + psu_class = NULL; + } + + return 0; +} +#endif + +#if SEP("drivers:leds") +extern void e530_24x2c_led_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e530_24x2c_led_get(struct led_classdev *led_cdev); +extern void e530_24x2c_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e530_24x2c_led_port_get(struct led_classdev *led_cdev); + +static struct led_classdev led_dev_system = { + .name = "system", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_idn = { + .name = "idn", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_fan1 = { + .name = "fan1", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_fan2 = { + .name = "fan2", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_fan3 = { + .name = "fan3", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_fan4 = { + .name = "fan4", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_psu1 = { + .name = "psu1", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_psu2 = { + .name = "psu2", + .brightness_set = e530_24x2c_led_set, + .brightness_get = e530_24x2c_led_get, +}; +static struct led_classdev led_dev_port[PORT_NUM] = { +{ .name = "port1", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port2", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port3", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port4", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port5", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port6", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port7", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port8", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port9", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port10", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port11", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port12", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port13", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port14", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port15", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port16", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port17", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port18", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port19", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port20", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port21", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port22", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port23", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port24", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port25", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +{ .name = "port26", .brightness_set = e530_24x2c_led_port_set, .brightness_get = e530_24x2c_led_port_get,}, +}; +static unsigned char port_led_mode[PORT_NUM] = {0}; + +void e530_24x2c_led_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_gpio1; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x60; + shift = 5; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x10; + shift = 4; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e530_24x2c_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return; + } + + led_value = ((led_value & (~mask)) | ((set_value << shift) & (mask))); + + ret = e530_24x2c_smbus_write_reg(i2c_led_client, reg, led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s led attr failed\n", led_cdev->name); + return; + } + + return; + +not_support: + + printk(KERN_INFO "Error: led not support device:%s\n", led_cdev->name); + return; +} + +enum led_brightness e530_24x2c_led_get(struct led_classdev *led_cdev) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_gpio0; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x60; + shift = 5; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x10; + shift = 4; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e530_24x2c_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return 0; + } + + led_value = ((led_value & mask) >> shift); + + return led_value; + +not_support: + + printk(KERN_INFO "Error: not support device:%s\n", led_cdev->name); + return 0; +} + +void e530_24x2c_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + port_led_mode[portNum-1] = set_value; + + return; +} + +enum led_brightness e530_24x2c_led_port_get(struct led_classdev *led_cdev) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + return port_led_mode[portNum-1]; +} + +static int e530_24x2c_init_led(void) +{ + int ret = 0; + int i = 0; + + ret = led_classdev_register(NULL, &led_dev_system); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_system device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_idn); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_idn device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan1); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_fan1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan2); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_fan2 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan3); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_fan3 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan4); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_fan4 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu1); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_psu1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu2); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c led_dev_psu2 device failed\n"); + return -1; + } + + for (i=0; i SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + buf[0] = '\0'; + return 0; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + presence = sfp_info[portNum].presence; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + return sprintf(buf, "%d\n", presence); +} + +static ssize_t e530_24x2c_sfp_write_presence(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + int presence = simple_strtol(buf, NULL, 10); + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + return size; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + sfp_info[portNum].presence = presence; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static ssize_t e530_24x2c_sfp_read_enable(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char value = 0; + unsigned char reg_no = 0; + unsigned char input_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + unsigned long flags = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read enable, invalid port number!\n"); + value = 0; + } + + if (portNum <= SFP_NUM) + { + if (portNum >= 1 && portNum <= 16) + { + reg_no = portNum - 1; + i2c_sfp_client = i2c_client_gpio0; + } + else if (portNum > 16 && portNum <= 24) + { + reg_no = portNum - 17; + i2c_sfp_client = i2c_client_gpio2; + } + + input_bank = (reg_no/8) + 0x2; + ret = e530_24x2c_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp enable: %s failed\n", attr->attr.name); + } + + value = ((value & (1<<(reg_no%8))) ? 0 : 1 ); + } + else + { + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + value = sfp_info[portNum].enable; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + } + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e530_24x2c_sfp_write_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + unsigned char value = 0; + unsigned char set_value = simple_strtol(buf, NULL, 10); + unsigned char reg_no = 0; + unsigned char input_bank = 0; + unsigned char output_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + unsigned long flags = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read enable, invalid port number!\n"); + return size; + } + + if (portNum <= SFP_NUM) + { + if (portNum >= 1 && portNum <= 16) + { + reg_no = portNum - 1; + i2c_sfp_client = i2c_client_gpio0; + } + else if (portNum > 16 && portNum <= 24) + { + reg_no = portNum - 17; + i2c_sfp_client = i2c_client_gpio2; + } + + set_value = ((set_value > 0) ? 0 : 1); + + input_bank = (reg_no/8) + 0x2; + ret = e530_24x2c_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s enable failed\n", name); + return size; + } + + if (set_value) + { + value = (value | (1<<(reg_no % 8))); + } + else + { + value = (value & (~(1<<(reg_no % 8)))); + } + + output_bank = (reg_no/8) + 0x2; + ret = e530_24x2c_smbus_write_reg(i2c_sfp_client, output_bank, value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s enable failed\n", name); + return size; + } + } + else + { + set_value = ((set_value > 0) ? 1 : 0); + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + sfp_info[portNum].enable = set_value; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + } + + return size; +} + +static ssize_t e530_24x2c_sfp_read_eeprom(struct device *dev, struct device_attribute *attr, char *buf) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + size_t size = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp read eeprom, invalid port number!\n"); + buf[0] = '\0'; + return 0; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + memcpy(buf, sfp_info[portNum].eeprom[0], sfp_info[portNum].data_len[0]); + size = sfp_info[portNum].data_len[0]; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static ssize_t e530_24x2c_sfp_write_eeprom(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM+QSFP_NUM)) + { + printk(KERN_CRIT "sfp write eeprom, invalid port number!\n"); + return size; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + memcpy(sfp_info[portNum].eeprom[0], buf, size); + sfp_info[portNum].data_len[0] = size; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static DEVICE_ATTR(sfp_presence, S_IRUGO|S_IWUSR, e530_24x2c_sfp_read_presence, e530_24x2c_sfp_write_presence); +static DEVICE_ATTR(sfp_enable, S_IRUGO|S_IWUSR, e530_24x2c_sfp_read_enable, e530_24x2c_sfp_write_enable); +static DEVICE_ATTR(sfp_eeprom, S_IRUGO|S_IWUSR, e530_24x2c_sfp_read_eeprom, e530_24x2c_sfp_write_eeprom); + +static int e530_24x2c_init_sfp(void) +{ + int ret = 0; + int i = 0; + + sfp_class = class_create(THIS_MODULE, "sfp"); + if (IS_INVALID_PTR(sfp_class)) + { + sfp_class = NULL; + printk(KERN_CRIT "create e530_24x2c class sfp failed\n"); + return -1; + } + + for (i=1; i<=SFP_NUM+QSFP_NUM; i++) + { + memset(&(sfp_info[i].eeprom), 0, sizeof(sfp_info[i].eeprom)); + memset(&(sfp_info[i].data_len), 0, sizeof(sfp_info[i].data_len)); + spin_lock_init(&(sfp_info[i].lock)); + + sfp_dev[i] = device_create(sfp_class, NULL, MKDEV(223,i), NULL, "sfp%d", i); + if (IS_INVALID_PTR(sfp_dev[i])) + { + sfp_dev[i] = NULL; + printk(KERN_CRIT "create e530_24x2c sfp[%d] device failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c sfp[%d] device attr:presence failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_enable); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c sfp[%d] device attr:enable failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_eeprom); + if (ret != 0) + { + printk(KERN_CRIT "create e530_24x2c sfp[%d] device attr:eeprom failed\n", i); + continue; + } + } + + return ret; +} + +static int e530_24x2c_exit_sfp(void) +{ + int i = 0; + + for (i=1; i<=SFP_NUM+QSFP_NUM; i++) + { + if (IS_VALID_PTR(sfp_dev[i])) + { + device_remove_file(sfp_dev[i], &dev_attr_sfp_presence); + device_remove_file(sfp_dev[i], &dev_attr_sfp_enable); + device_remove_file(sfp_dev[i], &dev_attr_sfp_eeprom); + device_destroy(sfp_class, MKDEV(223,i)); + sfp_dev[i] = NULL; + } + } + + if (IS_VALID_PTR(sfp_class)) + { + class_destroy(sfp_class); + sfp_class = NULL; + } + + return 0; +} +#endif + +static int e530_24x2c_init(void) +{ + int ret = 0; + int failed = 0; + + printk(KERN_ALERT "install e530_24x2c board dirver...\n"); + + ret = e530_24x2c_init_i2c_master(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_24x2c_init_i2c_gpio(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_24x2c_init_psu(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_24x2c_init_led(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_24x2c_init_sfp(); + if (ret != 0) + { + failed = 1; + } + + if (failed) + printk(KERN_INFO "install e530_24x2c board driver failed\n"); + else + printk(KERN_ALERT "install e530_24x2c board dirver...ok\n"); + + return 0; +} + +static void e530_24x2c_exit(void) +{ + printk(KERN_INFO "uninstall e530_24x2c board dirver...\n"); + + e530_24x2c_exit_sfp(); + e530_24x2c_exit_led(); + e530_24x2c_exit_psu(); + e530_24x2c_exit_i2c_gpio(); + e530_24x2c_exit_i2c_master(); +} + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("shil centecNetworks, Inc"); +MODULE_DESCRIPTION("e530-24x2c board driver"); +module_init(e530_24x2c_init); +module_exit(e530_24x2c_exit); diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/service/24x2c_platform.service b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/service/24x2c_platform.service new file mode 100644 index 000000000000..50e35ad601cb --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/service/24x2c_platform.service @@ -0,0 +1,13 @@ +[Unit] +Description=Centec modules init +After=local-fs.target +Before=syncd.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-e530-24x2c start +ExecStop=-/etc/init.d/platform-modules-e530-24x2c stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec-arm64/sonic-platform-modules-e530/24x2c/setup.py b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/setup.py new file mode 100755 index 000000000000..48e03a0d9e90 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/24x2c/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='24x2c', + version='1.1', + description='Module to initialize centec e530-24x2c platforms', + + packages=['24x2c'], + package_dir={'24x2c': '24x2c/classes'}, +) + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/classes/__init__.py b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/classes/__init__.py new file mode 100755 index 000000000000..e69de29bb2d1 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/Makefile b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/Makefile new file mode 100644 index 000000000000..47327a1a0037 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/Makefile @@ -0,0 +1 @@ +obj-m := centec_e530_48t4x_p_platform.o diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/centec_e530_48t4x_p_platform.c b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/centec_e530_48t4x_p_platform.c new file mode 100644 index 000000000000..43c4e5bb54cc --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/modules/centec_e530_48t4x_p_platform.c @@ -0,0 +1,1023 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SEP(XXX) 1 +#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_)) +#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_)) + +#if SEP("defines") +#define SFP_NUM 4 +#define PORT_NUM (48+SFP_NUM) +#endif + +#if SEP("i2c:smbus") +static int e530_48t4x_p_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_read_byte_data(client, reg); + if (ret >= 0) { + *value = (unsigned char)ret; + } + else + { + *value = 0; + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} + +static int e530_48t4x_p_smbus_write_reg(struct i2c_client *client, unsigned char reg, unsigned char value) +{ + int ret = 0; + + if (IS_INVALID_PTR(client)) + { + printk(KERN_CRIT "invalid i2c client"); + return -1; + } + + ret = i2c_smbus_write_byte_data(client, reg, value); + if (ret != 0) + { + printk(KERN_CRIT "i2c_smbus op failed: ret=%d reg=%d\n",ret ,reg); + return ret; + } + + return 0; +} +#endif + +#if SEP("i2c:master") +static struct i2c_adapter *i2c_adp_master = NULL; /* i2c-1-cpu */ + +static int e530_48t4x_p_init_i2c_master(void) +{ + /* find i2c-core master */ + i2c_adp_master = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_master)) + { + i2c_adp_master = NULL; + printk(KERN_CRIT "e530_48t4x_p_init_i2c_master can't find i2c-core bus\n"); + return -1; + } + + return 0; +} + +static int e530_48t4x_p_exit_i2c_master(void) +{ + /* uninstall i2c-core master */ + if(IS_VALID_PTR(i2c_adp_master)) { + i2c_put_adapter(i2c_adp_master); + i2c_adp_master = NULL; + } + + return 0; +} +#endif + +//TODO!!! +#if SEP("i2c:gpio") +static struct i2c_adapter *i2c_adp_gpio0 = NULL; /* gpio0 */ +static struct i2c_board_info i2c_dev_gpio0 = { + I2C_BOARD_INFO("i2c-gpio0", 0x22), +}; +static struct i2c_client *i2c_client_gpio0 = NULL; + +static int e530_48t4x_p_init_i2c_gpio(void) +{ + int ret = 0; + + if (IS_INVALID_PTR(i2c_adp_master)) + { + printk(KERN_CRIT "e530_48t4x_p_init_i2c_gpio can't find i2c-core bus\n"); + return -1; + } + + i2c_adp_gpio0 = i2c_get_adapter(0); + if(IS_INVALID_PTR(i2c_adp_gpio0)) + { + i2c_adp_gpio0 = NULL; + printk(KERN_CRIT "get e530_48t4x_p gpio0 i2c-adp failed\n"); + return -1; + } + + i2c_client_gpio0 = i2c_new_device(i2c_adp_gpio0, &i2c_dev_gpio0); + if(IS_INVALID_PTR(i2c_client_gpio0)) + { + i2c_client_gpio0 = NULL; + printk(KERN_CRIT "create e530_48t4x_p board i2c client gpio0 failed\n"); + return -1; + } + + /* gpio0 */ + /* tx enable and release mac led and close indicate led */ + ret = e530_48t4x_p_smbus_write_reg(i2c_client_gpio0, 0x02, 0xf0); + /* bank 0 : output bank 1 : input */ + ret += e530_48t4x_p_smbus_write_reg(i2c_client_gpio0, 0x06, 0x00); + ret += e530_48t4x_p_smbus_write_reg(i2c_client_gpio0, 0x07, 0xff); + + if (ret) + { + printk(KERN_CRIT "init e530_48t4x_p board i2c gpio config failed\n"); + return -1; + } + + return 0; +} + +static int e530_48t4x_p_exit_i2c_gpio(void) +{ + if(IS_VALID_PTR(i2c_client_gpio0)) { + i2c_unregister_device(i2c_client_gpio0); + i2c_client_gpio0 = NULL; + } + + if(IS_VALID_PTR(i2c_adp_gpio0)) + { + i2c_put_adapter(i2c_adp_gpio0); + i2c_adp_gpio0 = NULL; + } + + return 0; +} +#endif + + +#if SEP("drivers:psu") +static struct class* psu_class = NULL; +static struct device* psu_dev_psu1 = NULL; +static struct device* psu_dev_psu2 = NULL; + +static ssize_t e530_48t4x_p_psu_read_presence(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char present_no = 0; + unsigned char present = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio0; + present_no = 9; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio0; + present_no = 13; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e530_48t4x_p_smbus_read_reg(i2c_psu_client, present_no/8, &present); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((present & (1<<(present_no%8))) ? 1 : 0 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e530_48t4x_p_psu_read_status(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char workstate_no = 0; + unsigned char workstate = 0; + unsigned char value = 0; + struct i2c_client *i2c_psu_client = NULL; + + if (psu_dev_psu1 == dev) + { + i2c_psu_client = i2c_client_gpio0; + workstate_no = 11; + } + else if (psu_dev_psu2 == dev) + { + i2c_psu_client = i2c_client_gpio0; + workstate_no = 15; + } + else + { + return sprintf(buf, "Error: unknown psu device\n"); + } + + if (IS_INVALID_PTR(i2c_psu_client)) + { + return sprintf(buf, "Error: psu i2c-adapter invalid\n"); + } + + ret = e530_48t4x_p_smbus_read_reg(i2c_psu_client, workstate_no/8, &workstate); + if (ret != 0) + { + return sprintf(buf, "Error: read psu data:%s failed\n", attr->attr.name); + } + + value = ((workstate & (1<<(workstate_no%8))) ? 0 : 1 ); + + return sprintf(buf, "%d\n", value); +} + +static DEVICE_ATTR(psu_presence, S_IRUGO, e530_48t4x_p_psu_read_presence, NULL); +static DEVICE_ATTR(psu_status, S_IRUGO, e530_48t4x_p_psu_read_status, NULL); + +static int e530_48t4x_p_init_psu(void) +{ + int ret = 0; + + psu_class = class_create(THIS_MODULE, "psu"); + if (IS_INVALID_PTR(psu_class)) + { + psu_class = NULL; + printk(KERN_CRIT "create e530_48t4x_p class psu failed\n"); + return -1; + } + + psu_dev_psu1 = device_create(psu_class, NULL, MKDEV(222,0), NULL, "psu1"); + if (IS_INVALID_PTR(psu_dev_psu1)) + { + psu_dev_psu1 = NULL; + printk(KERN_CRIT "create e530_48t4x_p psu1 device failed\n"); + return -1; + } + + psu_dev_psu2 = device_create(psu_class, NULL, MKDEV(222,1), NULL, "psu2"); + if (IS_INVALID_PTR(psu_dev_psu2)) + { + psu_dev_psu2 = NULL; + printk(KERN_CRIT "create e530_48t4x_p psu2 device failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p psu1 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu1, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p psu1 device attr:status failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p psu2 device attr:presence failed\n"); + return -1; + } + + ret = device_create_file(psu_dev_psu2, &dev_attr_psu_status); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p psu2 device attr:status failed\n"); + return -1; + } + + return 0; +} + +static int e530_48t4x_p_exit_psu(void) +{ + if (IS_VALID_PTR(psu_dev_psu1)) + { + device_remove_file(psu_dev_psu1, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu1, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,0)); + } + + if (IS_VALID_PTR(psu_dev_psu2)) + { + device_remove_file(psu_dev_psu2, &dev_attr_psu_presence); + device_remove_file(psu_dev_psu2, &dev_attr_psu_status); + device_destroy(psu_class, MKDEV(222,1)); + } + + if (IS_VALID_PTR(psu_class)) + { + class_destroy(psu_class); + psu_class = NULL; + } + + return 0; +} +#endif + +#if SEP("drivers:leds") +extern void e530_48t4x_p_led_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e530_48t4x_p_led_get(struct led_classdev *led_cdev); +extern void e530_48t4x_p_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value); +extern enum led_brightness e530_48t4x_p_led_port_get(struct led_classdev *led_cdev); + +static struct led_classdev led_dev_system = { + .name = "system", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_idn = { + .name = "idn", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_fan1 = { + .name = "fan1", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_fan2 = { + .name = "fan2", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_fan3 = { + .name = "fan3", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_fan4 = { + .name = "fan4", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_psu1 = { + .name = "psu1", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_psu2 = { + .name = "psu2", + .brightness_set = e530_48t4x_p_led_set, + .brightness_get = e530_48t4x_p_led_get, +}; +static struct led_classdev led_dev_port[PORT_NUM] = { +{ .name = "port1", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port2", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port3", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port4", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port5", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port6", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port7", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port8", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port9", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port10", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port11", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port12", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port13", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port14", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port15", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port16", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port17", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port18", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port19", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port20", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port21", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port22", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port23", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port24", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port25", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port26", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port27", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port28", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port29", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port30", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port31", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port32", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port33", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port34", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port35", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port36", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port37", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port38", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port39", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port40", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port41", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port42", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port43", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port44", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port45", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port46", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port47", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port48", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port49", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port50", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port51", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +{ .name = "port52", .brightness_set = e530_48t4x_p_led_port_set, .brightness_get = e530_48t4x_p_led_port_get,}, +}; +static unsigned char port_led_mode[PORT_NUM] = {0}; + +void e530_48t4x_p_led_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_gpio0; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x60; + shift = 5; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x10; + shift = 4; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e530_48t4x_p_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return; + } + + led_value = ((led_value & (~mask)) | ((set_value << shift) & (mask))); + + ret = e530_48t4x_p_smbus_write_reg(i2c_led_client, reg, led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s led attr failed\n", led_cdev->name); + return; + } + + return; + +not_support: + + printk(KERN_INFO "Error: led not support device:%s\n", led_cdev->name); + return; +} + +enum led_brightness e530_48t4x_p_led_get(struct led_classdev *led_cdev) +{ + int ret = 0; + unsigned char reg = 0; + unsigned char mask = 0; + unsigned char shift = 0; + unsigned char led_value = 0; + struct i2c_client *i2c_led_client = i2c_client_gpio0; + + if (0 == strcmp(led_dev_system.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x60; + shift = 5; + } + else if (0 == strcmp(led_dev_idn.name, led_cdev->name)) + { + reg = 0x2; + mask = 0x10; + shift = 4; + } + else if (0 == strcmp(led_dev_fan1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan2.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan3.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_fan4.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu1.name, led_cdev->name)) + { + goto not_support; + } + else if (0 == strcmp(led_dev_psu2.name, led_cdev->name)) + { + goto not_support; + } + else + { + goto not_support; + } + + ret = e530_48t4x_p_smbus_read_reg(i2c_led_client, reg, &led_value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s led attr failed\n", led_cdev->name); + return 0; + } + + led_value = ((led_value & mask) >> shift); + + return led_value; + +not_support: + + printk(KERN_INFO "Error: not support device:%s\n", led_cdev->name); + return 0; +} + +void e530_48t4x_p_led_port_set(struct led_classdev *led_cdev, enum led_brightness set_value) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + port_led_mode[portNum-1] = set_value; + + return; +} + +enum led_brightness e530_48t4x_p_led_port_get(struct led_classdev *led_cdev) +{ + int portNum = 0; + + sscanf(led_cdev->name, "port%d", &portNum); + + return port_led_mode[portNum-1]; +} + +static int e530_48t4x_p_init_led(void) +{ + int ret = 0; + int i = 0; + + ret = led_classdev_register(NULL, &led_dev_system); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_system device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_idn); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_idn device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan1); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_fan1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan2); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_fan2 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan3); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_fan3 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_fan4); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_fan4 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu1); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_psu1 device failed\n"); + return -1; + } + + ret = led_classdev_register(NULL, &led_dev_psu2); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p led_dev_psu2 device failed\n"); + return -1; + } + + for (i=0; i SFP_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + buf[0] = '\0'; + return 0; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + presence = sfp_info[portNum].presence; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + return sprintf(buf, "%d\n", presence); +} + +static ssize_t e530_48t4x_p_sfp_write_presence(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + int presence = simple_strtol(buf, NULL, 10); + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp read presence, invalid port number!\n"); + return size; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + sfp_info[portNum].presence = presence; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static ssize_t e530_48t4x_p_sfp_read_enable(struct device *dev, struct device_attribute *attr, char *buf) +{ + int ret = 0; + unsigned char value = 0; + unsigned char reg_no = 0; + unsigned char input_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp read enable, invalid port number!\n"); + value = 0; + } + + reg_no = portNum - 1; + i2c_sfp_client = i2c_client_gpio0; + + input_bank = (reg_no/8) + 0x2; + ret = e530_48t4x_p_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + return sprintf(buf, "Error: read sfp enable: %s failed\n", attr->attr.name); + } + + value = ((value & (1<<(reg_no%8))) ? 0 : 1 ); + + return sprintf(buf, "%d\n", value); +} + +static ssize_t e530_48t4x_p_sfp_write_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int ret = 0; + unsigned char value = 0; + unsigned char set_value = simple_strtol(buf, NULL, 10); + unsigned char reg_no = 0; + unsigned char input_bank = 0; + unsigned char output_bank = 0; + int portNum = 0; + const char *name = dev_name(dev); + struct i2c_client *i2c_sfp_client = NULL; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp read enable, invalid port number!\n"); + return size; + } + + reg_no = portNum - 1; + i2c_sfp_client = i2c_client_gpio0; + + set_value = ((set_value > 0) ? 0 : 1); + + input_bank = (reg_no/8) + 0x2; + ret = e530_48t4x_p_smbus_read_reg(i2c_sfp_client, input_bank, &value); + if (ret != 0) + { + printk(KERN_CRIT "Error: read %s enable failed\n", name); + return size; + } + + if (set_value) + { + value = (value | (1<<(reg_no % 8))); + } + else + { + value = (value & (~(1<<(reg_no % 8)))); + } + + output_bank = (reg_no/8) + 0x2; + ret = e530_48t4x_p_smbus_write_reg(i2c_sfp_client, output_bank, value); + if (ret != 0) + { + printk(KERN_CRIT "Error: write %s enable failed\n", name); + return size; + } + + return size; +} + +static ssize_t e530_48t4x_p_sfp_read_eeprom(struct device *dev, struct device_attribute *attr, char *buf) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + size_t size = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp read eeprom, invalid port number!\n"); + buf[0] = '\0'; + return 0; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + memcpy(buf, sfp_info[portNum].data, sfp_info[portNum].data_len); + size = sfp_info[portNum].data_len; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static ssize_t e530_48t4x_p_sfp_write_eeprom(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + int portNum = 0; + const char *name = dev_name(dev); + unsigned long flags = 0; + + sscanf(name, "sfp%d", &portNum); + + if ((portNum < 1) || (portNum > SFP_NUM)) + { + printk(KERN_CRIT "sfp write eeprom, invalid port number!\n"); + return size; + } + + spin_lock_irqsave(&(sfp_info[portNum].lock), flags); + memcpy(sfp_info[portNum].data, buf, size); + sfp_info[portNum].data_len = size; + spin_unlock_irqrestore(&(sfp_info[portNum].lock), flags); + + return size; +} + +static DEVICE_ATTR(sfp_presence, S_IRUGO|S_IWUSR, e530_48t4x_p_sfp_read_presence, e530_48t4x_p_sfp_write_presence); +static DEVICE_ATTR(sfp_enable, S_IRUGO|S_IWUSR, e530_48t4x_p_sfp_read_enable, e530_48t4x_p_sfp_write_enable); +static DEVICE_ATTR(sfp_eeprom, S_IRUGO|S_IWUSR, e530_48t4x_p_sfp_read_eeprom, e530_48t4x_p_sfp_write_eeprom); +static int e530_48t4x_p_init_sfp(void) +{ + int ret = 0; + int i = 0; + + sfp_class = class_create(THIS_MODULE, "sfp"); + if (IS_INVALID_PTR(sfp_class)) + { + sfp_class = NULL; + printk(KERN_CRIT "create e530_48t4x_p class sfp failed\n"); + return -1; + } + + for (i=1; i<=SFP_NUM; i++) + { + memset(&(sfp_info[i].data), 0, MAX_SFP_EEPROM_DATA_LEN+1); + sfp_info[i].data_len = 0; + spin_lock_init(&(sfp_info[i].lock)); + + sfp_dev[i] = device_create(sfp_class, NULL, MKDEV(223,i), NULL, "sfp%d", i); + if (IS_INVALID_PTR(sfp_dev[i])) + { + sfp_dev[i] = NULL; + printk(KERN_CRIT "create e530_48t4x_p sfp[%d] device failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_presence); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p sfp[%d] device attr:presence failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_enable); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p sfp[%d] device attr:enable failed\n", i); + continue; + } + + ret = device_create_file(sfp_dev[i], &dev_attr_sfp_eeprom); + if (ret != 0) + { + printk(KERN_CRIT "create e530_48t4x_p sfp[%d] device attr:eeprom failed\n", i); + continue; + } + } + + return ret; +} + +static int e530_48t4x_p_exit_sfp(void) +{ + int i = 0; + + for (i=1; i<=SFP_NUM; i++) + { + if (IS_VALID_PTR(sfp_dev[i])) + { + device_remove_file(sfp_dev[i], &dev_attr_sfp_presence); + device_remove_file(sfp_dev[i], &dev_attr_sfp_enable); + device_remove_file(sfp_dev[i], &dev_attr_sfp_eeprom); + device_destroy(sfp_class, MKDEV(223,i)); + sfp_dev[i] = NULL; + } + } + + if (IS_VALID_PTR(sfp_class)) + { + class_destroy(sfp_class); + sfp_class = NULL; + } + + return 0; +} +#endif + +static int e530_48t4x_p_init(void) +{ + int ret = 0; + int failed = 0; + + printk(KERN_ALERT "install e530_48t4x_p board dirver...\n"); + + ret = e530_48t4x_p_init_i2c_master(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_48t4x_p_init_i2c_gpio(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_48t4x_p_init_psu(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_48t4x_p_init_led(); + if (ret != 0) + { + failed = 1; + } + + ret = e530_48t4x_p_init_sfp(); + if (ret != 0) + { + failed = 1; + } + + if (failed) + printk(KERN_INFO "install e530_48t4x_p board driver failed\n"); + else + printk(KERN_ALERT "install e530_48t4x_p board dirver...ok\n"); + + return 0; +} + +static void e530_48t4x_p_exit(void) +{ + printk(KERN_INFO "uninstall e530_48t4x_p board dirver...\n"); + + e530_48t4x_p_exit_sfp(); + e530_48t4x_p_exit_led(); + e530_48t4x_p_exit_psu(); + e530_48t4x_p_exit_i2c_gpio(); + e530_48t4x_p_exit_i2c_master(); +} + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("shil centecNetworks, Inc"); +MODULE_DESCRIPTION("e530-48t4x-p board driver"); +module_init(e530_48t4x_p_init); +module_exit(e530_48t4x_p_exit); diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/service/48t4x_p_platform.service b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/service/48t4x_p_platform.service new file mode 100644 index 000000000000..957f232259ad --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/service/48t4x_p_platform.service @@ -0,0 +1,13 @@ +[Unit] +Description=Centec modules init +After=local-fs.target +Before=syncd.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-e530-48t4x-p start +ExecStop=-/etc/init.d/platform-modules-e530-48t4x-p stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/setup.py b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/setup.py new file mode 100755 index 000000000000..b7b479a3e936 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/48t4x_p/setup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='48t4x_p', + version='1.1', + description='Module to initialize centec e530-48t4x-p platforms', + + packages=['48t4x_p'], + package_dir={'48t4x_p': '48t4x_p/classes'}, +) + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/LICENSE b/platform/centec-arm64/sonic-platform-modules-e530/LICENSE new file mode 100644 index 000000000000..2d14d2b7785f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/LICENSE @@ -0,0 +1,15 @@ +Copyright (C) 2019 Centec, Inc + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. diff --git a/platform/centec-arm64/sonic-platform-modules-e530/README.md b/platform/centec-arm64/sonic-platform-modules-e530/README.md new file mode 100644 index 000000000000..6b907de17378 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/README.md @@ -0,0 +1 @@ +platform drivers for Centec E530 for the SONiC project diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/changelog b/platform/centec-arm64/sonic-platform-modules-e530/debian/changelog new file mode 100644 index 000000000000..6ac3ca4827b9 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/changelog @@ -0,0 +1,11 @@ +sonic-centec-platform-modules (1.1) unstable; urgency=low + + * Add support for centec e530-48t4x-p and e530-24x2c + + -- shil Fri, 15 Nov 2019 13:36:54 +0800 + +sonic-centec-platform-modules (1.0) unstable; urgency=low + + * Initial release + + -- shil Fri, 15 Nov 2019 13:35:06 +0800 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/compat b/platform/centec-arm64/sonic-platform-modules-e530/debian/compat new file mode 100644 index 000000000000..ec635144f600 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/compat @@ -0,0 +1 @@ +9 diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/control b/platform/centec-arm64/sonic-platform-modules-e530/debian/control new file mode 100644 index 000000000000..b9edd353a751 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/control @@ -0,0 +1,16 @@ +Source: sonic-centec-platform-modules +Section: main +Priority: extra +Maintainer: shil +Build-Depends: debhelper (>= 8.0.0), bzip2 +Standards-Version: 3.9.3 + +Package: platform-modules-e530-48t4x-p +Architecture: arm64 +Depends: linux-image-4.9.0-11-2-arm64 +Description: kernel modules for platform devices such as fan, led, sfp + +Package: platform-modules-e530-24x2c +Architecture: arm64 +Depends: linux-image-4.9.0-11-2-arm64 +Description: kernel modules for platform devices such as fan, led, sfp diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.init b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.init new file mode 100755 index 000000000000..377df7f0042b --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.init @@ -0,0 +1,57 @@ +#!/bin/bash +# This script load/unload centec kernel modules + +### BEGIN INIT INFO +# Provides: platform-modules-e530-24x2c +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Load Centec kernel modules +### END INIT INFO + + +function load_kernel_modules() +{ + depmod -a + modprobe centec_e530_24x2c_platform + modprobe dal +} + +function remove_kernel_modules() +{ + modprobe -r dal + modprobe -r centec_e530_24x2c_platform +} + +case "$1" in +start) + echo -n "Load Centec kernel modules... " + + load_kernel_modules + + echo "done." + ;; + +stop) + echo -n "Unload Centec kernel modules... " + + remove_kernel_modules + + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-e530-24x2c {start|stop}" + exit 1 + ;; +esac + +exit 0 + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.install b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.install new file mode 100644 index 000000000000..35c20b97150f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.install @@ -0,0 +1,3 @@ +kdal/dal.ko /lib/modules/4.9.0-11-2-arm64/kernel/extra +24x2c/modules/centec_e530_24x2c_platform.ko /lib/modules/4.9.0-11-2-arm64/kernel/extra +24x2c/service/24x2c_platform.service /lib/systemd/system diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.postinst b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.postinst new file mode 100644 index 000000000000..8bc216369078 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-24x2c.postinst @@ -0,0 +1,2 @@ +systemctl enable 24x2c_platform.service +systemctl start 24x2c_platform.service diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.init b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.init new file mode 100755 index 000000000000..71c644a5b8ab --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.init @@ -0,0 +1,57 @@ +#!/bin/bash +# This script load/unload centec kernel modules + +### BEGIN INIT INFO +# Provides: platform-modules-e530-48t4x-p +# Required-Start: +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Load Centec kernel modules +### END INIT INFO + + +function load_kernel_modules() +{ + depmod -a + modprobe centec_e530_48t4x_p_platform + modprobe dal +} + +function remove_kernel_modules() +{ + modprobe -r dal + modprobe -r centec_e530_48t4x_p_platform +} + +case "$1" in +start) + echo -n "Load Centec kernel modules... " + + load_kernel_modules + + echo "done." + ;; + +stop) + echo -n "Unload Centec kernel modules... " + + remove_kernel_modules + + echo "done." + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-e530-48t4x-p {start|stop}" + exit 1 + ;; +esac + +exit 0 + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.install b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.install new file mode 100644 index 000000000000..c4878173b2c1 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.install @@ -0,0 +1,3 @@ +kdal/dal.ko /lib/modules/4.9.0-11-2-arm64/kernel/extra +48t4x_p/modules/centec_e530_48t4x_p_platform.ko /lib/modules/4.9.0-11-2-arm64/kernel/extra +48t4x_p/service/48t4x_p_platform.service /lib/systemd/system diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.postinst b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.postinst new file mode 100644 index 000000000000..12ef719aad8f --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/platform-modules-e530-48t4x-p.postinst @@ -0,0 +1,2 @@ +systemctl enable 48t4x_p_platform.service +systemctl start 48t4x_p_platform.service diff --git a/platform/centec-arm64/sonic-platform-modules-e530/debian/rules b/platform/centec-arm64/sonic-platform-modules-e530/debian/rules new file mode 100755 index 000000000000..18545d0847d8 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/debian/rules @@ -0,0 +1,91 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +include /usr/share/dpkg/pkg-info.mk + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +export INSTALL_MOD_DIR:=extra + +PYTHON ?= python2 + +PACKAGE_PRE_NAME := sonic-platform-modules-e530 +KVERSION ?= $(shell uname -r) +KERNEL_SRC := /lib/modules/$(KVERSION) +MOD_SRC_DIR:= $(shell pwd) +MODULE_DIRS:= 48t4x_p 24x2c +MODULE_DIR := modules +UTILS_DIR := utils +SERVICE_DIR := service +CLASSES_DIR := classes +CONF_DIR := conf +KDAL_DIR := kdal + +%: + dh $@ --with systemd,python2,python3 --buildsystem=pybuild + +clean: + dh_testdir + dh_testroot + dh_clean + +build: + #make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC) + (for mod in $(KDAL_DIR); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/; \ + done) + (for mod in $(MODULE_DIRS); do \ + make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + $(PYTHON) $${mod}/setup.py build; \ + done) + +binary: binary-arch binary-indep + # Nothing to do + +binary-arch: + # Nothing to do + +#install: build + #dh_testdir + #dh_testroot + #dh_clean -k + #dh_installdirs + +binary-indep: + dh_testdir + dh_installdirs + + # Custom package commands + (for mod in $(MODULE_DIRS); do \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} usr/local/bin; \ + dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} lib/systemd/system; \ + cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$(KDAL_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ + cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \ + cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \ + $(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \ + done) + # Resuming debhelper scripts + dh_testroot + dh_install + dh_installchangelogs + dh_installdocs + dh_systemd_enable + dh_installinit + dh_systemd_start + dh_link + dh_fixperms + dh_compress + dh_strip + dh_installdeb + dh_gencontrol + dh_md5sums + dh_builddeb +.PHONY: build binary binary-arch binary-indep clean diff --git a/platform/centec-arm64/sonic-platform-modules-e530/kdal/Makefile b/platform/centec-arm64/sonic-platform-modules-e530/kdal/Makefile new file mode 100644 index 000000000000..1140f6b2f93e --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/kdal/Makefile @@ -0,0 +1,2 @@ +obj-m := dal.o +dal-y := dal_kernel.o dal_mpool.o diff --git a/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_common.h b/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_common.h new file mode 100644 index 000000000000..d8d4d6a67c0d --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_common.h @@ -0,0 +1,119 @@ +/** + @file dal.h + + @author Copyright (C) 2012 Centec Networks Inc. All rights reserved. + + @date 2012-4-9 + + @version v2.0 + +*/ +#ifndef _DAL_COMMON_H_ +#define _DAL_COMMON_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#define DAL_MAX_CHIP_NUM 8 /* DAL support max chip num is 8 */ +#define DAL_MAX_INTR_NUM 8 + +#define DAL_NETIF_T_PORT 0 +#define DAL_NETIF_T_VLAN 1 + +#define DAL_MAX_KNET_NETIF 64 +#define DAL_MAX_KNET_NAME_LEN 32 + +enum dal_operate_code_e +{ + DAL_OP_CREATE, + DAL_OP_DESTORY, + DAL_OP_GET, + DAL_OP_MAX, +}; +typedef enum dal_operate_code_e dal_operate_code_t; + +struct dal_dma_info_s +{ + unsigned int lchip; + unsigned int phy_base; + unsigned int phy_base_hi; + unsigned int size; + unsigned int knet_tx_offset; + unsigned int knet_tx_size; + unsigned int* virt_base; +}; +typedef struct dal_dma_info_s dal_dma_info_t; + +struct dal_dma_chan_s +{ + unsigned char lchip; + unsigned char channel_id; + unsigned char dmasel; + unsigned char active; + unsigned short current_index; + unsigned short desc_num; + unsigned short desc_depth; + unsigned short data_size; + unsigned long long mem_base; + void* virt_base; /**< don't use when register chan*/ + unsigned char* p_desc_used; /**< don't use when register chan*/ +}; +typedef struct dal_dma_chan_s dal_dma_chan_t; + +struct dal_netif_s +{ + unsigned char op_type; + unsigned char netif_id; + unsigned char type; + unsigned char lchip; + unsigned short vlan; + unsigned int gport; + unsigned char mac[6]; + char name[DAL_MAX_KNET_NAME_LEN]; +}; +typedef struct dal_netif_s dal_netif_t; + +/** + @brief define dal error type +*/ +enum dal_err_e +{ + DAL_E_NONE = 0, /**< NO error */ + DAL_E_INVALID_PTR = -1000, /**< invalid pointer */ + DAL_E_INVALID_FD = -999, /**< invalid FD */ + DAL_E_TIME_OUT = -998, /**< time out */ + DAL_E_INVALID_ACCESS = -997, /**< invalid access type*/ + DAL_E_MPOOL_NOT_CREATE = -996, /**< mpool not create*/ + DAL_E_INVALID_IRQ = -995, + DAL_E_DEV_NOT_FOUND = -994, + DAL_E_EXCEED_MAX = -993, + DAL_E_NOT_INIT = -992, + DAL_E_ENVALID_MSI_PARA = -991, + + DAL_E_ERROR_CODE_END +}; + +enum dal_access_type_e +{ + DAL_PCI_IO, /* [HB]humber is access as pci device, using ioctrl */ + DAL_SUPER_IF, /* [HB]humber is controled by fpga device */ + DAL_PCIE_MM, /* [GB]Gb is access as pcie device, using mmap */ + DAL_SPECIAL_EMU, /* [GB]special for emulation */ + DAL_MAX_ACCESS_TYPE +}; +typedef enum dal_access_type_e dal_access_type_t; + +struct dal_pci_dev_s +{ + unsigned int busNo; + unsigned int devNo; + unsigned int funNo; +}; +typedef struct dal_pci_dev_s dal_pci_dev_t; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_kernel.c b/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_kernel.c new file mode 100644 index 000000000000..5b228939e379 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_kernel.c @@ -0,0 +1,2232 @@ +/** + @file dal_kernal.c + + @date 2012-10-18 + + @version v2.0 + + +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) +#include +#endif +#include "dal_kernel.h" +#include "dal_common.h" +#include "dal_mpool.h" +#include +#if defined(SOC_ACTIVE) +#include +#endif +MODULE_AUTHOR("Centec Networks Inc."); +MODULE_DESCRIPTION("DAL kernel module"); +MODULE_LICENSE("GPL"); + +/* DMA memory pool size */ +static char* dma_pool_size; +module_param(dma_pool_size, charp, 0); +MODULE_PARM_DESC(dma_pool_size, + "Specify DMA memory pool size (default 4MB)"); + +/***************************************************************************** + * defines + *****************************************************************************/ +#define MB_SIZE 0x100000 +#define CTC_MAX_INTR_NUM 8 + +#define MEM_MAP_RESERVE SetPageReserved +#define MEM_MAP_UNRESERVE ClearPageReserved + +#define CTC_VENDOR_VID 0xc001 +#define CTC_HUMBER_DEVICE_ID 0x6048 +#define CTC_GOLDENGATE_DEVICE_ID 0xc010 +#define CTC_PCIE_VENDOR_ID 0xcb10 +#define CTC_DUET2_DEVICE_ID 0x7148 +#define CTC_TSINGMA_DEVICE_ID 0x5236 + +#define MEM_MAP_RESERVE SetPageReserved +#define MEM_MAP_UNRESERVE ClearPageReserved + +#define CTC_GREATBELT_DEVICE_ID 0x03e8 /* TBD */ +#define DAL_MAX_CHIP_NUM 8 +#define VIRT_TO_PAGE(p) virt_to_page((p)) +#define DAL_UNTAG_BLOCK 0 +#define DAL_DISCARD_BLOCK 1 +#define DAL_MATCHED_BLOCK 2 +#define DAL_CUR_MATCH_BLOCk 3 +/***************************************************************************** + * typedef + *****************************************************************************/ +typedef enum dal_cpu_mode_type_e +{ + DAL_CPU_MODE_TYPE_NONE, + DAL_CPU_MODE_TYPE_PCIE, /*use pcie*/ + DAL_CPU_MODE_TYPE_LOCAL, /*use local bus*/ + DAL_CPU_MODE_MAX_TYPE, + +} dal_cpu_mode_type_t; +/* Control Data */ +typedef struct dal_isr_s +{ + int irq; + void (* isr)(void*); + void (* isr_knet)(void*); + void* isr_data; + void* isr_knet_data; + int trigger; + int count; + wait_queue_head_t wqh; +} dal_isr_t; + +#if defined(SOC_ACTIVE) +typedef struct dal_kernel_local_dev_s +{ + struct list_head list; + struct platform_device* pci_dev; + + /* PCI I/O mapped base address */ + void __iomem * logic_address; + + /* Physical address */ + uintptr phys_address; +} dal_kern_local_dev_t; +#endif + +typedef struct dal_kernel_pcie_dev_s +{ + struct list_head list; + struct pci_dev* pci_dev; + + /* PCI I/O mapped base address */ + uintptr logic_address; + + /* Physical address */ + unsigned long long phys_address; +} dal_kern_pcie_dev_t; + +typedef struct _dma_segment +{ + struct list_head list; + unsigned long req_size; /* Requested DMA segment size */ + unsigned long blk_size; /* DMA block size */ + unsigned long blk_order; /* DMA block size in alternate format */ + unsigned long seg_size; /* Current DMA segment size */ + unsigned long seg_begin; /* Logical address of segment */ + unsigned long seg_end; /* Logical end address of segment */ + unsigned long* blk_ptr; /* Array of logical DMA block addresses */ + int blk_cnt_max; /* Maximum number of block to allocate */ + int blk_cnt; /* Current number of blocks allocated */ +} dma_segment_t; + +typedef irqreturn_t (*p_func) (int irq, void* dev_id); + +/*************************************************************************** + *declared + ***************************************************************************/ +static unsigned int linux_dal_poll0(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll1(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll2(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll3(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll4(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll5(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll6(struct file* filp, struct poll_table_struct* p); +static unsigned int linux_dal_poll7(struct file* filp, struct poll_table_struct* p); + +/***************************************************************************** + * global variables + *****************************************************************************/ +static void* dal_dev[DAL_MAX_CHIP_NUM]={0}; +static dal_isr_t dal_isr[CTC_MAX_INTR_NUM]; +#if defined(SOC_ACTIVE) +static dal_isr_t dal_int[CTC_MAX_INTR_NUM] = {0}; +#endif +static int dal_chip_num = 0; +static int dal_version = 0; +static int dal_intr_num = 0; +static int use_high_memory = 0; +static unsigned int* dma_virt_base[DAL_MAX_CHIP_NUM]; +static unsigned long long dma_phy_base[DAL_MAX_CHIP_NUM]; +static unsigned int dma_mem_size = 0xc00000; +static unsigned int msi_irq_base[DAL_MAX_CHIP_NUM]; +static unsigned int msi_irq_num[DAL_MAX_CHIP_NUM]; +static unsigned int msi_used = 0; +static unsigned int active_type[DAL_MAX_CHIP_NUM] = {0}; +static struct class *dal_class; + +static LIST_HEAD(_dma_seg); +static int dal_debug = 0; +module_param(dal_debug, int, 0); +MODULE_PARM_DESC(dal_debug, "Set debug level (default 0)"); + +static struct pci_device_id dal_id_table[] = +{ + {PCI_DEVICE(CTC_VENDOR_VID, CTC_GREATBELT_DEVICE_ID)}, + {PCI_DEVICE(CTC_PCIE_VENDOR_ID, CTC_GOLDENGATE_DEVICE_ID)}, + {PCI_DEVICE((CTC_PCIE_VENDOR_ID+1), (CTC_GOLDENGATE_DEVICE_ID+1))}, + {PCI_DEVICE(CTC_PCIE_VENDOR_ID, CTC_DUET2_DEVICE_ID)}, + {PCI_DEVICE(CTC_PCIE_VENDOR_ID, CTC_TSINGMA_DEVICE_ID)}, + {0, }, +}; +#if defined(SOC_ACTIVE) +static const struct of_device_id linux_dal_of_match[] = { + { .compatible = "centec,dal-localbus",}, + {}, +}; +MODULE_DEVICE_TABLE(of, linux_dal_of_match); +#endif + +static wait_queue_head_t poll_intr[CTC_MAX_INTR_NUM]; + +p_func intr_handler_fun[CTC_MAX_INTR_NUM]; + +static int poll_intr_trigger[CTC_MAX_INTR_NUM]; + +static struct file_operations dal_intr_fops[CTC_MAX_INTR_NUM] = +{ + { + .owner = THIS_MODULE, + .poll = linux_dal_poll0, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll1, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll2, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll3, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll4, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll5, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll6, + }, + { + .owner = THIS_MODULE, + .poll = linux_dal_poll7, + }, +}; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)) +#include +#define virt_to_bus virt_to_phys +#define bus_to_virt phys_to_virt +#endif +/***************************************************************************** + * macros + *****************************************************************************/ +#define VERIFY_CHIP_INDEX(n) (n < dal_chip_num) + +#define _KERNEL_INTERUPT_PROCESS +static irqreturn_t +intr0_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + + if(poll_intr_trigger[0]) + { + return IRQ_HANDLED; + } + + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[0] = 1; + wake_up(&poll_intr[0]); + } + + if (p_dal_isr->isr_knet) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr_knet(p_dal_isr->isr_knet_data); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr1_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + + if(poll_intr_trigger[1]) + { + return IRQ_HANDLED; + } + + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[1] = 1; + wake_up(&poll_intr[1]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr2_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[2]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[2] = 1; + wake_up(&poll_intr[2]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr3_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[3]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[3] = 1; + wake_up(&poll_intr[3]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr4_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[4]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[4] = 1; + wake_up(&poll_intr[4]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr5_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[5]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[5] = 1; + wake_up(&poll_intr[5]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr6_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[6]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[6] = 1; + wake_up(&poll_intr[6]); + } + } + + return IRQ_HANDLED; +} + +static irqreturn_t +intr7_handler(int irq, void* dev_id) +{ + dal_isr_t* p_dal_isr = (dal_isr_t*)dev_id; + if(poll_intr_trigger[7]) + { + return IRQ_HANDLED; + } + disable_irq_nosync(irq); + + if (p_dal_isr) + { + if (p_dal_isr->isr) + { + /* kernel mode interrupt handler */ + p_dal_isr->isr(p_dal_isr->isr_data); + } + else if ((NULL == p_dal_isr->isr) && (NULL == p_dal_isr->isr_data)) + { + /* user mode interrupt handler */ + poll_intr_trigger[7] = 1; + wake_up(&poll_intr[7]); + } + } + + return IRQ_HANDLED; +} + +int +dal_interrupt_register(unsigned int irq, int prio, void (* isr)(void*), void* data) +{ + int ret; + unsigned char str[16]; + unsigned char* int_name = NULL; + unsigned int intr_num_tmp = 0; + unsigned int intr_num = CTC_MAX_INTR_NUM; + unsigned long irq_flags = 0; + + if (dal_intr_num >= CTC_MAX_INTR_NUM) + { + printk("Interrupt numbers exceeds max.\n"); + return -1; + } + + if (msi_used) + { + int_name = "dal_msi"; + } + else + { + int_name = "dal_intr"; + } + + + for (intr_num_tmp=0;intr_num_tmp < CTC_MAX_INTR_NUM; intr_num_tmp++) + { + if (irq == dal_isr[intr_num_tmp].irq) + { + if (0 == msi_used) + { + dal_isr[intr_num_tmp].count++; + printk("Interrupt irq %d register count %d.\n", irq, dal_isr[intr_num_tmp].count); + } + return 0; + } + if ((0 == dal_isr[intr_num_tmp].irq) && (CTC_MAX_INTR_NUM == intr_num)) + { + intr_num = intr_num_tmp; + dal_isr[intr_num].count = 0; + } + } + dal_isr[intr_num].irq = irq; + dal_isr[intr_num].isr = isr; + dal_isr[intr_num].isr_data = data; + dal_isr[intr_num].count++; + + init_waitqueue_head(&poll_intr[intr_num]); + + /* only user mode */ + if ((NULL == isr) && (NULL == data)) + { + snprintf(str, 16, "%s%d", "dal_intr", intr_num); + ret = register_chrdev(DAL_DEV_INTR_MAJOR_BASE + intr_num, + str, &dal_intr_fops[intr_num]); + if (ret < 0) + { + printk("Register character device for irq %d failed, ret= %d", irq, ret); + return ret; + } + } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) + irq_flags = 0; +#else + irq_flags = IRQF_DISABLED; +#endif + if ((ret = request_irq(irq, + intr_handler_fun[intr_num], + irq_flags, + int_name, + &dal_isr[intr_num])) < 0) + { + printk("Cannot request irq %d, ret %d.\n", irq, ret); + unregister_chrdev(DAL_DEV_INTR_MAJOR_BASE + intr_num, str); + } + + if (0 == ret) + { + dal_intr_num++; + } + + return ret; +} + +int +dal_interrupt_unregister(unsigned int irq) +{ + unsigned char str[16]; + int intr_idx = 0; + int find_flag = 0; + + /* get intr device index */ + for (intr_idx = 0; intr_idx < CTC_MAX_INTR_NUM; intr_idx++) + { + if (dal_isr[intr_idx].irq == irq) + { + find_flag = 1; + break; + } + } + + if (find_flag == 0) + { + printk ("irq%d is not registered! unregister failed \n", irq); + return -1; + } + + dal_isr[intr_idx].count--; + if (0 != dal_isr[intr_idx].count) + { + printk("Interrupt irq %d unregister count %d.\n", irq, dal_isr[intr_idx].count); + return -1; + } + snprintf(str, 16, "%s%d", "dal_intr", intr_idx); + + unregister_chrdev(DAL_DEV_INTR_MAJOR_BASE + intr_idx, str); + + free_irq(irq, &dal_isr[intr_idx]); + + dal_isr[intr_idx].irq = 0; + + dal_intr_num--; + + return 0; +} + +int +dal_interrupt_connect(unsigned int irq, int prio, void (* isr)(void*), void* data) +{ + int irq_idx = 0; + + for (irq_idx = 0; irq_idx < dal_intr_num; irq_idx++) + { + if (dal_isr[irq_idx].irq == irq) + { + dal_isr[irq_idx].isr_knet = isr; + dal_isr[irq_idx].isr_knet_data = data; + + return 0; + } + } + + return -1; +} + +int +dal_interrupt_disconnect(unsigned int irq) +{ + int irq_idx = 0; + + for (irq_idx = 0; irq_idx < dal_intr_num; irq_idx++) + { + if (dal_isr[irq_idx].irq == irq) + { + dal_isr[irq_idx].isr_knet = NULL; + dal_isr[irq_idx].isr_knet_data = NULL; + + return 0; + } + } + + return -1; +} + +static dal_ops_t g_dal_ops = +{ + interrupt_connect:dal_interrupt_connect, + interrupt_disconnect:dal_interrupt_disconnect, +}; + +int +dal_get_dal_ops(dal_ops_t **dal_ops) +{ + *dal_ops = &g_dal_ops; + + return 0; +} + +int +dal_interrupt_set_en(unsigned int irq, unsigned int enable) +{ + enable ? enable_irq(irq) : disable_irq_nosync(irq); + return 0; +} + +static int +_dal_set_msi_enabe(unsigned int lchip, unsigned int irq_num) +{ + int ret = 0; + dal_kern_pcie_dev_t* dev = NULL; + + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + dev = dal_dev[lchip]; + if (NULL == dev) + { + return -1; + } + if (irq_num == 1) + { + ret = pci_enable_msi(dev->pci_dev); + if (ret) + { + printk ("msi enable failed!!! lchip = %d, irq_num = %d\n", lchip, irq_num); + pci_disable_msi(dev->pci_dev); + msi_used = 0; + } + + msi_irq_base[lchip] = dev->pci_dev->irq; + msi_irq_num[lchip] = 1; + } + else + { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 79)) + ret = pci_enable_msi_exact(dev->pci_dev, irq_num); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 26, 32)) + ret = pci_enable_msi_block(dev->pci_dev, irq_num); +#else + ret = -1; +#endif + if (ret) + { + printk ("msi enable failed!!! lchip = %d, irq_num = %d\n", lchip, irq_num); + pci_disable_msi(dev->pci_dev); + msi_used = 0; + } + + msi_irq_base[lchip] = dev->pci_dev->irq; + msi_irq_num[lchip] = irq_num; + } + } + + return ret; +} + +static int +_dal_set_msi_disable(unsigned int lchip) +{ + dal_kern_pcie_dev_t* dev = NULL; + + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + dev = dal_dev[lchip]; + if (NULL == dev) + { + return -1; + } + pci_disable_msi(dev->pci_dev); + + msi_irq_base[lchip] = 0; + msi_irq_num[lchip] = 0; + } + + return 0; +} + +int +dal_set_msi_cap(unsigned long arg) +{ + int ret = 0; + int index = 0; + dal_msi_info_t msi_info; + + if (copy_from_user(&msi_info, (void*)arg, sizeof(dal_msi_info_t))) + { + return -EFAULT; + } + + printk("####dal_set_msi_cap lchip %d base %d num:%d\n", msi_info.lchip, msi_info.irq_base, msi_info.irq_num); + if (DAL_CPU_MODE_TYPE_PCIE == active_type[msi_info.lchip]) + { + if (msi_info.irq_num > 0) + { + if (0 == msi_used) + { + msi_used = 1; + ret = _dal_set_msi_enabe(msi_info.lchip, msi_info.irq_num); + } + else if ((1 == msi_used) && (msi_info.irq_num != msi_irq_num[msi_info.lchip])) + { + for (index = 0; index < msi_irq_num[msi_info.lchip]; index++) + { + dal_interrupt_unregister(msi_irq_base[msi_info.lchip]+index); + } + _dal_set_msi_disable(msi_info.lchip); + msi_used = 1; + ret = _dal_set_msi_enabe(msi_info.lchip, msi_info.irq_num); + } + } + else + { + msi_used = 0; + ret = _dal_set_msi_disable(msi_info.lchip); + } + } + + return ret; +} + +int +dal_user_interrupt_register(unsigned long arg) +{ + int irq = 0; + if (copy_from_user(&irq, (void*)arg, sizeof(int))) + { + return -EFAULT; + } + printk("####register interrupt irq:%d\n", irq); + return dal_interrupt_register(irq, 0, NULL, NULL); +} + +int +dal_user_interrupt_unregister(unsigned long arg) +{ + int irq = 0; + if (copy_from_user(&irq, (void*)arg, sizeof(int))) + { + return -EFAULT; + } + printk("####unregister interrupt irq:%d\n", irq); + return dal_interrupt_unregister(irq); +} + +int +dal_user_interrupt_set_en(unsigned long arg) +{ + dal_intr_parm_t dal_intr_parm; + + if (copy_from_user(&dal_intr_parm, (void*)arg, sizeof(dal_intr_parm_t))) + { + return -EFAULT; + } + + return dal_interrupt_set_en(dal_intr_parm.irq, dal_intr_parm.enable); +} + +/* + * Function: _dal_dma_segment_free + */ + +/* + * Function: _find_largest_segment + * + * Purpose: + * Find largest contiguous segment from a pool of DMA blocks. + * Parameters: + * dseg - DMA segment descriptor + * Returns: + * 0 on success, < 0 on error. + * Notes: + * Assembly stops if a segment of the requested segment size + * has been obtained. + * + * Lower address bits of the DMA blocks are used as follows: + * 0: Untagged + * 1: Discarded block + * 2: Part of largest contiguous segment + * 3: Part of current contiguous segment + */ +#ifndef DMA_MEM_MODE_PLATFORM +static int +_dal_find_largest_segment(dma_segment_t* dseg) +{ + int i, j, blks, found; + unsigned long seg_begin; + unsigned long seg_end; + unsigned long seg_tmp; + + blks = dseg->blk_cnt; + + /* Clear all block tags */ + for (i = 0; i < blks; i++) + { + dseg->blk_ptr[i] &= ~3; + } + + for (i = 0; i < blks && dseg->seg_size < dseg->req_size; i++) + { + /* First block must be an untagged block */ + if ((dseg->blk_ptr[i] & 3) == DAL_UNTAG_BLOCK) + { + /* Initial segment size is the block size */ + seg_begin = dseg->blk_ptr[i]; + seg_end = seg_begin + dseg->blk_size; + dseg->blk_ptr[i] |= DAL_CUR_MATCH_BLOCk; + + /* Loop looking for adjacent blocks */ + do + { + found = 0; + + for (j = i + 1; j < blks && (seg_end - seg_begin) < dseg->req_size; j++) + { + seg_tmp = dseg->blk_ptr[j]; + /* Check untagged blocks only */ + if ((seg_tmp & 3) == DAL_UNTAG_BLOCK) + { + if (seg_tmp == (seg_begin - dseg->blk_size)) + { + /* Found adjacent block below current segment */ + dseg->blk_ptr[j] |= DAL_CUR_MATCH_BLOCk; + seg_begin = seg_tmp; + found = 1; + } + else if (seg_tmp == seg_end) + { + /* Found adjacent block above current segment */ + dseg->blk_ptr[j] |= DAL_CUR_MATCH_BLOCk; + seg_end += dseg->blk_size; + found = 1; + } + } + } + } + while (found); + + if ((seg_end - seg_begin) > dseg->seg_size) + { + /* The current block is largest so far */ + dseg->seg_begin = seg_begin; + dseg->seg_end = seg_end; + dseg->seg_size = seg_end - seg_begin; + + /* Re-tag current and previous largest segment */ + for (j = 0; j < blks; j++) + { + if ((dseg->blk_ptr[j] & 3) == DAL_CUR_MATCH_BLOCk) + { + /* Tag current segment as the largest */ + dseg->blk_ptr[j] &= ~1; + } + else if ((dseg->blk_ptr[j] & 3) == DAL_MATCHED_BLOCK) + { + /* Discard previous largest segment */ + dseg->blk_ptr[j] ^= 3; + } + } + } + else + { + /* Discard all blocks in current segment */ + for (j = 0; j < blks; j++) + { + if ((dseg->blk_ptr[j] & 3) == DAL_CUR_MATCH_BLOCk) + { + dseg->blk_ptr[j] &= ~2; + } + } + } + } + } + + return 0; +} + +/* + * Function: _alloc_dma_blocks + */ +static int +_dal_alloc_dma_blocks(dma_segment_t* dseg, int blks) +{ + int i, start; + unsigned long addr; + + if (dseg->blk_cnt + blks > dseg->blk_cnt_max) + { + printk("No more DMA blocks\n"); + return -1; + } + + start = dseg->blk_cnt; + dseg->blk_cnt += blks; + + for (i = start; i < dseg->blk_cnt; i++) + { + addr = __get_free_pages(GFP_ATOMIC, dseg->blk_order); + if (addr) + { + dseg->blk_ptr[i] = addr; + } + else + { + printk("DMA allocation failed\n"); + return -1; + } + } + + return 0; +} + +/* + * Function: _dal_dma_segment_alloc + */ +static dma_segment_t* +_dal_dma_segment_alloc(unsigned int size, unsigned int blk_size) +{ + dma_segment_t* dseg; + int i, blk_ptr_size; + unsigned long page_addr; + struct sysinfo si; + + /* Sanity check */ + if (size == 0 || blk_size == 0) + { + return NULL; + } + + /* Allocate an initialize DMA segment descriptor */ + if ((dseg = kmalloc(sizeof(dma_segment_t), GFP_ATOMIC)) == NULL) + { + return NULL; + } + + memset(dseg, 0, sizeof(dma_segment_t)); + dseg->req_size = size; + dseg->blk_size = PAGE_ALIGN(blk_size); + + while ((PAGE_SIZE << dseg->blk_order) < dseg->blk_size) + { + dseg->blk_order++; + } + + si_meminfo(&si); + dseg->blk_cnt_max = (si.totalram << PAGE_SHIFT) / dseg->blk_size; + blk_ptr_size = dseg->blk_cnt_max * sizeof(unsigned long); + /* Allocate an initialize DMA block pool */ + dseg->blk_ptr = kmalloc(blk_ptr_size, GFP_KERNEL); + if (dseg->blk_ptr == NULL) + { + kfree(dseg); + return NULL; + } + + memset(dseg->blk_ptr, 0, blk_ptr_size); + /* Allocate minimum number of blocks */ + _dal_alloc_dma_blocks(dseg, dseg->req_size / dseg->blk_size); + + /* Allocate more blocks until we have a complete segment */ + do + { + _dal_find_largest_segment(dseg); + if (dseg->seg_size >= dseg->req_size) + { + break; + } + } + while (_dal_alloc_dma_blocks(dseg, 8) == 0); + + /* Reserve all pages in the DMA segment and free unused blocks */ + for (i = 0; i < dseg->blk_cnt; i++) + { + if ((dseg->blk_ptr[i] & 3) == 2) + { + dseg->blk_ptr[i] &= ~3; + + for (page_addr = dseg->blk_ptr[i]; + page_addr < dseg->blk_ptr[i] + dseg->blk_size; + page_addr += PAGE_SIZE) + { + MEM_MAP_RESERVE(VIRT_TO_PAGE((void*)page_addr)); + } + } + else if (dseg->blk_ptr[i]) + { + dseg->blk_ptr[i] &= ~3; + free_pages(dseg->blk_ptr[i], dseg->blk_order); + dseg->blk_ptr[i] = 0; + } + } + + return dseg; +} + +/* + * Function: _dal_dma_segment_free + */ +static void +_dal_dma_segment_free(dma_segment_t* dseg) +{ + int i; + unsigned long page_addr; + + if (dseg->blk_ptr) + { + for (i = 0; i < dseg->blk_cnt; i++) + { + if (dseg->blk_ptr[i]) + { + for (page_addr = dseg->blk_ptr[i]; + page_addr < dseg->blk_ptr[i] + dseg->blk_size; + page_addr += PAGE_SIZE) + { + MEM_MAP_UNRESERVE(VIRT_TO_PAGE(page_addr)); + } + + free_pages(dseg->blk_ptr[i], dseg->blk_order); + } + } + + kfree(dseg->blk_ptr); + kfree(dseg); + } +} + +/* + * Function: -dal_pgalloc + */ +static void* +_dal_pgalloc(unsigned int size) +{ + dma_segment_t* dseg; + unsigned int blk_size; + + blk_size = (size < DMA_BLOCK_SIZE) ? size : DMA_BLOCK_SIZE; + if ((dseg = _dal_dma_segment_alloc(size, blk_size)) == NULL) + { + return NULL; + } + + if (dseg->seg_size < size) + { + /* If we didn't get the full size then forget it */ + printk("Notice: Can not get enough memory for requset!!\n"); + printk("actual size:0x%lx, request size:0x%x\n", dseg->seg_size, size); + /*-_dal_dma_segment_free(dseg);*/ + /*-return NULL;*/ + } + + list_add(&dseg->list, &_dma_seg); + return (void*)dseg->seg_begin; +} + +/* + * Function: _dal_pgfree + */ +static int +_dal_pgfree(void* ptr) +{ + struct list_head* pos; + + list_for_each(pos, &_dma_seg) + { + dma_segment_t* dseg = list_entry(pos, dma_segment_t, list); + if (ptr == (void*)dseg->seg_begin) + { + list_del(&dseg->list); + _dal_dma_segment_free(dseg); + return 0; + } + } + return -1; +} +#endif + +static void +dal_alloc_dma_pool(int lchip, int size) +{ +#if defined(DMA_MEM_MODE_PLATFORM) || defined(SOC_ACTIVE) + struct device * dev = NULL; +#endif + + if (use_high_memory) + { + dma_phy_base[lchip] = virt_to_bus(high_memory); + dma_virt_base[lchip] = ioremap_nocache(dma_phy_base[lchip], size); + } + else + { +#if defined(DMA_MEM_MODE_PLATFORM) || defined(SOC_ACTIVE) + if ((DAL_CPU_MODE_TYPE_PCIE != active_type[lchip]) && (DAL_CPU_MODE_TYPE_LOCAL != active_type[lchip])) + { + printk("active type %d error, not cpu and soc!\n", active_type[lchip]); + return; + } + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + dev = &(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->pci_dev->dev); + } +#if defined (SOC_ACTIVE) + if (DAL_CPU_MODE_TYPE_LOCAL == active_type[lchip]) + { + dev = &(((dal_kern_local_dev_t*)(dal_dev[lchip]))->pci_dev->dev); + } +#endif + dma_virt_base[lchip] = dma_alloc_coherent(dev, dma_mem_size, + &dma_phy_base[lchip], GFP_KERNEL); + + printk("dma_phy_base[lchip] 0x%llx dma_virt_base[lchip] %p \n", dma_phy_base[lchip], dma_virt_base[lchip]); + printk(KERN_WARNING "########Using DMA_MEM_MODE_PLATFORM \n"); +#else + /* Get DMA memory from kernel */ + dma_virt_base[lchip] = _dal_pgalloc(size); + dma_phy_base[lchip] = virt_to_bus(dma_virt_base[lchip]); + //dma_virt_base [lchip]= ioremap_nocache(dma_phy_base[lchip], size); +#endif + } +} + +static void +dal_free_dma_pool(int lchip) +{ + int ret = 0; +#if defined(DMA_MEM_MODE_PLATFORM) || defined(SOC_ACTIVE) + struct device * dev = NULL; +#endif + + ret = ret; + if (use_high_memory) + { + iounmap(dma_virt_base[lchip]); + } + else + { +#if defined(DMA_MEM_MODE_PLATFORM) || defined(SOC_ACTIVE) + if ((DAL_CPU_MODE_TYPE_PCIE != active_type[lchip]) && (DAL_CPU_MODE_TYPE_LOCAL != active_type[lchip])) + { + return; + } + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + dev = &(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->pci_dev->dev); + } +#if defined(SOC_ACTIVE) + if (DAL_CPU_MODE_TYPE_LOCAL == active_type[lchip]) + { + dev = &(((dal_kern_local_dev_t*)(dal_dev[lchip]))->pci_dev->dev); + } +#endif + dma_free_coherent(dev, dma_mem_size, + dma_virt_base[lchip], dma_phy_base[lchip]); +#else + iounmap(dma_virt_base[lchip]); + ret = _dal_pgfree(dma_virt_base[lchip]); + if(ret<0) + { + printk("Dma free memory fail !!!!!! \n"); + } +#endif + } +} + +#define _KERNEL_DAL_IO +static int +_dal_pci_read(unsigned char lchip, unsigned int offset, unsigned int* value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + if ((DAL_CPU_MODE_TYPE_PCIE != active_type[lchip]) && (DAL_CPU_MODE_TYPE_LOCAL != active_type[lchip])) + { + return -1; + } + + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + *value = *(volatile unsigned int*)(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->logic_address + offset); + } +#if defined(SOC_ACTIVE) + if (DAL_CPU_MODE_TYPE_LOCAL == active_type[lchip]) + { + *value = *(volatile unsigned int*)(((dal_kern_local_dev_t*)(dal_dev[lchip]))->logic_address + offset); + } +#endif + return 0; +} + +int +dal_create_irq_mapping(unsigned long arg) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) + +#ifndef NO_IRQ +#define NO_IRQ (-1) +#endif + dal_irq_mapping_t irq_map; + + if (copy_from_user(&irq_map, (void*)arg, sizeof(dal_irq_mapping_t))) + { + return -EFAULT; + } + + irq_map.sw_irq = irq_create_mapping(NULL, irq_map.hw_irq); + if (irq_map.sw_irq == NO_IRQ) + { + printk("IRQ mapping fail !!!!!! \n"); + return -1; + } + + if (copy_to_user((dal_irq_mapping_t*)arg, (void*)&irq_map, sizeof(dal_irq_mapping_t))) + { + return -EFAULT; + } +#endif + return 0; +} + +int +dal_pci_read(unsigned long arg) +{ + dal_chip_parm_t cmdpara_chip; + + if (copy_from_user(&cmdpara_chip, (void*)arg, sizeof(dal_chip_parm_t))) + { + return -EFAULT; + } + + _dal_pci_read((unsigned char)cmdpara_chip.lchip, (unsigned int)cmdpara_chip.reg_addr, + (unsigned int*)(&(cmdpara_chip.value))); + + if (copy_to_user((dal_chip_parm_t*)arg, (void*)&cmdpara_chip, sizeof(dal_chip_parm_t))) + { + return -EFAULT; + } + + return 0; +} + +static int +_dal_pci_write(unsigned char lchip, unsigned int offset, unsigned int value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + if ((DAL_CPU_MODE_TYPE_PCIE != active_type[lchip]) && (DAL_CPU_MODE_TYPE_LOCAL != active_type[lchip])) + { + return -1; + } + + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + *(volatile unsigned int*)(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->logic_address + offset) = value; + } +#if defined(SOC_ACTIVE) + if (DAL_CPU_MODE_TYPE_LOCAL == active_type[lchip]) + { + *(volatile unsigned int*)(((dal_kern_local_dev_t*)(dal_dev[lchip]))->logic_address + offset) = value; + } +#endif + + return 0; +} + +int +dal_pci_write(unsigned long arg) +{ + dal_chip_parm_t cmdpara_chip; + + if (copy_from_user(&cmdpara_chip, (void*)arg, sizeof(dal_chip_parm_t))) + { + return -EFAULT; + } + + _dal_pci_write((unsigned char)cmdpara_chip.lchip, (unsigned int)cmdpara_chip.reg_addr, + (unsigned int)cmdpara_chip.value); + + return 0; +} + +int +dal_pci_conf_read(unsigned char lchip, unsigned int offset, unsigned int* value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + pci_read_config_dword(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->pci_dev, offset, value); + } + + return 0; +} + +int +dal_pci_conf_write(unsigned char lchip, unsigned int offset, unsigned int value) +{ + if (!VERIFY_CHIP_INDEX(lchip)) + { + return -1; + } + + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + pci_write_config_dword(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->pci_dev, offset, value); + } + + return 0; +} +int +dal_user_read_pci_conf(unsigned long arg) +{ + dal_pci_cfg_ioctl_t dal_cfg; + + if (copy_from_user(&dal_cfg, (void*)arg, sizeof(dal_pci_cfg_ioctl_t))) + { + return -EFAULT; + } + + if (dal_pci_conf_read(dal_cfg.lchip, dal_cfg.offset, &dal_cfg.value)) + { + printk("dal_pci_conf_read failed.\n"); + return -EFAULT; + } + + if (copy_to_user((dal_pci_cfg_ioctl_t*)arg, (void*)&dal_cfg, sizeof(dal_pci_cfg_ioctl_t))) + { + return -EFAULT; + } + + return 0; +} + +int +dal_user_write_pci_conf(unsigned long arg) +{ + dal_pci_cfg_ioctl_t dal_cfg; + + if (copy_from_user(&dal_cfg, (void*)arg, sizeof(dal_pci_cfg_ioctl_t))) + { + return -EFAULT; + } + + return dal_pci_conf_write(dal_cfg.lchip, dal_cfg.offset, dal_cfg.value); +} + +static int +linux_get_device(unsigned long arg) +{ + dal_user_dev_t user_dev; + int lchip = 0; + + if (copy_from_user(&user_dev, (void*)arg, sizeof(user_dev))) + { + return -EFAULT; + } + + user_dev.chip_num = dal_chip_num; + lchip = user_dev.lchip; + + if (lchip < dal_chip_num) + { + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + user_dev.phy_base0 = (unsigned int)((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->phys_address; + user_dev.phy_base1 = (unsigned int)(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->phys_address >> 32); + user_dev.bus_no = ((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->pci_dev->bus->number; + user_dev.dev_no = ((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->pci_dev->device; + user_dev.fun_no = ((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->pci_dev->devfn; + user_dev.soc_active = 0; + } +#if defined(SOC_ACTIVE) + if (DAL_CPU_MODE_TYPE_LOCAL == active_type[lchip]) + { + user_dev.phy_base0 = (unsigned int)((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->phys_address; + user_dev.phy_base1 = (unsigned int)(((dal_kern_pcie_dev_t*)(dal_dev[lchip]))->phys_address >> 32); + user_dev.bus_no = 0; + user_dev.dev_no = CTC_TSINGMA_DEVICE_ID; + user_dev.fun_no = 0; + user_dev.soc_active = 1; + } +#endif + } + + if (copy_to_user((dal_user_dev_t*)arg, (void*)&user_dev, sizeof(user_dev))) + { + return -EFAULT; + } + + return 0; +} + +/* set dal version, copy to user */ +static int +linux_get_dal_version(unsigned long arg) +{ + int dal_ver = VERSION_1DOT2; /* set dal version */ + + if (copy_to_user((int*)arg, (void*)&dal_ver, sizeof(dal_ver))) + { + return -EFAULT; + } + + dal_version = dal_ver; /* up sw */ + + return 0; +} + +static int +linux_get_dma_info(unsigned long arg) +{ + dal_dma_info_t dma_para; + + if (copy_from_user(&dma_para, (void*)arg, sizeof(dal_dma_info_t))) + { + return -EFAULT; + } + + dma_para.phy_base = (unsigned int)dma_phy_base[dma_para.lchip]; + dma_para.phy_base_hi = dma_phy_base[dma_para.lchip] >> 32; + dma_para.virt_base = dma_virt_base[dma_para.lchip]; + dma_para.size = dma_mem_size; + + printk("dal dma phy addr: 0x%llx, virt addr: %p.\n", dma_phy_base[dma_para.lchip], dma_virt_base[dma_para.lchip]); + + if (copy_to_user((dal_dma_info_t*)arg, (void*)&dma_para, sizeof(dal_dma_info_t))) + { + return -EFAULT; + } + + return 0; +} + +static int +dal_get_msi_info(unsigned long arg) +{ + dal_msi_info_t msi_para; + unsigned int lchip = 0; + + /* get lchip form user mode */ + if (copy_from_user(&msi_para, (void*)arg, sizeof(dal_msi_info_t))) + { + return -EFAULT; + } + lchip = msi_para.lchip; + + if (DAL_CPU_MODE_TYPE_PCIE == active_type[lchip]) + { + msi_para.irq_base = msi_irq_base[lchip]; + msi_para.irq_num = msi_irq_num[lchip]; + } +#if defined(SOC_ACTIVE) + if (DAL_CPU_MODE_TYPE_LOCAL == active_type[lchip]) + { + msi_para.irq_base = dal_int[0].irq; + msi_para.irq_num = CTC_MAX_INTR_NUM; + } +#endif + + /* send msi info to user mode */ + if (copy_to_user((dal_msi_info_t*)arg, (void*)&msi_para, sizeof(dal_msi_info_t))) + { + return -EFAULT; + } + + return 0; +} + + +static int +dal_get_intr_info(unsigned long arg) +{ + dal_intr_info_t intr_para; + unsigned int intr_num = 0; + + /* get lchip form user mode */ + if (copy_from_user(&intr_para, (void*)arg, sizeof(dal_intr_info_t))) + { + return -EFAULT; + } + + intr_para.irq_idx = CTC_MAX_INTR_NUM; + for (intr_num=0; intr_num< CTC_MAX_INTR_NUM; intr_num++) + { + if (intr_para.irq == dal_isr[intr_num].irq) + { + intr_para.irq_idx = intr_num; + break; + } + } + + if (CTC_MAX_INTR_NUM == intr_para.irq_idx) + { + printk("Interrupt %d cann't find.\n", intr_para.irq); + } + /* send msi info to user mode */ + if (copy_to_user((dal_intr_info_t*)arg, (void*)&intr_para, sizeof(dal_intr_info_t))) + { + return -EFAULT; + } + + return 0; +} + +int +dal_cache_inval(unsigned long ptr, unsigned int length) +{ +#ifdef DMA_CACHE_COHERENCE_EN + /*dma_cache_wback_inv((unsigned long)intr_para.ptr, intr_para.length);*/ + + dma_sync_single_for_cpu(NULL, ptr, length, DMA_FROM_DEVICE); + + /*dma_cache_sync(NULL, (void*)bus_to_virt(intr_para.ptr), intr_para.length, DMA_FROM_DEVICE);*/ +#endif + return 0; +} + +int +dal_cache_flush(unsigned long ptr, unsigned int length) +{ +#ifdef DMA_CACHE_COHERENCE_EN + /*dma_cache_wback_inv(intr_para.ptr, intr_para.length);*/ + + dma_sync_single_for_device(NULL, ptr, length, DMA_TO_DEVICE); + + /*dma_cache_sync(NULL, (void*)bus_to_virt(intr_para.ptr), intr_para.length, DMA_TO_DEVICE);*/ +#endif + return 0; +} + +static int +dal_user_cache_inval(unsigned long arg) +{ +#ifndef DMA_MEM_MODE_PLATFORM + dal_dma_cache_info_t intr_para; + + if (copy_from_user(&intr_para, (void*)arg, sizeof(dal_dma_cache_info_t))) + { + return -EFAULT; + } + + dal_cache_inval(intr_para.ptr, intr_para.length); +#endif + return 0; +} + +static int +dal_user_cache_flush(unsigned long arg) +{ +#ifndef DMA_MEM_MODE_PLATFORM + dal_dma_cache_info_t intr_para; + + if (copy_from_user(&intr_para, (void*)arg, sizeof(dal_dma_cache_info_t))) + { + return -EFAULT; + } + + dal_cache_flush(intr_para.ptr, intr_para.length); +#endif + return 0; +} + +#if defined(SOC_ACTIVE) +static int linux_dal_local_probe(struct platform_device *pdev) +{ + dal_kern_local_dev_t* dev = NULL; + unsigned int temp = 0; + unsigned int lchip = 0; + int i = 0; + int irq = 0; + struct resource * res = NULL; + + printk(KERN_WARNING "********found soc dal device*****\n"); + + for (lchip = 0; lchip < DAL_MAX_CHIP_NUM; lchip ++) + { + if (NULL == dal_dev[lchip]) + { + break; + } + } + + if (lchip >= DAL_MAX_CHIP_NUM) + { + printk("Exceed max local chip num\n"); + return -1; + } + + if (NULL == dal_dev[lchip]) + { + dal_dev[lchip] = kmalloc(sizeof(dal_kern_local_dev_t), GFP_ATOMIC); + if (NULL == dal_dev[lchip]) + { + printk("no memory for dal soc dev, lchip %d\n", lchip); + return -1; + } + } + dev = dal_dev[lchip]; + if (NULL == dev) + { + printk("Cannot obtain PCI resources\n"); + } + + lchip = lchip; + dal_chip_num += 1; + + dev->pci_dev = pdev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dev->phys_address = res->start; + dev->logic_address = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(dev->logic_address)) + { + kfree(dev); + return PTR_ERR(dev->logic_address); + } + + for (i = 0; i < CTC_MAX_INTR_NUM; i++) + { + irq = platform_get_irq(pdev, i); + if (irq < 0) + { + printk( "can't get irq number\n"); + kfree(dev); + return irq; + } + dal_int[i].irq = irq; + printk( "irq %d vector %d\n", i, irq); + } + + active_type[lchip] = DAL_CPU_MODE_TYPE_LOCAL; + _dal_pci_read(lchip, 0x48, &temp); + if (((temp >> 8) & 0xffff) == 0x3412) + { + printk("Little endian Cpu detected!!! \n"); + _dal_pci_write(lchip, 0x48, 0xFFFFFFFF); + } + + /* alloc dma_mem_size for every chip */ + if (dma_mem_size) + { + dal_alloc_dma_pool(lchip, dma_mem_size); + + /*add check Dma memory pool cannot cross 4G space*/ + if ((0==(dma_phy_base[lchip]>>32)) && (0!=((dma_phy_base[lchip]+dma_mem_size)>>32))) + { + printk("Dma malloc memory cross 4G space!!!!!! \n"); + kfree(dev); + return -1; + } + } + + printk(KERN_WARNING "linux_dal_probe end*****\n"); + + return 0; +} +#endif + +int linux_dal_pcie_probe(struct pci_dev* pdev, const struct pci_device_id* id) +{ + dal_kern_pcie_dev_t* dev = NULL; + unsigned int temp = 0; + unsigned int lchip = 0; + int bar = 0; + int ret = 0; + /*unsigned int devid = 0;*/ + + printk(KERN_WARNING "********found cpu dal device*****\n"); + + for (lchip = 0; lchip < DAL_MAX_CHIP_NUM; lchip ++) + { + if (NULL == dal_dev[lchip]) + { + break; + } + } + + if (lchip >= DAL_MAX_CHIP_NUM) + { + printk("Exceed max local chip num\n"); + return -1; + } + + if (NULL == dal_dev[lchip]) + { + dal_dev[lchip] = kmalloc(sizeof(dal_kern_pcie_dev_t), GFP_ATOMIC); + if (NULL == dal_dev[lchip]) + { + printk("no memory for dal cpu dev, lchip %d\n", lchip); + return -1; + } + } + dev = dal_dev[lchip]; + if (NULL == dev) + { + printk("Cannot obtain PCI resources\n"); + } + + lchip = lchip; + dal_chip_num += 1; + + dev->pci_dev = pdev; + + if (pdev->device == 0x5236) + { + printk("use bar2 to config memory space\n"); + bar = 2; + } + + if (pci_enable_device(pdev) < 0) + { + printk("Cannot enable PCI device: vendor id = %x, device id = %x\n", + pdev->vendor, pdev->device); + } + + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); + if (ret) + { + ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (ret) + { + printk("Could not set PCI DMA Mask\n"); + kfree(dev); + return ret; + } + } + + if (pci_request_regions(pdev, DAL_NAME) < 0) + { + printk("Cannot obtain PCI resources\n"); + } + + dev->phys_address = pci_resource_start(pdev, bar); + dev->logic_address = (uintptr)ioremap_nocache(dev->phys_address, + pci_resource_len(dev->pci_dev, bar)); + + active_type[lchip] = DAL_CPU_MODE_TYPE_PCIE; + + _dal_pci_read(lchip, 0x48, &temp); + if (((temp >> 8) & 0xffff) == 0x3412) + { + printk("Little endian Cpu detected!!! \n"); + _dal_pci_write(lchip, 0x48, 0xFFFFFFFF); + } + + pci_set_master(pdev); + + + /* alloc dma_mem_size for every chip */ + if (dma_mem_size) + { + dal_alloc_dma_pool(lchip, dma_mem_size); + + /*add check Dma memory pool cannot cross 4G space*/ + if ((0==(dma_phy_base[lchip]>>32)) && (0!=((dma_phy_base[lchip]+dma_mem_size)>>32))) + { + printk("Dma malloc memory cross 4G space!!!!!! \n"); + kfree(dev); + return -1; + } + } + + printk(KERN_WARNING "linux_dal_probe end*****\n"); + + return 0; +} + +#if defined(SOC_ACTIVE) +static int +linux_dal_local_remove(struct platform_device *pdev) +{ + unsigned int lchip = 0; + unsigned int flag = 0; + dal_kern_local_dev_t* dev = NULL; + + for (lchip = 0; lchip < DAL_MAX_CHIP_NUM; lchip ++) + { + dev = dal_dev[lchip]; + if ((NULL != dev )&& (pdev == dev->pci_dev)) + { + flag = 1; + break; + } + } + + if (1 == flag) + { + dal_free_dma_pool(lchip); + dev->pci_dev = NULL; + kfree(dev); + dal_chip_num--; + active_type[lchip] = DAL_CPU_MODE_TYPE_NONE; + } + + return 0; +} +#endif + +void +linux_dal_pcie_remove(struct pci_dev* pdev) +{ + unsigned int lchip = 0; + unsigned int flag = 0; + dal_kern_pcie_dev_t* dev = NULL; + + for (lchip = 0; lchip < DAL_MAX_CHIP_NUM; lchip ++) + { + dev = dal_dev[lchip]; + if ((NULL != dev )&& (pdev == dev->pci_dev)) + { + flag = 1; + break; + } + } + + if (1 == flag) + { + dal_free_dma_pool(lchip); + pci_release_regions(pdev); + pci_disable_device(pdev); + dev->pci_dev = NULL; + kfree(dev); + dal_chip_num--; + active_type[lchip] = DAL_CPU_MODE_TYPE_NONE; + } +} + +#ifdef CONFIG_COMPAT +static long +linux_dal_ioctl(struct file* file, + unsigned int cmd, unsigned long arg) +#else + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) +static long +linux_dal_ioctl(struct file* file, + unsigned int cmd, unsigned long arg) +#else +static int +linux_dal_ioctl(struct inode* inode, struct file* file, + unsigned int cmd, unsigned long arg) +#endif + +#endif +{ + switch (cmd) + { + + case CMD_READ_CHIP: + return dal_pci_read(arg); + + case CMD_WRITE_CHIP: + return dal_pci_write(arg); + + case CMD_GET_DEVICES: + return linux_get_device(arg); + + case CMD_GET_DAL_VERSION: + return linux_get_dal_version(arg); + + case CMD_GET_DMA_INFO: + return linux_get_dma_info(arg); + + case CMD_PCI_CONFIG_READ: + return dal_user_read_pci_conf(arg); + + case CMD_PCI_CONFIG_WRITE: + return dal_user_write_pci_conf(arg); + + case CMD_REG_INTERRUPTS: + return dal_user_interrupt_register(arg); + + case CMD_UNREG_INTERRUPTS: + return dal_user_interrupt_unregister(arg); + + case CMD_EN_INTERRUPTS: + return dal_user_interrupt_set_en(arg); + + case CMD_SET_MSI_CAP: + return dal_set_msi_cap(arg); + + case CMD_GET_MSI_INFO: + return dal_get_msi_info(arg); + + case CMD_IRQ_MAPPING: + return dal_create_irq_mapping(arg); + + case CMD_GET_INTR_INFO: + return dal_get_intr_info(arg); + + case CMD_CACHE_INVAL: + return dal_user_cache_inval(arg); + + case CMD_CACHE_FLUSH: + return dal_user_cache_flush(arg); + + default: + break; + } + + return 0; +} + +static unsigned int +linux_dal_poll0(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[0], p); + local_irq_save(flags); + if (poll_intr_trigger[0]) + { + poll_intr_trigger[0] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll1(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[1], p); + local_irq_save(flags); + if (poll_intr_trigger[1]) + { + poll_intr_trigger[1] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll2(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[2], p); + local_irq_save(flags); + if (poll_intr_trigger[2]) + { + poll_intr_trigger[2] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll3(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[3], p); + local_irq_save(flags); + if (poll_intr_trigger[3]) + { + poll_intr_trigger[3] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll4(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[4], p); + local_irq_save(flags); + if (poll_intr_trigger[4]) + { + poll_intr_trigger[4] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll5(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[5], p); + local_irq_save(flags); + if (poll_intr_trigger[5]) + { + poll_intr_trigger[5] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll6(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[6], p); + local_irq_save(flags); + if (poll_intr_trigger[6]) + { + poll_intr_trigger[6] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static unsigned int +linux_dal_poll7(struct file* filp, struct poll_table_struct* p) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &poll_intr[7], p); + local_irq_save(flags); + if (poll_intr_trigger[7]) + { + poll_intr_trigger[7] = 0; + mask |= POLLIN | POLLRDNORM; + } + + local_irq_restore(flags); + + return mask; +} + +static struct pci_driver linux_dal_pcie_driver = +{ + .name = DAL_NAME, + .id_table = dal_id_table, + .probe = linux_dal_pcie_probe, + .remove = linux_dal_pcie_remove, +}; +#if defined(SOC_ACTIVE) +static struct platform_driver linux_dal_local_driver = +{ + .probe = linux_dal_local_probe, + .remove = linux_dal_local_remove, + .driver = { + .name = DAL_NAME, + .of_match_table = of_match_ptr(linux_dal_of_match), + }, +}; +#endif + +static struct file_operations fops = +{ + .owner = THIS_MODULE, +#ifdef CONFIG_COMPAT + .compat_ioctl = linux_dal_ioctl, + .unlocked_ioctl = linux_dal_ioctl, +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) + .unlocked_ioctl = linux_dal_ioctl, +#else + .ioctl = linux_dal_ioctl, +#endif +#endif +}; + +static int __init +linux_dal_init(void) +{ + int ret = 0; + + /* Get DMA memory pool size form dal.ok input param, or use default dma_mem_size */ + if (dma_pool_size) + { + if ((dma_pool_size[strlen(dma_pool_size) - 1] & ~0x20) == 'M') + { + dma_mem_size = simple_strtoul(dma_pool_size, NULL, 0); + printk("dma_mem_size: 0x%x \n", dma_mem_size); + + dma_mem_size *= MB_SIZE; + } + else + { + printk("DMA memory pool size must be specified as e.g. dma_pool_size=8M\n"); + } + + if (dma_mem_size & (dma_mem_size - 1)) + { + printk("dma_mem_size must be a power of 2 (1M, 2M, 4M, 8M etc.)\n"); + dma_mem_size = 0; + } + } + + ret = register_chrdev(DAL_DEV_MAJOR, DAL_NAME, &fops); + if (ret < 0) + { + printk(KERN_WARNING "Register linux_dal device, ret %d\n", ret); + return ret; + } + + ret = pci_register_driver(&linux_dal_pcie_driver); + if (ret < 0) + { + printk(KERN_WARNING "Register ASIC PCI driver failed, ret %d\n", ret); + return ret; + } +#if defined(SOC_ACTIVE) + ret = platform_driver_register(&linux_dal_local_driver); + if (ret < 0) + { + printk(KERN_WARNING "Register ASIC LOCALBUS driver failed, ret %d\n", ret); + } +#endif + + /* alloc /dev/linux_dal node */ + dal_class = class_create(THIS_MODULE, DAL_NAME); + device_create(dal_class, NULL, MKDEV(DAL_DEV_MAJOR, 0), NULL, DAL_NAME); + + /* init interrupt function */ + intr_handler_fun[0] = intr0_handler; + intr_handler_fun[1] = intr1_handler; + intr_handler_fun[2] = intr2_handler; + intr_handler_fun[3] = intr3_handler; + intr_handler_fun[4] = intr4_handler; + intr_handler_fun[5] = intr5_handler; + intr_handler_fun[6] = intr6_handler; + intr_handler_fun[7] = intr7_handler; + + return ret; +} + +static void __exit +linux_dal_exit(void) +{ + device_destroy(dal_class, MKDEV(DAL_DEV_MAJOR, 0)); + class_destroy(dal_class); + unregister_chrdev(DAL_DEV_MAJOR, "linux_dal"); + pci_unregister_driver(&linux_dal_pcie_driver); +#if defined(SOC_ACTIVE) + platform_driver_unregister(&linux_dal_local_driver); +#endif +} + +module_init(linux_dal_init); +module_exit(linux_dal_exit); +EXPORT_SYMBOL(dal_get_dal_ops); +EXPORT_SYMBOL(dal_cache_inval); +EXPORT_SYMBOL(dal_cache_flush); + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_kernel.h b/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_kernel.h new file mode 100644 index 000000000000..9aed4a723492 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_kernel.h @@ -0,0 +1,183 @@ +/** + @file dal_kernel_io.h + + @author Copyright (C) 2012 Centec Networks Inc. All rights reserved. + + @date 2012-4-9 + + @version v2.0 + +*/ +#ifndef _DAL_KERNEL_H_ +#define _DAL_KERNEL_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#define SOC_ACTIVE +#define DMA_MEM_MODE_PLATFORM + +#if defined(CONFIG_RESOURCES_64BIT) || defined(CONFIG_PHYS_ADDR_T_64BIT) +#define PHYS_ADDR_IS_64BIT +#endif + +#ifndef SDK_IN_USERMODE +#ifdef PHYS_ADDR_IS_64BIT +typedef long long intptr; +typedef unsigned long long uintptr; +#else +typedef int intptr; +typedef unsigned int uintptr; +#endif +#endif + +#ifndef STATIC +#define STATIC static +#endif +#define DAL_PCI_READ_ADDR 0x0 +#define DAL_PCI_READ_DATA 0xc +#define DAL_PCI_WRITE_ADDR 0x8 +#define DAL_PCI_WRITE_DATA 0x4 +#define DAL_PCI_STATUS 0x10 + +#define DAL_PCI_STATUS_IN_PROCESS 31 +#define DAL_PCI_STATUS_BAD_PARITY 5 +#define DAL_PCI_STATUS_CPU_ACCESS_ERR 4 +#define DAL_PCI_STATUS_READ_CMD 3 +#define DAL_PCI_STATUS_REGISTER_ERR 1 +#define DAL_PCI_STATUS_REGISTER_ACK 0 + +#define DAL_PCI_ACCESS_TIMEOUT 0x64 + +#define DAL_NAME "linux_dal" /* "linux_dal" */ + +#define DAL_DEV_MAJOR 198 + +#define DAL_DEV_INTR_MAJOR_BASE 200 + +#define DAL_DEV_NAME "/dev/" DAL_NAME +#define DAL_ONE_KB 1024 +#define DAL_ONE_MB (1024*1024) +struct dal_chip_parm_s +{ + unsigned int lchip; /*tmp should be uint8*/ + unsigned int fpga_id; /*tmp add*/ + unsigned int reg_addr; + unsigned int value; +}; +typedef struct dal_chip_parm_s dal_chip_parm_t; + +struct dal_intr_parm_s +{ + unsigned int irq; + unsigned int enable; +}; +typedef struct dal_intr_parm_s dal_intr_parm_t; + +struct dal_irq_mapping_s +{ + unsigned int hw_irq; + unsigned int sw_irq; +}; +typedef struct dal_irq_mapping_s dal_irq_mapping_t; + +struct dal_user_dev_s +{ + unsigned int chip_num; /*output: local chip number*/ + unsigned int lchip; /*input: local chip id*/ + unsigned int phy_base0; /* low 32bits physical base address */ + unsigned int phy_base1; /* high 32bits physical base address */ + unsigned int bus_no; + unsigned int dev_no; + unsigned int fun_no; + unsigned int soc_active; + void* virt_base[2]; /* !!!!warning!!!!Virtual base address; pointer void* must be last member */ +}; +typedef struct dal_user_dev_s dal_user_dev_t; + +struct dal_pci_cfg_ioctl_s +{ + unsigned int lchip; /* Device ID */ + unsigned int offset; + unsigned int value; +}; +typedef struct dal_pci_cfg_ioctl_s dal_pci_cfg_ioctl_t; + +struct dal_msi_info_s +{ + unsigned int lchip; + unsigned int irq_base; + unsigned int irq_num; +}; +typedef struct dal_msi_info_s dal_msi_info_t; + +struct dal_intr_info_s +{ + unsigned int irq; + unsigned int irq_idx; +}; +typedef struct dal_intr_info_s dal_intr_info_t; + +struct dal_dma_cache_info_s +{ + unsigned long ptr; + unsigned int length; +}; +typedef struct dal_dma_cache_info_s dal_dma_cache_info_t; + +#define CMD_MAGIC 'C' +#define CMD_WRITE_CHIP _IO(CMD_MAGIC, 0) /* for humber ioctrol*/ +#define CMD_READ_CHIP _IO(CMD_MAGIC, 1) /* for humber ioctrol*/ +#define CMD_GET_DEVICES _IO(CMD_MAGIC, 2) +#define CMD_GET_DAL_VERSION _IO(CMD_MAGIC, 3) +#define CMD_PCI_CONFIG_WRITE _IO(CMD_MAGIC, 4) +#define CMD_PCI_CONFIG_READ _IO(CMD_MAGIC, 5) +#define CMD_GET_DMA_INFO _IO(CMD_MAGIC, 6) +#define CMD_REG_INTERRUPTS _IO(CMD_MAGIC, 7) +#define CMD_UNREG_INTERRUPTS _IO(CMD_MAGIC, 8) +#define CMD_EN_INTERRUPTS _IO(CMD_MAGIC, 9) +#define CMD_I2C_READ _IO(CMD_MAGIC, 10) +#define CMD_I2C_WRITE _IO(CMD_MAGIC, 11) +#define CMD_GET_MSI_INFO _IO(CMD_MAGIC, 12) +#define CMD_SET_MSI_CAP _IO(CMD_MAGIC, 13) +#define CMD_IRQ_MAPPING _IO(CMD_MAGIC, 14) +#define CMD_GET_INTR_INFO _IO(CMD_MAGIC, 15) +#define CMD_CACHE_INVAL _IO(CMD_MAGIC, 16) +#define CMD_CACHE_FLUSH _IO(CMD_MAGIC, 17) +#define CMD_GET_KNET_VERSION _IO(CMD_MAGIC, 18) +#define CMD_CONNECT_INTERRUPTS _IO(CMD_MAGIC, 19) +#define CMD_DISCONNECT_INTERRUPTS _IO(CMD_MAGIC, 20) +#define CMD_SET_DMA_INFO _IO(CMD_MAGIC, 21) +#define CMD_REG_DMA_CHAN _IO(CMD_MAGIC, 22) +#define CMD_HANDLE_NETIF _IO(CMD_MAGIC, 23) + +enum dal_version_e +{ + VERSION_MIN, + VERSION_1DOT0, + VERSION_1DOT1, + VERSION_1DOT2, + + VERSION_MAX +}; +typedef enum dal_version_e dal_version_t; + +struct dal_ops_s { + int (*interrupt_connect)(unsigned int irq, int prio, void (*)(void*), void *data); + int (*interrupt_disconnect)(unsigned int irq); +}; +typedef struct dal_ops_s dal_ops_t; + +/* We try to assemble a contiguous segment from chunks of this size */ +#define DMA_BLOCK_SIZE (512 * DAL_ONE_KB) + +extern int dal_get_dal_ops(dal_ops_t **dal_ops); +extern int dal_cache_inval(unsigned long ptr, unsigned int length); +extern int dal_cache_flush(unsigned long ptr, unsigned int length); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_mpool.c b/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_mpool.c new file mode 100644 index 000000000000..f3b5f85e5ecd --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_mpool.c @@ -0,0 +1,360 @@ + +/*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ +//#include "sal.h" +#include "dal_mpool.h" +#define DAL_MAX_CHIP_NUM 32 +#ifdef __KERNEL__ +#include +#include + +#define DAL_MALLOC(x) kmalloc(x, GFP_ATOMIC) +#define DAL_FREE(x) kfree(x) + +static spinlock_t dal_mpool_lock[DAL_MAX_CHIP_NUM]; +#define MPOOL_LOCK_INIT() spin_lock_init(&dal_mpool_lock[lchip]) +#define MPOOL_LOCK_DEINIT() +#define MPOOL_LOCK() unsigned long flags; spin_lock_irqsave(&dal_mpool_lock[lchip], flags) +#define MPOOL_UNLOCK() spin_unlock_irqrestore(&dal_mpool_lock[lchip], flags) +#define DAL_PRINT(fmt,arg...) printk(fmt,##arg) +#else /* !__KERNEL__*/ + +#include +#include "sal.h" +#define DAL_MALLOC(x) sal_malloc(x) +#define DAL_FREE(x) sal_free(x) +static sal_mutex_t* dal_mpool_lock[DAL_MAX_CHIP_NUM]; +#define MPOOL_LOCK_INIT() sal_mutex_create(&dal_mpool_lock[lchip]) +#define MPOOL_LOCK_DEINIT() sal_mutex_destroy(dal_mpool_lock[lchip]) +#define MPOOL_LOCK() sal_mutex_lock(dal_mpool_lock[lchip]) +#define MPOOL_UNLOCK() sal_mutex_unlock(dal_mpool_lock[lchip]) +#define DAL_PRINT(fmt,arg...) sal_printf(fmt,##arg) + +#endif /* __KERNEL__ */ +dal_mpool_mem_t* g_free_block_ptr = NULL; + +/* System cache line size */ +#ifndef DAL_CACHE_LINE_BYTES +#define DAL_CACHE_LINE_BYTES 256 +#endif + +static dal_mpool_mem_t* p_desc_pool[DAL_MAX_CHIP_NUM] = {0}; +static dal_mpool_mem_t* p_data_pool[DAL_MAX_CHIP_NUM] = {0}; + +/*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ +int +dal_mpool_init(uint8_t lchip) +{ + MPOOL_LOCK_INIT(); + return 0; +} +/*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ +int +dal_mpool_deinit(uint8_t lchip) +{ + MPOOL_LOCK_DEINIT(); + return 0; +} + +dal_mpool_mem_t* +_dal_mpool_create(void* base, int size, int type) +{ + dal_mpool_mem_t* head = NULL; + dal_mpool_mem_t* tail = NULL; + + head = (dal_mpool_mem_t*)DAL_MALLOC(sizeof(dal_mpool_mem_t)); + if (head == NULL) + { + return NULL; + } + + tail = (dal_mpool_mem_t*)DAL_MALLOC(sizeof(dal_mpool_mem_t)); + if (tail == NULL) + { + DAL_FREE(head); + return NULL; + } + + head->size = tail->size = 0; + head->type = type; + head->address = base; + tail->address = head->address + size; + head->next = tail; + tail->next = NULL; + + return head; +} + +dal_mpool_mem_t* +dal_mpool_create(unsigned char lchip, void* base, int size) +{ + dal_mpool_mem_t* head = NULL; + int mod = (int)(((unsigned long)base) & (DAL_CACHE_LINE_BYTES - 1)); + + MPOOL_LOCK(); + + if (mod) + { + base = (char*)base + (DAL_CACHE_LINE_BYTES - mod); + size -= (DAL_CACHE_LINE_BYTES - mod); + } + + size &= ~(DAL_CACHE_LINE_BYTES - 1); + + /* init for common linkptr, only used for GB */ + head = _dal_mpool_create(base, size, DAL_MPOOL_TYPE_USELESS); + if (NULL == head) + { + MPOOL_UNLOCK(); + return NULL; + } + + /* init for desc linkptr */ + p_desc_pool[lchip] = _dal_mpool_create(base, DAL_MPOOL_MAX_DESX_SIZE, DAL_MPOOL_TYPE_DESC); + if (NULL == p_desc_pool[lchip]) + { + MPOOL_UNLOCK(); + DAL_FREE(head->next); + DAL_FREE(head); + return NULL; + } + + /* init for data linkptr */ + p_data_pool[lchip] = _dal_mpool_create(((char*)base+DAL_MPOOL_MAX_DESX_SIZE), (size - DAL_MPOOL_MAX_DESX_SIZE), DAL_MPOOL_TYPE_DATA); + if (NULL == p_data_pool[lchip]) + { + MPOOL_UNLOCK(); + DAL_FREE(head->next); + DAL_FREE(head); + DAL_FREE(p_desc_pool[lchip]->next); + DAL_FREE(p_desc_pool[lchip]); + return NULL; + } + + MPOOL_UNLOCK(); + + return head; +} + +dal_mpool_mem_t* +_dal_mpool_alloc_comon(dal_mpool_mem_t* ptr, int size, int type) +{ + dal_mpool_mem_t* new_ptr = NULL; + + while (ptr && ptr->next) + { + if (ptr->next->address - (ptr->address + ptr->size) >= size) + { + break; + } + + ptr = ptr->next; + } + + if (!(ptr && ptr->next)) + { + return NULL; + } + + new_ptr = DAL_MALLOC(sizeof(dal_mpool_mem_t)); + if (!new_ptr) + { + return NULL; + } + + new_ptr->type = type; + new_ptr->address = ptr->address + ptr->size; + new_ptr->size = size; + new_ptr->next = ptr->next; + ptr->next = new_ptr; + + return new_ptr; +} + +void* +dal_mpool_alloc(unsigned char lchip, dal_mpool_mem_t* pool, int size, int type) +{ + dal_mpool_mem_t* ptr = NULL; + dal_mpool_mem_t* new_ptr = NULL; + int mod; + + MPOOL_LOCK(); + + mod = size & (DAL_CACHE_LINE_BYTES - 1); + if (mod != 0) + { + size += (DAL_CACHE_LINE_BYTES - mod); + } + + switch(type) + { + case DAL_MPOOL_TYPE_USELESS: + ptr = pool; + new_ptr = _dal_mpool_alloc_comon(ptr, size, type); + if (NULL == new_ptr) + { + MPOOL_UNLOCK(); + return NULL; + } + break; + case DAL_MPOOL_TYPE_DESC: + ptr = p_desc_pool[lchip]; + new_ptr = _dal_mpool_alloc_comon(ptr, size, type); + if (NULL == new_ptr) + { + MPOOL_UNLOCK(); + return NULL; + } + break; + case DAL_MPOOL_TYPE_DATA: + ptr = p_data_pool[lchip]; + new_ptr = _dal_mpool_alloc_comon(ptr, size, type); + if (NULL == new_ptr) + { + MPOOL_UNLOCK(); + return NULL; + } + break; + default: + MPOOL_UNLOCK(); + return NULL; + break; + } + + MPOOL_UNLOCK(); + if( NULL == new_ptr ) + { + return NULL; + } + + return new_ptr->address; +} + +void +_dal_mpool_free(dal_mpool_mem_t* ptr, void* addr, int type) +{ + unsigned char* address = (unsigned char*)addr; + dal_mpool_mem_t* prev = NULL; + + while (ptr && ptr->next) + { + if (ptr->next->address == address) + { + break; + } + + ptr = ptr->next; + } + + if (ptr && ptr->next) + { + prev = ptr; + ptr = ptr->next; + prev->next = ptr->next; + DAL_FREE(ptr); + } + + return; +} + +void +dal_mpool_free(unsigned char lchip, dal_mpool_mem_t* pool, void* addr) +{ + dal_mpool_mem_t* ptr = pool; + + MPOOL_LOCK(); + + switch(pool->type) + { + case DAL_MPOOL_TYPE_USELESS: + ptr = pool; + _dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_USELESS); + break; + case DAL_MPOOL_TYPE_DESC: + ptr = p_desc_pool[lchip]; + _dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_DESC); + break; + case DAL_MPOOL_TYPE_DATA: + ptr = p_data_pool[lchip]; + _dal_mpool_free(ptr, addr, DAL_MPOOL_TYPE_DATA); + break; + default: + break; + } + + MPOOL_UNLOCK(); + return; +} + +int +dal_mpool_destroy(unsigned char lchip, dal_mpool_mem_t* pool) +{ + dal_mpool_mem_t* ptr, * next; + + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = next) + { + next = ptr->next; + DAL_FREE(ptr); + } + + for (ptr = p_desc_pool[lchip]; ptr; ptr = next) + { + next = ptr->next; + DAL_FREE(ptr); + } + + for (ptr = p_data_pool[lchip]; ptr; ptr = next) + { + next = ptr->next; + DAL_FREE(ptr); + } + + MPOOL_UNLOCK(); + + return 0; +} + +int +dal_mpool_usage(dal_mpool_mem_t* pool, int type) +{ + int usage = 0; + dal_mpool_mem_t* ptr; + /*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ + uint8_t lchip = 0; + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = ptr->next) + { + if (ptr->type == type || ptr->type == -1) + { + usage += ptr->size; + } + } + + MPOOL_UNLOCK(); + + return usage; +} + +int +dal_mpool_debug(dal_mpool_mem_t* pool) +{ + dal_mpool_mem_t* ptr; + int index = 0; + /*SYSTEM MODIFIED, Added by weij for compile SDK, 2017-09-11*/ + uint8_t lchip = 0; + MPOOL_LOCK(); + + for (ptr = pool; ptr; ptr = ptr->next) + { + /* DAL_PRINT("%2dst mpool block: address=0x%8x, size=0x%x \n", index, (unsigned int)ptr->address, ptr->size);*/ + DAL_PRINT("%2dst mpool block: address=%p, size=0x%x \n", index, ptr->address, ptr->size); /* note*/ + index++; + } + + MPOOL_UNLOCK(); + + return 0; +} + diff --git a/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_mpool.h b/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_mpool.h new file mode 100644 index 000000000000..4c2e3487e394 --- /dev/null +++ b/platform/centec-arm64/sonic-platform-modules-e530/kdal/dal_mpool.h @@ -0,0 +1,74 @@ +/** + @file dal_mpool.h + + @author Copyright (C) 2011 Centec Networks Inc. All rights reserved. + + @date 2012-5-10 + + @version v2.0 + + This file contains the dma memory init, allocation and free APIs +*/ + +#ifndef _DMA_MPOOL_H +#define _DMA_MPOOL_H +#ifdef __cplusplus +extern "C" { +#endif + +#define DAL_MPOOL_MAX_DESX_SIZE (1024*1024) + +enum dal_mpool_type_e +{ + DAL_MPOOL_TYPE_USELESS, /* just compatible with GB */ + DAL_MPOOL_TYPE_DESC, /* dma mpool op for desc */ + DAL_MPOOL_TYPE_DATA /* dma mpool op for data */ +}; +typedef enum dal_mpool_type_e dal_mpool_type_t; + +struct dal_mpool_mem_s +{ + unsigned char* address; + int size; + int type; + struct dal_mpool_mem_s* next; +}; +typedef struct dal_mpool_mem_s dal_mpool_mem_t; + +/** + @brief This function is to alloc dma memory + + @param[in] size size of memory + + @return NULL + +*/ +extern int +dal_mpool_init(unsigned char lchip); + +extern int +dal_mpool_deinit(unsigned char lchip); + +extern dal_mpool_mem_t* +dal_mpool_create(unsigned char lchip, void* base_ptr, int size); + +extern void* +dal_mpool_alloc(unsigned char lchip, dal_mpool_mem_t* pool, int size, int type); + +extern void +dal_mpool_free(unsigned char lchip, dal_mpool_mem_t* pool, void* addr); + +extern int +dal_mpool_destroy(unsigned char lchip, dal_mpool_mem_t* pool); + +extern int +dal_mpool_usage(dal_mpool_mem_t* pool, int type); + +extern int +dal_mpool_debug(dal_mpool_mem_t* pool); +#ifdef __cplusplus +} +#endif + +#endif /* !_DMA_MPOOL_H */ + diff --git a/platform/centec-arm64/sonic_fit.its b/platform/centec-arm64/sonic_fit.its new file mode 100644 index 000000000000..4503db42d8bc --- /dev/null +++ b/platform/centec-arm64/sonic_fit.its @@ -0,0 +1,62 @@ +/* + *Copyright 2018 CENTEC + * + */ + +/dts-v1/; + +/ { + description = "arm64 kernel, initramfs and FDT blob"; + #address-cells = <1>; + + images { + kernel_ctc { + description = "ARM64 Kernel"; + data = /incbin/("./vmlinuz-4.9.0-11-2-arm64"); + type = "kernel"; + arch = "arm64"; + os = "linux"; + compression = "none"; + load = <0x80080000>; + entry = <0x80080000>; + hash { + algo = "crc32"; + }; + }; + initramfs { + description = "initramfs"; + data = /incbin/("./initramfs.lzma"); + type = "ramdisk"; + arch = "arm64"; + os = "linux"; + compression = "lzma"; + load = <0x85000000>; + entry = <0x85000000>; + hash { + algo = "crc32"; + }; + }; + ctc_fdt { + description = "dtb for tm_ctc5236"; + data = /incbin/("./e530-ctc5236.dtb"); + type = "flat_dt"; + arch = "arm64"; + os = "linux"; + compression = "none"; + load = <0x88000000>; + hash { + algo = "crc32"; + }; + }; + }; + configurations { + default = "e530-ctc5236"; + + e530-ctc5236 { + description = "config for tm_ctc5236"; + kernel = "kernel_ctc"; + ramdisk = "initramfs"; + fdt = "ctc_fdt"; + }; + }; +}; diff --git a/src/sonic-linux-kernel b/src/sonic-linux-kernel index 6650d4eb8d8c..e31a421a5be0 160000 --- a/src/sonic-linux-kernel +++ b/src/sonic-linux-kernel @@ -1 +1 @@ -Subproject commit 6650d4eb8d8c1ea4007145e5ffe17c3821298da2 +Subproject commit e31a421a5be0c66bcbf344f3927ee1876c118ddf