diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py index f4aa5bab..c0bcd1ad 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py @@ -8,11 +8,18 @@ class OnlPlatform_arm_accton_as4610_30_r0(OnlPlatformAccton, SYS_OBJECT_ID=".4610.30" def baseconfig(self): - self.insmod("accton_i2c_cpld") - self.new_i2c_device("as4610_30_cpld", 0x30, 0) - self.insmod("accton_as4610_sfp") + self.insmod("accton_as4610_cpld") self.insmod("accton_as4610_psu") self.insmod("accton_as4610_fan") self.insmod("accton_as4610_leds") self.insmod("ym2651y") + self.insmod("optoe") + + subprocess.call('echo port25 > /sys/bus/i2c/devices/2-0050/port_name', shell=True) + subprocess.call('echo port26 > /sys/bus/i2c/devices/3-0050/port_name', shell=True) + subprocess.call('echo port27 > /sys/bus/i2c/devices/4-0050/port_name', shell=True) + subprocess.call('echo port28 > /sys/bus/i2c/devices/5-0050/port_name', shell=True) + subprocess.call('echo port29 > /sys/bus/i2c/devices/6-0050/port_name', shell=True) + subprocess.call('echo port30 > /sys/bus/i2c/devices/7-0050/port_name', shell=True) + return True diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py index 87383d76..5a32e574 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py @@ -8,13 +8,20 @@ class OnlPlatform_arm_accton_as4610_54_r0(OnlPlatformAccton, SYS_OBJECT_ID=".4610.54" def baseconfig(self): - self.insmod("accton_i2c_cpld") - self.new_i2c_device("as4610_54_cpld", 0x30, 0) - self.insmod("accton_as4610_sfp") + self.insmod("accton_as4610_cpld") self.insmod("accton_as4610_psu") self.insmod("accton_as4610_fan") self.insmod("accton_as4610_leds") self.insmod("ym2651y") + self.insmod("optoe") + + subprocess.call('echo port49 > /sys/bus/i2c/devices/2-0050/port_name', shell=True) + subprocess.call('echo port50 > /sys/bus/i2c/devices/3-0050/port_name', shell=True) + subprocess.call('echo port51 > /sys/bus/i2c/devices/4-0050/port_name', shell=True) + subprocess.call('echo port52 > /sys/bus/i2c/devices/5-0050/port_name', shell=True) + subprocess.call('echo port53 > /sys/bus/i2c/devices/6-0050/port_name', shell=True) + subprocess.call('echo port54 > /sys/bus/i2c/devices/7-0050/port_name', shell=True) + # self.new_i2c_devices( # [ # ("pca9548", 0x70, 1), diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py index f4aa5bab..c0bcd1ad 100644 --- a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py @@ -8,11 +8,18 @@ class OnlPlatform_arm_accton_as4610_30_r0(OnlPlatformAccton, SYS_OBJECT_ID=".4610.30" def baseconfig(self): - self.insmod("accton_i2c_cpld") - self.new_i2c_device("as4610_30_cpld", 0x30, 0) - self.insmod("accton_as4610_sfp") + self.insmod("accton_as4610_cpld") self.insmod("accton_as4610_psu") self.insmod("accton_as4610_fan") self.insmod("accton_as4610_leds") self.insmod("ym2651y") + self.insmod("optoe") + + subprocess.call('echo port25 > /sys/bus/i2c/devices/2-0050/port_name', shell=True) + subprocess.call('echo port26 > /sys/bus/i2c/devices/3-0050/port_name', shell=True) + subprocess.call('echo port27 > /sys/bus/i2c/devices/4-0050/port_name', shell=True) + subprocess.call('echo port28 > /sys/bus/i2c/devices/5-0050/port_name', shell=True) + subprocess.call('echo port29 > /sys/bus/i2c/devices/6-0050/port_name', shell=True) + subprocess.call('echo port30 > /sys/bus/i2c/devices/7-0050/port_name', shell=True) + return True diff --git a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py index 87383d76..5a32e574 100644 --- a/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py +++ b/packages/platforms/accton/armhf/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py @@ -8,13 +8,20 @@ class OnlPlatform_arm_accton_as4610_54_r0(OnlPlatformAccton, SYS_OBJECT_ID=".4610.54" def baseconfig(self): - self.insmod("accton_i2c_cpld") - self.new_i2c_device("as4610_54_cpld", 0x30, 0) - self.insmod("accton_as4610_sfp") + self.insmod("accton_as4610_cpld") self.insmod("accton_as4610_psu") self.insmod("accton_as4610_fan") self.insmod("accton_as4610_leds") self.insmod("ym2651y") + self.insmod("optoe") + + subprocess.call('echo port49 > /sys/bus/i2c/devices/2-0050/port_name', shell=True) + subprocess.call('echo port50 > /sys/bus/i2c/devices/3-0050/port_name', shell=True) + subprocess.call('echo port51 > /sys/bus/i2c/devices/4-0050/port_name', shell=True) + subprocess.call('echo port52 > /sys/bus/i2c/devices/5-0050/port_name', shell=True) + subprocess.call('echo port53 > /sys/bus/i2c/devices/6-0050/port_name', shell=True) + subprocess.call('echo port54 > /sys/bus/i2c/devices/7-0050/port_name', shell=True) + # self.new_i2c_devices( # [ # ("pca9548", 0x70, 1), diff --git a/packages/platforms/accton/armxx/arm-accton-as4610/arm-accton-as4610.dts b/packages/platforms/accton/armxx/arm-accton-as4610/arm-accton-as4610.dts index 87bacbd9..476b04e4 100644 --- a/packages/platforms/accton/armxx/arm-accton-as4610/arm-accton-as4610.dts +++ b/packages/platforms/accton/armxx/arm-accton-as4610/arm-accton-as4610.dts @@ -87,8 +87,8 @@ #address-cells = <1>; #size-cells = <0>; reg = <0>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp1"; + optoe@50 { + compatible = "optoe2"; reg = <0x50>; label = "port49"; }; @@ -99,8 +99,8 @@ #address-cells = <1>; #size-cells = <0>; reg = <1>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp2"; + optoe@50 { + compatible = "optoe2"; reg = <0x50>; label = "port50"; }; @@ -111,8 +111,8 @@ #address-cells = <1>; #size-cells = <0>; reg = <2>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp3"; + optoe@50 { + compatible = "optoe2"; reg = <0x50>; label = "port51"; }; @@ -123,8 +123,8 @@ #address-cells = <1>; #size-cells = <0>; reg = <3>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp4"; + optoe@50 { + compatible = "optoe2"; reg = <0x50>; label = "port52"; }; @@ -135,9 +135,10 @@ #address-cells = <1>; #size-cells = <0>; reg = <4>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp5"; + optoe@50 { + compatible = "optoe1"; reg = <0x50>; + label = "port53"; }; }; @@ -146,9 +147,10 @@ #address-cells = <1>; #size-cells = <0>; reg = <5>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp6"; + optoe@50 { + compatible = "optoe1"; reg = <0x50>; + label = "port54"; }; }; diff --git a/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/sfpi.c b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/sfpi.c index 7199a31a..41379f73 100644 --- a/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/sfpi.c +++ b/packages/platforms/accton/armxx/arm-accton-as4610/arm_accton_as4610/module/src/sfpi.c @@ -24,50 +24,31 @@ * ***********************************************************/ #include +#include #include "platform_lib.h" #include #include "arm_accton_as4610_log.h" -#define MAX_SFP_PATH 64 -static char sfp_node_path[MAX_SFP_PATH] = {0}; -#define FRONT_PORT_MUX_INDEX(port) (port-46) +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/0-0030/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/0-0030/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/0-0030/module_tx_fault_%d" +#define MODULE_PRESENT_ALL_ATTR_CPLD "/sys/bus/i2c/devices/0-0030/module_present_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD "/sys/bus/i2c/devices/0-0030/module_rx_los_all" -static int -sfp_node_read_int(char *node_path, int *value, int data_len) +static int front_port_bus_index(int port) { - int ret = 0; - char buf[8]; - *value = 0; - - ret = deviceNodeReadString(node_path, buf, sizeof(buf), data_len); - - if (ret == 0) { - *value = atoi(buf); - } - - return ret; + return (platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0) ? + (port - 22) : /* PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0 */ + (port - 46) ; /* PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0 */ } -static char* -sfp_get_port_path_addr(int port, int addr, char *node_name) +static int front_port_to_cpld_port(int port) { - int front_port_mux_id; - - if(platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0) - front_port_mux_id = port - 22; - else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/ - front_port_mux_id = port - 46; - - sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-00%d/%s", - front_port_mux_id, addr, node_name); - return sfp_node_path; -} - -static char* -sfp_get_port_path(int port, char *node_name) -{ - return sfp_get_port_path_addr(port, 50, node_name); + return (platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0) ? + (port - 23) : /* PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0 */ + (port - 47) ; /* PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0 */ } /************************************************************ @@ -115,9 +96,9 @@ onlp_sfpi_is_present(int port) * Return < 0 if error. */ int present; - char* path = sfp_get_port_path(port, "sfp_is_present"); - - if (sfp_node_read_int(path, &present, 0) != 0) { + int cpld_port = front_port_to_cpld_port(port); + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, cpld_port) < 0) { AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } @@ -129,7 +110,6 @@ int onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) { uint32_t byte; - char* path; FILE* fp; int port; @@ -140,18 +120,18 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/ port = 48; - path = sfp_get_port_path(port, "sfp_is_present_all"); - fp = fopen(path, "r"); - + /* Read present status of each port */ + fp = fopen(MODULE_PRESENT_ALL_ATTR_CPLD, "r"); if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file."); + AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD."); return ONLP_STATUS_E_INTERNAL; } + int count = fscanf(fp, "%x", &byte); fclose(fp); if(count != 1) { /* Likely a CPLD read timeout. */ - AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file."); + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD."); return ONLP_STATUS_E_INTERNAL; } @@ -173,7 +153,6 @@ int onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) { uint32_t byte; - char* path; FILE* fp; int port; @@ -182,16 +161,18 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/ port = 48; - path = sfp_get_port_path(port, "sfp_rx_los_all"); - fp = fopen(path, "r"); + /* Read present status of each port */ + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD, "r"); if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file."); + AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD."); return ONLP_STATUS_E_INTERNAL; } + int count = fscanf(fp, "%x", &byte); fclose(fp); if(count != 1) { - AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file."); + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_rx_los_all device file of CPLD."); return ONLP_STATUS_E_INTERNAL; } @@ -212,32 +193,51 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) int onlp_sfpi_eeprom_read(int port, uint8_t data[256]) { - char* path = sfp_get_port_path(port, "sfp_eeprom"); - /* * Read the SFP eeprom into data[] * * Return MISSING if SFP is missing. * Return OK if eeprom is read */ + int size = 0; memset(data, 0, 256); - if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) { + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, front_port_bus_index(port)) != ONLP_STATUS_OK) { AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + return ONLP_STATUS_OK; } int onlp_sfpi_dom_read(int port, uint8_t data[256]) { - char* path = sfp_get_port_path_addr(port, 51, "sfp_eeprom"); - memset(data, 0, 256); + FILE* fp; + char file[64] = {0}; + + sprintf(file, PORT_EEPROM_FORMAT, front_port_bus_index(port)); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } - if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) { - AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port); return ONLP_STATUS_E_INTERNAL; } @@ -247,45 +247,24 @@ onlp_sfpi_dom_read(int port, uint8_t data[256]) int onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { - int rv; - - switch(control) - { - case ONLP_SFP_CONTROL_TX_DISABLE: - { - char* path = sfp_get_port_path(port, "sfp_tx_disable"); - - if (deviceNodeWriteInt(path, value, 0) != 0) { - AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); - rv = ONLP_STATUS_E_INTERNAL; - } - else { - rv = ONLP_STATUS_OK; - } - break; - } - - default: - rv = ONLP_STATUS_E_UNSUPPORTED; - break; - } - - return rv; + return ONLP_STATUS_E_UNSUPPORTED; } int onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { int rv; - char* path = NULL; + int cpld_port = front_port_to_cpld_port(port); + + if (cpld_port > 4) { + return ONLP_STATUS_E_UNSUPPORTED; + } switch(control) { case ONLP_SFP_CONTROL_RX_LOS: { - path = sfp_get_port_path(port, "sfp_rx_los"); - - if (sfp_node_read_int(path, value, 0) != 0) { + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, cpld_port) < 0) { AIM_LOG_ERROR("Unable to read rx_los status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -297,9 +276,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_FAULT: { - path = sfp_get_port_path(port, "sfp_tx_fault"); - - if (sfp_node_read_int(path, value, 0) != 0) { + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, cpld_port) < 0) { AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -309,20 +286,6 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) break; } - case ONLP_SFP_CONTROL_TX_DISABLE: - { - path = sfp_get_port_path(port, "sfp_tx_disable"); - - if (sfp_node_read_int(path, value, 0) != 0) { - AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); - rv = ONLP_STATUS_E_INTERNAL; - } - else { - rv = ONLP_STATUS_OK; - } - break; - } - default: rv = ONLP_STATUS_E_UNSUPPORTED; } @@ -330,9 +293,9 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) return rv; } - int onlp_sfpi_denit(void) { return ONLP_STATUS_OK; } + diff --git a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_cpld.c b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_cpld.c new file mode 100644 index 00000000..2ee2d163 --- /dev/null +++ b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_cpld.c @@ -0,0 +1,627 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as4610_54 CPLD + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ +#define AS4610_CPLD_SLAVE_ADDR 0x30 +#define AS4610_CPLD_PID_OFFSET 0x01 /* Product ID offset */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as4610_54_cpld +}; + +enum as4610_product_id_e { + PID_AS4610_30T, + PID_AS4610_30P, + PID_AS4610_54T, + PID_AS4610_54P, + PID_RESERVED, + PID_AS4610_54T_B, + PID_UNKNOWN +}; + +struct as4610_54_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as4610_54_cpld_id[] = { + { "as4610_54_cpld", as4610_54_cpld }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as4610_54_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index + +enum as4610_54_cpld1_sysfs_attributes { + CPLD_VERSION, + PRODUCT_ID, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_RXLOS_ATTR_ID(1), + TRANSCEIVER_RXLOS_ATTR_ID(2), + TRANSCEIVER_RXLOS_ATTR_ID(3), + TRANSCEIVER_RXLOS_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_product_id(struct device *dev, struct device_attribute *attr, + char *buf); +static int as4610_54_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as4610_54_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index) +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +static SENSOR_DEVICE_ATTR(product_id, S_IRUGO, show_product_id, NULL, PRODUCT_ID); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); + +static struct attribute *as4610_54_cpld_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + &sensor_dev_attr_product_id.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_SFP_TRANSCEIVER_ATTR(1), + DECLARE_SFP_TRANSCEIVER_ATTR(2), + DECLARE_SFP_TRANSCEIVER_ATTR(3), + DECLARE_SFP_TRANSCEIVER_ATTR(4), + NULL +}; + +static const struct attribute_group as4610_54_cpld_group = { + .attrs = as4610_54_cpld_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status, present = 0; + u8 regs[] = {0x2, 0x3, 0x21}; + struct i2c_client *client = to_i2c_client(dev); + struct as4610_54_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as4610_54_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + switch (i) { + case 0: + present |= (status & BIT(6)) >> 6; /* port 25/49 */ + present |= (status & BIT(2)) >> 1; /* port 26/50 */ + break; + case 1: + present |= (status & BIT(6)) >> 4; /* port 27/51 */ + present |= (status & BIT(2)) << 1; /* port 28/52 */ + break; + case 2: + present |= (status & BIT(0)) << 4; /* port 29/53 */ + present |= (status & BIT(4)) << 1; /* port 30/54 */ + break; + default: + break; + } + } + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%.2x\n", present); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status, rx_los = 0; + u8 regs[] = {0x2, 0x3}; + struct i2c_client *client = to_i2c_client(dev); + struct as4610_54_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as4610_54_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + switch (i) { + case 0: + rx_los |= (status & BIT(4)) >> 4; /* port 25/49 rx_los */ + rx_los |= (status & BIT(0)) << 1; /* port 26/50 rx_los */ + break; + case 1: + rx_los |= (status & BIT(4)) >> 2; /* port 27/51 rx_los */ + rx_los |= (status & BIT(0)) << 3; /* port 28/52 rx_los */ + break; + default: + break; + } + } + + mutex_unlock(&data->update_lock); + + /* Return values 25/49 -> 28/52 in order */ + return sprintf(buf, "%.2x\n", rx_los); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as4610_54_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case MODULE_PRESENT_1: + reg = 0x2; + mask = 0x40; + break; + case MODULE_PRESENT_2: + reg = 0x2; + mask = 0x4; + break; + case MODULE_PRESENT_3: + reg = 0x3; + mask = 0x40; + break; + case MODULE_PRESENT_4: + reg = 0x3; + mask = 0x4; + break; + case MODULE_PRESENT_5: + reg = 0x21; + mask = 0x1; + break; + case MODULE_PRESENT_6: + reg = 0x21; + mask = 0x10; + break; + case MODULE_TXFAULT_1: + reg = 0x2; + mask = 0x20; + break; + case MODULE_TXFAULT_2: + reg = 0x2; + mask = 0x2; + break; + case MODULE_TXFAULT_3: + reg = 0x3; + mask = 0x20; + break; + case MODULE_TXFAULT_4: + reg = 0x3; + mask = 0x2; + break; + case MODULE_RXLOS_1: + reg = 0x2; + mask = 0x10; + break; + case MODULE_RXLOS_2: + reg = 0x2; + mask = 0x1; + break; + case MODULE_RXLOS_3: + reg = 0x3; + mask = 0x10; + break; + case MODULE_RXLOS_4: + reg = 0x3; + mask = 0x1; + break; + default: + return 0; + } + + mutex_lock(&data->update_lock); + status = as4610_54_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as4610_54_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = as4610_54_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as4610_54_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as4610_54_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_product_id(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", (val & 0xF)); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0xB); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0xB) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +/* I2C init/probing/exit functions */ +static int as4610_54_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as4610_54_cpld_data *data; + int ret = -ENODEV; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as4610_54_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + /* Bring QSFPs out of reset */ + as4610_54_cpld_write_internal(client, 0x2A, 0); + + ret = sysfs_create_group(&client->dev.kobj, &as4610_54_cpld_group); + if (ret) { + goto exit_free; + } + + as4610_54_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as4610_54_cpld_remove(struct i2c_client *client) +{ + struct as4610_54_cpld_data *data = i2c_get_clientdata(client); + + as4610_54_cpld_remove_client(client); + + /* Remove sysfs hooks */ + sysfs_remove_group(&client->dev.kobj, &as4610_54_cpld_group); + kfree(data); + + return 0; +} + +static int as4610_54_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as4610_54_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as4610_54_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as4610_54_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as4610_54_cpld_read); + +int as4610_54_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as4610_54_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as4610_54_cpld_write); + +int as4610_product_id(void) +{ + int pid = as4610_54_cpld_read(AS4610_CPLD_SLAVE_ADDR, AS4610_CPLD_PID_OFFSET); + pid &= 0xF; + + if (pid < PID_AS4610_30T || pid > PID_AS4610_54T_B || pid == PID_RESERVED) { + return PID_UNKNOWN; + } + + return pid; +} +EXPORT_SYMBOL(as4610_product_id); + +int as4610_is_poe_system(void) +{ + int pid = as4610_product_id(); + return (pid == PID_AS4610_30P || pid == PID_AS4610_54P); +} +EXPORT_SYMBOL(as4610_is_poe_system); + +static struct i2c_driver as4610_54_cpld_driver = { + .driver = { + .name = "as4610_54_cpld", + .owner = THIS_MODULE, + }, + .probe = as4610_54_cpld_probe, + .remove = as4610_54_cpld_remove, + .id_table = as4610_54_cpld_id, +}; + +static int __init as4610_54_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as4610_54_cpld_driver); +} + +static void __exit as4610_54_cpld_exit(void) +{ + i2c_del_driver(&as4610_54_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as4610_54_cpld_init); +module_exit(as4610_54_cpld_exit); + diff --git a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_fan.c b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_fan.c index e84bbaf5..ab69fb19 100644 --- a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_fan.c +++ b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_fan.c @@ -29,15 +29,16 @@ #include #include #include -#include "accton_i2c_cpld.h" #define DRVNAME "as4610_fan" - static struct as4610_fan_data *as4610_fan_update_device(struct device *dev); static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, const char *buf, size_t count); +extern int as4610_54_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as4610_54_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +extern int as4610_product_id(void); /* fan related data, the index should match sysfs_fan_attributes */ @@ -74,6 +75,16 @@ enum sysfs_fan_attributes { FAN2_FAULT }; +enum as4610_product_id_e { + PID_AS4610_30T, + PID_AS4610_30P, + PID_AS4610_54T, + PID_AS4610_54P, + PID_RESERVED, + PID_AS4610_54T_B, + PID_UNKNOWN +}; + /* Define attributes */ #define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ @@ -113,12 +124,12 @@ static struct attribute *as4610_fan_attributes[] = { static int as4610_fan_read_value(u8 reg) { - return accton_i2c_cpld_read(AS4610_CPLD_SLAVE_ADDR, reg); + return as4610_54_cpld_read(0x30, reg); } static int as4610_fan_write_value(u8 reg, u8 value) { - return accton_i2c_cpld_write(AS4610_CPLD_SLAVE_ADDR, reg, value); + return as4610_54_cpld_write(0x30, reg, value); } /* fan utility functions @@ -290,6 +301,27 @@ static struct platform_driver as4610_fan_driver = { }, }; +static int as4610_number_of_system_fan(void) +{ + int nFan = 0; + int pid = as4610_product_id(); + + switch (pid) { + case PID_AS4610_30P: + case PID_AS4610_54P: + nFan = 1; + break; + case PID_AS4610_54T_B: + nFan = 2; + break; + default: + nFan = 0; + break; + } + + return nFan; +} + static int __init as4610_fan_init(void) { int ret; @@ -342,3 +374,4 @@ module_exit(as4610_fan_exit); MODULE_AUTHOR("Brandon Chuang "); MODULE_DESCRIPTION("as4610_fan driver"); MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_leds.c b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_leds.c index cdc80779..5771b0a5 100644 --- a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_leds.c +++ b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_leds.c @@ -29,10 +29,10 @@ #include #include #include -#include "accton_i2c_cpld.h" -//extern void led_classdev_unregister(struct led_classdev *led_cdev); -//extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); +extern int as4610_54_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as4610_54_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +extern int as4610_product_id(void); #define DRVNAME "as4610_led" @@ -93,6 +93,16 @@ static const u8 led_reg[] = { 0x33, /* STK1-2/Fan/PoE/Alarm LED */ }; +enum as4610_product_id_e { + PID_AS4610_30T, + PID_AS4610_30P, + PID_AS4610_54T, + PID_AS4610_54P, + PID_RESERVED, + PID_AS4610_54T_B, + PID_UNKNOWN +}; + enum led_type { LED_TYPE_SYS, LED_TYPE_PRI, @@ -145,12 +155,12 @@ enum led_light_mode { static int as4610_led_read_value(u8 reg) { - return accton_i2c_cpld_read(0x30, reg); + return as4610_54_cpld_read(0x30, reg); } static int as4610_led_write_value(u8 reg, u8 value) { - return accton_i2c_cpld_write(0x30, reg, value); + return as4610_54_cpld_write(0x30, reg, value); } static void as4610_led_update(void) @@ -672,3 +682,4 @@ module_exit(as4610_led_exit); MODULE_AUTHOR("Brandon Chuang "); MODULE_DESCRIPTION("as4610_led driver"); MODULE_LICENSE("GPL"); + diff --git a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_psu.c b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_psu.c index 1f0d79dc..68f0348d 100644 --- a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_psu.c +++ b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_psu.c @@ -37,7 +37,7 @@ static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); static int as4610_psu_read_data(struct i2c_client *client, u8 command, u8 *data,int data_len); -extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as4610_54_cpld_read(unsigned short cpld_addr, u8 reg); /* Addresses scanned */ @@ -227,7 +227,7 @@ static struct as4610_psu_data *as4610_psu_update_device(struct device *dev) dev_dbg(&client->dev, "Starting as4610 update\n"); /* Read psu status */ - status = accton_i2c_cpld_read(0x30, 0x11); + status = as4610_54_cpld_read(0x30, 0x11); if (status < 0) { dev_dbg(&client->dev, "cpld reg 0x30 err %d\n", status); diff --git a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_sfp.c b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_sfp.c deleted file mode 100644 index 39c17ecf..00000000 --- a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_as4610_sfp.c +++ /dev/null @@ -1,1269 +0,0 @@ -/* - * SFP driver for accton as4610 sfp - * - * Copyright (C) Brandon Chuang - * - * Based on ad7414.c - * Copyright 2006 Stefan Roese , DENX Software Engineering - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "as4610_sfp" /* Platform dependent */ - -#define DEBUG_MODE 0 - -#if (DEBUG_MODE == 1) - #define DEBUG_PRINT(fmt, args...) \ - printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) -#else - #define DEBUG_PRINT(fmt, args...) -#endif - -#define NUM_OF_SFP_PORT 32 -#define EEPROM_NAME "sfp_eeprom" -#define EEPROM_SIZE 256 /* 256 byte eeprom */ -#define BIT_INDEX(i) (1ULL << (i)) -#define USE_I2C_BLOCK_READ 0 /* Platform dependent */ -#define I2C_RW_RETRY_COUNT 3 -#define I2C_RW_RETRY_INTERVAL 100 /* ms */ - -#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) -#define SFP_EEPROM_A2_I2C_ADDR (0xA2 >> 1) - -#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 -#define SFF8024_DEVICE_ID_SFP 0x3 -#define SFF8024_DEVICE_ID_QSFP 0xC -#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD -#define SFF8024_DEVICE_ID_QSFP28 0x11 - -#define SFF8472_DIAG_MON_TYPE_ADDR 92 -#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 -#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 -#define SFF8472_10G_BASE_MASK 0xF0 - -#define SFF8436_RX_LOS_ADDR 3 -#define SFF8436_TX_FAULT_ADDR 4 -#define SFF8436_TX_DISABLE_ADDR 86 - -static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t show_port_type(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; -static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); -static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); -extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); -extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); - -enum sfp_sysfs_attributes { - PRESENT, - PRESENT_ALL, - PORT_NUMBER, - PORT_TYPE, - DDM_IMPLEMENTED, - TX_FAULT, - TX_FAULT1, - TX_FAULT2, - TX_FAULT3, - TX_FAULT4, - TX_DISABLE, - TX_DISABLE1, - TX_DISABLE2, - TX_DISABLE3, - TX_DISABLE4, - RX_LOS, - RX_LOS1, - RX_LOS2, - RX_LOS3, - RX_LOS4, - RX_LOS_ALL -}; - -/* SFP/QSFP common attributes for sysfs */ -static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); -static SENSOR_DEVICE_ATTR(sfp_port_type, S_IRUGO, show_port_type, NULL, PORT_TYPE); -static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); -static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); -static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); -static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); -static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); - -/* QSFP attributes for sysfs */ -static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); -static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); -static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); -static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); -static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); -static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); -static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); -static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); -static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); -static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); -static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); -static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); -static struct attribute *qsfp_attributes[] = { - &sensor_dev_attr_sfp_port_number.dev_attr.attr, - &sensor_dev_attr_sfp_port_type.dev_attr.attr, - &sensor_dev_attr_sfp_is_present.dev_attr.attr, - &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, - NULL -}; - -/* SFP msa attributes for sysfs */ -static SENSOR_DEVICE_ATTR(sfp_ddm_implemented, S_IRUGO, sfp_show_ddm_implemented, NULL, DDM_IMPLEMENTED); -static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); -static struct attribute *sfp_msa_attributes[] = { - &sensor_dev_attr_sfp_port_number.dev_attr.attr, - &sensor_dev_attr_sfp_port_type.dev_attr.attr, - &sensor_dev_attr_sfp_is_present.dev_attr.attr, - &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, - &sensor_dev_attr_sfp_ddm_implemented.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, - NULL -}; - -/* SFP ddm attributes for sysfs */ -static struct attribute *sfp_ddm_attributes[] = { - NULL -}; - -/* Platform dependent +++ */ -enum port_numbers { -as4610_sfp1, /* Port 25 for as4610_30, Port 49 for as4610_54 */ -as4610_sfp2, /* Port 26 for as4610_30, Port 50 for as4610_54 */ -as4610_sfp3, /* Port 27 for as4610_30, Port 51 for as4610_54 */ -as4610_sfp4, /* Port 28 for as4610_30, Port 52 for as4610_54 */ -as4610_sfp5, /* Port 29 for as4610_30, Port 53 for as4610_54 */ -as4610_sfp6, /* Port 30 for as4610_30, Port 54 for as4610_54 */ -}; - -static const struct i2c_device_id sfp_device_id[] = { -{"as4610_sfp1", as4610_sfp1}, -{"as4610_sfp2", as4610_sfp2}, -{"as4610_sfp3", as4610_sfp3}, -{"as4610_sfp4", as4610_sfp4}, -{"as4610_sfp5", as4610_sfp5}, -{"as4610_sfp6", as4610_sfp6}, -{ /* LIST END */ } -}; -MODULE_DEVICE_TABLE(i2c, sfp_device_id); -/* Platform dependent --- */ - -/* - * list of valid port types - * note OOM_PORT_TYPE_NOT_PRESENT to indicate no - * module is present in this port - */ -typedef enum oom_driver_port_type_e { - OOM_DRIVER_PORT_TYPE_INVALID, - OOM_DRIVER_PORT_TYPE_NOT_PRESENT, - OOM_DRIVER_PORT_TYPE_SFP, - OOM_DRIVER_PORT_TYPE_SFP_PLUS, - OOM_DRIVER_PORT_TYPE_QSFP, - OOM_DRIVER_PORT_TYPE_QSFP_PLUS, - OOM_DRIVER_PORT_TYPE_QSFP28 -} oom_driver_port_type_t; - -enum driver_type_e { - DRIVER_TYPE_SFP_MSA, - DRIVER_TYPE_SFP_DDM, - DRIVER_TYPE_QSFP -}; - -/* Each client has this additional data - */ -struct eeprom_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - struct bin_attribute bin; /* eeprom data */ -}; - -struct sfp_msa_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u64 status[6]; /* bit0:port0, bit1:port1 and so on */ - /* index 0 => tx_fail - 1 => tx_disable - 2 => rx_loss - 3 => device id - 4 => 10G Ethernet Compliance Codes - to distinguish SFP or SFP+ - 5 => DIAGNOSTIC MONITORING TYPE */ - struct eeprom_data eeprom; -}; - -struct sfp_ddm_data { - struct eeprom_data eeprom; -}; - -struct qsfp_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u8 status[3]; /* bit0:port0, bit1:port1 and so on */ - /* index 0 => tx_fail - 1 => tx_disable - 2 => rx_loss */ - - u8 device_id; - struct eeprom_data eeprom; -}; - -struct sfp_port_data { - struct mutex update_lock; - enum driver_type_e driver_type; - int port; /* CPLD port index */ - oom_driver_port_type_t port_type; - u64 present; /* present status, bit0:port0, bit1:port1 and so on */ - - struct sfp_msa_data *msa; - struct sfp_ddm_data *ddm; - struct qsfp_data *qsfp; - - struct i2c_client *client; -}; - -static ssize_t show_port_number(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - return sprintf(buf, "sfp %d\n", data->port); -} - -/* Platform dependent +++ */ -static struct sfp_port_data *sfp_update_present(struct i2c_client *client) -{ - struct sfp_port_data *data = i2c_get_clientdata(client); - int i = 0; - int status = -1; - u8 regs[] = {0x2, 0x3, 0x21}; - - DEBUG_PRINT("Starting sfp present status update"); - mutex_lock(&data->update_lock); - - /* Read present status of port 49~54 */ - data->present = 0; - - for (i = 0; i < ARRAY_SIZE(regs); i++) { - status = accton_i2c_cpld_read(0x30, regs[i]); - - if (status < 0) { - DEBUG_PRINT("cpld(0x30) reg(0x%x) err %d", regs[i], status); - goto exit; - } - - DEBUG_PRINT("Present status = 0x%lx", data->present); - switch (i) { - case 0: - data->present |= (status & BIT_INDEX(6)) >> 6; /* port 25/49 */ - data->present |= (status & BIT_INDEX(2)) >> 1; /* port 26/50 */ - break; - case 1: - data->present |= (status & BIT_INDEX(6)) >> 4; /* port 27/51 */ - data->present |= (status & BIT_INDEX(2)) << 1; /* port 28/52 */ - break; - case 2: - data->present |= (status & BIT_INDEX(0)) << 4; /* port 29/53 */ - data->present |= (status & BIT_INDEX(4)) << 1; /* port 30/54 */ - break; - default: - break; - } - } - - DEBUG_PRINT("Present status = 0x%lx", data->present); -exit: - mutex_unlock(&data->update_lock); - return (status < 0) ? ERR_PTR(status) : data; -} - -static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - int i = 0; - int status = -1; - u8 regs[] = {0x2, 0x3, 0x21}; - - if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { - return data; - } - - DEBUG_PRINT("Starting as4610 sfp tx rx status update"); - mutex_lock(&data->update_lock); - data->msa->valid = 0; - memset(data->msa->status, 0, sizeof(data->msa->status)); - - /* Read status of port 49~52(SFP port) */ - for (i = 0; i < ARRAY_SIZE(regs); i++) { - status = accton_i2c_cpld_read(0x30, regs[i]); - - if (status < 0) { - DEBUG_PRINT("cpld(0x30) reg(0x%x) err %d", regs[i], status); - goto exit; - } - - DEBUG_PRINT("TX_FAULT = 0x%lx, TX_DISABLE = 0x%lx, TX_FAULT = 0x%lx", - data->msa->status[0], data->msa->status[1], data->msa->status[2]); - switch (i) { - case 0: - /* port 25/49 */ - data->msa->status[0] |= (status & BIT_INDEX(5)) >> 5; /* tx_fail */ - data->msa->status[2] |= (status & BIT_INDEX(4)) >> 4; /* rx_los */ - /* port 26/50 */ - data->msa->status[0] |= (status & BIT_INDEX(1)) << 0; /* tx_fail */ - data->msa->status[2] |= (status & BIT_INDEX(0)) << 1; /* rx_los */ - break; - case 1: - /* port 27/51 */ - data->msa->status[0] |= (status & BIT_INDEX(5)) >> 3; /* tx_fail */ - data->msa->status[2] |= (status & BIT_INDEX(4)) >> 2; /* rx_los */ - /* port 28/52 */ - data->msa->status[0] |= (status & BIT_INDEX(1)) << 1; /* tx_fail */ - data->msa->status[2] |= (status & BIT_INDEX(0)) << 2; /* rx_los */ - break; - default: - break; - } - } - - DEBUG_PRINT("TX_FAULT = 0x%lx, TX_DISABLE = 0x%lx, TX_FAULT = 0x%lx", - data->msa->status[0], data->msa->status[1], data->msa->status[2]); - data->msa->valid = 1; - data->msa->last_updated = jiffies; - -exit: - mutex_unlock(&data->update_lock); - return data; -} -/* Platform dependent --- */ - -static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - if (data->driver_type == DRIVER_TYPE_QSFP) { - return qsfp_set_tx_disable(dev, da, buf, count); - } - - return 0; -} - -static int sfp_is_port_present(struct i2c_client *client, int port) -{ - struct sfp_port_data *data = i2c_get_clientdata(client); - - data = sfp_update_present(client); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - return (data->present & BIT_INDEX(data->port)) ? 1 : 0; /* Platform dependent */ -} - -/* Platform dependent +++ */ -static ssize_t show_present(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - - if (PRESENT_ALL == attr->index) { - struct sfp_port_data *data = sfp_update_present(client); - - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - /* Return values 25/49 -> 30/54 in order */ - return sprintf(buf, "%.2x\n", (u8)(data->present)); - } - else { - struct sfp_port_data *data = i2c_get_clientdata(client); - int present = sfp_is_port_present(client, data->port); - - if (IS_ERR_VALUE(present)) { - return present; - } - - /* PRESENT */ - return sprintf(buf, "%d\n", present); - } -} -/* Platform dependent --- */ - -static struct sfp_port_data *sfp_update_port_type(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - u8 buf = 0; - int status; - - mutex_lock(&data->update_lock); - - switch (data->driver_type) { - case DRIVER_TYPE_SFP_MSA: - { - status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); - if (unlikely(status < 0)) { - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - if (buf != SFF8024_DEVICE_ID_SFP) { - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - status = sfp_eeprom_read(client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); - if (unlikely(status < 0)) { - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); - data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; - break; - } - case DRIVER_TYPE_QSFP: - { - status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); - if (unlikely(status < 0)) { - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); - switch (buf) { - case SFF8024_DEVICE_ID_QSFP: - data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; - break; - case SFF8024_DEVICE_ID_QSFP_PLUS: - data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; - break; - case SFF8024_DEVICE_ID_QSFP28: - data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; - break; - default: - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - break; - } - default: - break; - } - - mutex_unlock(&data->update_lock); - return data; -} - -static ssize_t show_port_type(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - int present = sfp_is_port_present(client, data->port); - - if (IS_ERR_VALUE(present)) { - return present; - } - - if (!present) { - return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); - } - - sfp_update_port_type(dev); - return sprintf(buf, "%d\n", data->port_type); -} - -static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - int i, status = -1; - u8 buf = 0; - u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; - - if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { - return data; - } - - DEBUG_PRINT("Starting sfp tx rx status update"); - mutex_lock(&data->update_lock); - data->qsfp->valid = 0; - memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); - - /* Notify device to update tx fault/ tx disable/ rx los status */ - for (i = 0; i < ARRAY_SIZE(reg); i++) { - status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); - if (unlikely(status < 0)) { - goto exit; - } - } - msleep(200); - - /* Read actual tx fault/ tx disable/ rx los status */ - for (i = 0; i < ARRAY_SIZE(reg); i++) { - status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); - if (unlikely(status < 0)) { - goto exit; - } - - DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); - data->qsfp->status[i] = (buf & 0xF); - } - - data->qsfp->valid = 1; - data->qsfp->last_updated = jiffies; - -exit: - mutex_unlock(&data->update_lock); - return (status < 0) ? ERR_PTR(status) : data; -} - -static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, - char *buf) -{ - int present; - u8 val = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - present = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENXIO; - } - - data = qsfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - switch (attr->index) { - case TX_FAULT: - val = !!(data->qsfp->status[2] & 0xF); - break; - case TX_FAULT1: - case TX_FAULT2: - case TX_FAULT3: - case TX_FAULT4: - val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); - break; - case TX_DISABLE: - val = data->qsfp->status[1] & 0xF; - break; - case TX_DISABLE1: - case TX_DISABLE2: - case TX_DISABLE3: - case TX_DISABLE4: - val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); - break; - case RX_LOS: - val = !!(data->qsfp->status[0] & 0xF); - break; - case RX_LOS1: - case RX_LOS2: - case RX_LOS3: - case RX_LOS4: - val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); - break; - default: - break; - } - - return sprintf(buf, "%d\n", val); -} - -static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - long disable; - int status; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - status = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(status)) { - return status; - } - - if (!status) { - /* port is not present */ - return -ENXIO; - } - - status = kstrtol(buf, 10, &disable); - if (status) { - return status; - } - - data = qsfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - mutex_lock(&data->update_lock); - - if (attr->index == TX_DISABLE) { - data->qsfp->status[1] = disable & 0xF; - } - else {/* TX_DISABLE1 ~ TX_DISABLE4*/ - if (disable) { - data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); - } - else { - data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); - } - } - - DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); - status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); - if (unlikely(status < 0)) { - count = status; - } - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, - char *buf) -{ - int status; - char ddm; - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - status = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(status)) { - return status; - } - - if (status == 0) { - /* port is not present */ - return -ENODEV; - } - - status = sfp_eeprom_read(client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); - if (unlikely(status < 0)) { - return status; - } - - return sprintf(buf, "%d\n", !!(ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK)); -} - -/* Platform dependent +++ */ -static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, - char *buf) -{ - u8 val = 0, index = 0; - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - if (data->driver_type == DRIVER_TYPE_QSFP) { - return qsfp_show_tx_rx_status(dev, da, buf); - } - - data = sfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - if(attr->index == RX_LOS_ALL) { - /** Return values 25/49 -> 28/52 in order */ - return sprintf(buf, "%.2x\n", (u8)(data->msa->status[2])); - } - - switch (attr->index) { - case TX_FAULT: - index = 0; - break; - case TX_DISABLE: - index = 1; - break; - case RX_LOS: - index = 2; - break; - default: - return 0; - } - - val = (data->msa->status[index] & BIT_INDEX(data->port)) ? 1 : 0; - return sprintf(buf, "%d\n", val); -} -/* Platform dependent --- */ -static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, - int data_len) -{ -#if USE_I2C_BLOCK_READ - int status, retry = I2C_RW_RETRY_COUNT; - - if (data_len > I2C_SMBUS_BLOCK_MAX) { - data_len = I2C_SMBUS_BLOCK_MAX; - } - - while (retry) { - status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - return status; - } - - return data_len; -#else - int status, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_write_byte_data(client, command, *data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - return status; - } - - return 1; -#endif - - -} - -static ssize_t sfp_port_write(struct sfp_port_data *data, - const char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) { - return count; - } - - /* - * Write data to chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&data->update_lock); - - while (count) { - ssize_t status; - - status = sfp_eeprom_write(data->client, off, buf, count); - if (status <= 0) { - if (retval == 0) { - retval = status; - } - break; - } - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&data->update_lock); - return retval; -} - - -static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - int present; - struct sfp_port_data *data; - DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); - data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - - present = sfp_is_port_present(data->client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENODEV; - } - - return sfp_port_write(data, buf, off, count); -} - -static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, - int data_len) -{ -#if USE_I2C_BLOCK_READ - int status, retry = I2C_RW_RETRY_COUNT; - - if (data_len > I2C_SMBUS_BLOCK_MAX) { - data_len = I2C_SMBUS_BLOCK_MAX; - } - - while (retry) { - status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - goto abort; - } - if (unlikely(status != data_len)) { - status = -EIO; - goto abort; - } - - //result = data_len; - -abort: - return status; -#else - int status, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_read_byte_data(client, command); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); - goto abort; - } - - *data = (u8)status; - status = 1; - -abort: - return status; -#endif -} - -static ssize_t sfp_port_read(struct sfp_port_data *data, - char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) { - DEBUG_PRINT("Count = 0, return"); - return count; - } - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&data->update_lock); - - while (count) { - ssize_t status; - - status = sfp_eeprom_read(data->client, off, buf, count); - if (status <= 0) { - if (retval == 0) { - retval = status; - } - break; - } - - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&data->update_lock); - return retval; - -} - -static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - int present; - struct sfp_port_data *data; - DEBUG_PRINT("offset = (%d), count = (%d)", off, count); - data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - - present = sfp_is_port_present(data->client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENODEV; - } - - return sfp_port_read(data, buf, off, count); -} - -static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) -{ - int err; - - sysfs_bin_attr_init(eeprom); - eeprom->attr.name = EEPROM_NAME; - eeprom->attr.mode = S_IWUSR | S_IRUGO; - eeprom->read = sfp_bin_read; - eeprom->write = sfp_bin_write; - eeprom->size = EEPROM_SIZE; - - /* Create eeprom file */ - err = sysfs_create_bin_file(kobj, eeprom); - if (err) { - return err; - } - - return 0; -} - -static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) -{ - sysfs_remove_bin_file(kobj, eeprom); - return 0; -} - -static const struct attribute_group sfp_msa_group = { - .attrs = sfp_msa_attributes, -}; - -static int sfp_i2c_check_functionality(struct i2c_client *client) -{ -#if USE_I2C_BLOCK_READ - return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); -#else - return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); -#endif -} - -static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, - struct sfp_msa_data **data) -{ - int status; - struct sfp_msa_data *msa; - - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } - - msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); - if (!msa) { - status = -ENOMEM; - goto exit; - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); - if (status) { - goto exit_free; - } - - /* init eeprom */ - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); - if (status) { - goto exit_remove; - } - - *data = msa; - dev_info(&client->dev, "sfp msa '%s'\n", client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); -exit_free: - kfree(msa); -exit: - - return status; -} - -static const struct attribute_group sfp_ddm_group = { - .attrs = sfp_ddm_attributes, -}; - -static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, - struct sfp_ddm_data **data) -{ - int status; - struct sfp_ddm_data *ddm; - - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } - - ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); - if (!ddm) { - status = -ENOMEM; - goto exit; - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); - if (status) { - goto exit_free; - } - - /* init eeprom */ - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); - if (status) { - goto exit_remove; - } - - *data = ddm; - dev_info(&client->dev, "sfp ddm '%s'\n", client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); -exit_free: - kfree(ddm); -exit: - - return status; -} - -static const struct attribute_group qsfp_group = { - .attrs = qsfp_attributes, -}; - -static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, - struct qsfp_data **data) -{ - int status; - struct qsfp_data *qsfp; - - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } - - qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); - if (!qsfp) { - status = -ENOMEM; - goto exit; - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &qsfp_group); - if (status) { - goto exit_free; - } - - /* init eeprom */ - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); - if (status) { - goto exit_remove; - } - - *data = qsfp; - dev_info(&client->dev, "qsfp '%s'\n", client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &qsfp_group); -exit_free: - kfree(qsfp); -exit: - - return status; -} - -/* Platform dependent +++ */ -static int sfp_device_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - struct sfp_port_data *data = NULL; - - data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); - if (!data) { - return -ENOMEM; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - data->port = dev_id->driver_data; - data->client = client; - - if (client->addr != SFP_EEPROM_A0_I2C_ADDR && - client->addr != SFP_EEPROM_A2_I2C_ADDR ) { - return -ENODEV; - } - - if (dev_id->driver_data >= as4610_sfp1 && dev_id->driver_data <= as4610_sfp4) { - if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { - data->driver_type = DRIVER_TYPE_SFP_MSA; - return sfp_msa_probe(client, dev_id, &data->msa); - } - else if (client->addr == SFP_EEPROM_A2_I2C_ADDR) { - data->driver_type = DRIVER_TYPE_SFP_DDM; - return sfp_ddm_probe(client, dev_id, &data->ddm); - } - } - else if (dev_id->driver_data >= as4610_sfp5 && dev_id->driver_data <= as4610_sfp6) { - if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { - data->driver_type = DRIVER_TYPE_QSFP; - return qsfp_probe(client, dev_id, &data->qsfp); - } - } - - return -ENODEV; -} -/* Platform dependent --- */ - -static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) -{ - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); - sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); - kfree(data); - return 0; -} - -static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) -{ - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); - sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); - kfree(data); - return 0; -} - -static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) -{ - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); - sysfs_remove_group(&client->dev.kobj, &qsfp_group); - kfree(data); - return 0; -} - -static int sfp_device_remove(struct i2c_client *client) -{ - struct sfp_port_data *data = i2c_get_clientdata(client); - - switch (data->driver_type) { - case DRIVER_TYPE_SFP_MSA: - return sfp_msa_remove(client, data->msa); - case DRIVER_TYPE_SFP_DDM: - return sfp_ddm_remove(client, data->ddm); - case DRIVER_TYPE_QSFP: - return qfp_remove(client, data->qsfp); - } - - return 0; -} - -/* Addresses scanned - */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; - -static struct i2c_driver sfp_driver = { - .driver = { - .name = DRIVER_NAME, - }, - .probe = sfp_device_probe, - .remove = sfp_device_remove, - .id_table = sfp_device_id, - .address_list = normal_i2c, -}; - -static int __init sfp_init(void) -{ - return i2c_add_driver(&sfp_driver); -} - -static void __exit sfp_exit(void) -{ - i2c_del_driver(&sfp_driver); -} - -MODULE_AUTHOR("Brandon Chuang "); -MODULE_DESCRIPTION("accton as4610_sfp driver"); -MODULE_LICENSE("GPL"); - -late_initcall(sfp_init); -module_exit(sfp_exit); - diff --git a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_i2c_cpld.c b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_i2c_cpld.c deleted file mode 100644 index a7140def..00000000 --- a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_i2c_cpld.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * A hwmon driver for the accton_i2c_cpld - * - * Copyright (C) 2013 Accton Technology Corporation. - * Brandon Chuang - * - * Based on ad7414.c - * Copyright 2006 Stefan Roese , DENX Software Engineering - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include "accton_i2c_cpld.h" - -static LIST_HEAD(cpld_client_list); -static struct mutex list_lock; - -enum cpld_device_id { - as4610_30_cpld, - as4610_54_cpld -}; - -struct cpld_data { - enum cpld_device_id id; -}; - -struct cpld_client_node { - struct i2c_client *client; - struct list_head list; -}; - -/* Addresses scanned for accton_i2c_cpld - */ -static const unsigned short normal_i2c[] = { 0x31, 0x35, 0x60, 0x61, 0x62, I2C_CLIENT_END }; - -static u8 cpld_product_id_offset(enum cpld_device_id id) -{ - switch (id) { - case as4610_30_cpld: - case as4610_54_cpld: - return 0x1; - } - - return 0; -} - -static int cpld_has_product_id(const struct i2c_device_id *dev_id) -{ - return (dev_id->driver_data == as4610_30_cpld) || - (dev_id->driver_data == as4610_54_cpld); -} - -static ssize_t show_cpld_product_id(struct device *dev, struct device_attribute *attr, char *buf) -{ - int val = 0; - struct i2c_client *client = to_i2c_client(dev); - struct cpld_data *data = i2c_get_clientdata(client); - - val = i2c_smbus_read_byte_data(client, cpld_product_id_offset(data->id)); - if (val < 0) { - dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", client->addr, cpld_product_id_offset(data->id), val); - } - - return sprintf(buf, "%d\n", (val & 0xF)); -} - -static u8 cpld_version_offset(enum cpld_device_id id) -{ - switch (id) { - case as4610_30_cpld: - case as4610_54_cpld: - return 0xB; - } - - return 0; -} - -static ssize_t show_cpld_version(struct device *dev, struct device_attribute *attr, char *buf) -{ - int val = 0; - struct i2c_client *client = to_i2c_client(dev); - struct cpld_data *data = i2c_get_clientdata(client); - - val = i2c_smbus_read_byte_data(client, cpld_version_offset(data->id)); - if (val < 0) { - dev_dbg(&client->dev, "cpld(0x%x) reg(0xB) err %d\n", client->addr, val); - } - - return sprintf(buf, "%d\n", val); -} - -static void accton_i2c_cpld_add_client(struct i2c_client *client, enum cpld_device_id id) -{ - struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); - struct cpld_data *data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); - - if (!node) { - dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); - return; - } - - if (!data) { - dev_dbg(&client->dev, "Can't allocate cpld_client_data (0x%x)\n", client->addr); - return; - } - - data->id = id; - i2c_set_clientdata(client, data); - node->client = client; - - mutex_lock(&list_lock); - list_add(&node->list, &cpld_client_list); - mutex_unlock(&list_lock); -} - -static void accton_i2c_cpld_remove_client(struct i2c_client *client) -{ - struct list_head *list_node = NULL; - struct cpld_client_node *cpld_node = NULL; - int found = 0; - - mutex_lock(&list_lock); - - list_for_each(list_node, &cpld_client_list) - { - cpld_node = list_entry(list_node, struct cpld_client_node, list); - - if (cpld_node->client == client) { - found = 1; - break; - } - } - - if (found) { - list_del(list_node); - kfree(cpld_node); - } - - mutex_unlock(&list_lock); -} - -static struct device_attribute ver = __ATTR(version, 0600, show_cpld_version, NULL); -static struct device_attribute pid = __ATTR(product_id, 0600, show_cpld_product_id, NULL); - -static int accton_i2c_cpld_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - int status; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); - status = -EIO; - goto exit; - } - - status = sysfs_create_file(&client->dev.kobj, &ver.attr); - if (status) { - goto exit; - } - - if (cpld_has_product_id(dev_id)) { - status = sysfs_create_file(&client->dev.kobj, &pid.attr); - if (status) { - goto exit; - } - } - - dev_info(&client->dev, "chip found\n"); - accton_i2c_cpld_add_client(client, (enum cpld_device_id)dev_id->driver_data); - - return 0; - - exit: - return status; -} - -static int accton_i2c_cpld_remove(struct i2c_client *client) -{ - sysfs_remove_file(&client->dev.kobj, &ver.attr); - accton_i2c_cpld_remove_client(client); - - return 0; -} - -static const struct i2c_device_id accton_i2c_cpld_id[] = { - { "as4610_30_cpld", as4610_30_cpld }, - { "as4610_54_cpld", as4610_54_cpld }, - { /* LIST END */} -}; -MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_id); - -static struct i2c_driver accton_i2c_cpld_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "accton_i2c_cpld", - }, - .probe = accton_i2c_cpld_probe, - .remove = accton_i2c_cpld_remove, - .id_table = accton_i2c_cpld_id, - .address_list = normal_i2c, -}; - -int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg) -{ - struct list_head *list_node = NULL; - struct cpld_client_node *cpld_node = NULL; - int ret = -EPERM; - - mutex_lock(&list_lock); - - list_for_each(list_node, &cpld_client_list) - { - cpld_node = list_entry(list_node, struct cpld_client_node, list); - - if (cpld_node->client->addr == cpld_addr) { - ret = i2c_smbus_read_byte_data(cpld_node->client, reg); - break; - } - } - - mutex_unlock(&list_lock); - - return ret; -} -EXPORT_SYMBOL(accton_i2c_cpld_read); - -int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) -{ - struct list_head *list_node = NULL; - struct cpld_client_node *cpld_node = NULL; - int ret = -EIO; - - mutex_lock(&list_lock); - - list_for_each(list_node, &cpld_client_list) - { - cpld_node = list_entry(list_node, struct cpld_client_node, list); - - if (cpld_node->client->addr == cpld_addr) { - ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); - break; - } - } - - mutex_unlock(&list_lock); - - return ret; -} -EXPORT_SYMBOL(accton_i2c_cpld_write); - -static int __init accton_i2c_cpld_init(void) -{ - mutex_init(&list_lock); - return i2c_add_driver(&accton_i2c_cpld_driver); -} - -static void __exit accton_i2c_cpld_exit(void) -{ - i2c_del_driver(&accton_i2c_cpld_driver); -} - -MODULE_AUTHOR("Brandon Chuang "); -MODULE_DESCRIPTION("accton_i2c_cpld driver"); -MODULE_LICENSE("GPL"); - -module_init(accton_i2c_cpld_init); -module_exit(accton_i2c_cpld_exit); diff --git a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_i2c_cpld.h b/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_i2c_cpld.h deleted file mode 100644 index 9b75abd9..00000000 --- a/packages/platforms/accton/armxx/arm-accton-as4610/modules/accton_i2c_cpld.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * A hwmon driver for the accton_i2c_cpld - * - * Copyright (C) 2016 Accton Technology Corporation. - * Brandon Chuang - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); -extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); - -#define AS4610_CPLD_SLAVE_ADDR 0x30 -#define AS4610_CPLD_PID_OFFSET 0x01 /* Product ID offset */ - -enum as4610_product_id_e { - PID_AS4610_30T, - PID_AS4610_30P, - PID_AS4610_54T, - PID_AS4610_54P, - PID_RESERVED, - PID_AS4610_54T_B, - PID_UNKNOWN -}; - -static inline int as4610_product_id(void) -{ - int pid = accton_i2c_cpld_read(AS4610_CPLD_SLAVE_ADDR, AS4610_CPLD_PID_OFFSET); - pid &= 0xF; - - if (pid < PID_AS4610_30T || pid > PID_AS4610_54T_B || pid == PID_RESERVED) { - return PID_UNKNOWN; - } - - return pid; -} - -static inline int as4610_is_poe_system(void) -{ - int pid = as4610_product_id(); - return (pid == PID_AS4610_30P || pid == PID_AS4610_54P); -} - -static inline int as4610_number_of_system_fan(void) -{ - int nFan = 0; - int pid = as4610_product_id(); - - switch (pid) { - case PID_AS4610_30P: - case PID_AS4610_54P: - nFan = 1; - break; - case PID_AS4610_54T_B: - nFan = 2; - break; - default: - nFan = 0; - break; - } - - return nFan; -} -