diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-cpld.c b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-cpld.c index ad09168d..42a215d7 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-cpld.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-cpld.c @@ -32,31 +32,13 @@ #include #include #include -#include #include +#include +#include +#include -static struct dmi_system_id as5712_dmi_table[] = { - { - .ident = "Accton AS5712", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Accton"), - DMI_MATCH(DMI_PRODUCT_NAME, "AS5712"), - }, - }, - { - .ident = "Accton AS5712", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Accton"), - DMI_MATCH(DMI_PRODUCT_NAME, "AS5712"), - }, - }, -}; - -int platform_accton_as5712_54x(void) -{ - return dmi_check_system(as5712_dmi_table); -} -EXPORT_SYMBOL(platform_accton_as5712_54x); +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ #define NUM_OF_CPLD1_CHANS 0x0 #define NUM_OF_CPLD2_CHANS 0x18 @@ -64,10 +46,6 @@ EXPORT_SYMBOL(platform_accton_as5712_54x); #define CPLD_CHANNEL_SELECT_REG 0x2 #define CPLD_DESELECT_CHANNEL 0xFF -#if 0 -#define NUM_OF_ALL_CPLD_CHANS (NUM_OF_CPLD2_CHANS + NUM_OF_CPLD3_CHANS) -#endif - #define ACCTON_I2C_CPLD_MUX_MAX_NCHANS NUM_OF_CPLD3_CHANS static LIST_HEAD(cpld_client_list); @@ -84,19 +62,14 @@ enum cpld_mux_type { as5712_54x_cpld1 }; -struct accton_i2c_cpld_mux { +struct as5712_54x_cpld_data { enum cpld_mux_type type; struct i2c_adapter *virt_adaps[ACCTON_I2C_CPLD_MUX_MAX_NCHANS]; u8 last_chan; /* last register value */ -}; -#if 0 -/* The mapping table between mux index and adapter index - array index : the mux index - the content : adapter index - */ -static int mux_adap_map[NUM_OF_ALL_CPLD_CHANS]; -#endif + struct device *hwmon_dev; + struct mutex update_lock; +}; struct chip_desc { u8 nchans; @@ -119,45 +92,835 @@ static const struct chip_desc chips[] = { } }; -static const struct i2c_device_id accton_i2c_cpld_mux_id[] = { +static const struct i2c_device_id as5712_54x_cpld_mux_id[] = { { "as5712_54x_cpld1", as5712_54x_cpld1 }, { "as5712_54x_cpld2", as5712_54x_cpld2 }, { "as5712_54x_cpld3", as5712_54x_cpld3 }, { } }; -MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_mux_id); +MODULE_DEVICE_TABLE(i2c, as5712_54x_cpld_mux_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 as5712_54x_cpld1_sysfs_attributes { + CPLD_VERSION, + 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_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_PRESENT_ATTR_ID(35), + TRANSCEIVER_PRESENT_ATTR_ID(36), + TRANSCEIVER_PRESENT_ATTR_ID(37), + TRANSCEIVER_PRESENT_ATTR_ID(38), + TRANSCEIVER_PRESENT_ATTR_ID(39), + TRANSCEIVER_PRESENT_ATTR_ID(40), + TRANSCEIVER_PRESENT_ATTR_ID(41), + TRANSCEIVER_PRESENT_ATTR_ID(42), + TRANSCEIVER_PRESENT_ATTR_ID(43), + TRANSCEIVER_PRESENT_ATTR_ID(44), + TRANSCEIVER_PRESENT_ATTR_ID(45), + TRANSCEIVER_PRESENT_ATTR_ID(46), + TRANSCEIVER_PRESENT_ATTR_ID(47), + TRANSCEIVER_PRESENT_ATTR_ID(48), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_TXDISABLE_ATTR_ID(5), + TRANSCEIVER_TXDISABLE_ATTR_ID(6), + TRANSCEIVER_TXDISABLE_ATTR_ID(7), + TRANSCEIVER_TXDISABLE_ATTR_ID(8), + TRANSCEIVER_TXDISABLE_ATTR_ID(9), + TRANSCEIVER_TXDISABLE_ATTR_ID(10), + TRANSCEIVER_TXDISABLE_ATTR_ID(11), + TRANSCEIVER_TXDISABLE_ATTR_ID(12), + TRANSCEIVER_TXDISABLE_ATTR_ID(13), + TRANSCEIVER_TXDISABLE_ATTR_ID(14), + TRANSCEIVER_TXDISABLE_ATTR_ID(15), + TRANSCEIVER_TXDISABLE_ATTR_ID(16), + TRANSCEIVER_TXDISABLE_ATTR_ID(17), + TRANSCEIVER_TXDISABLE_ATTR_ID(18), + TRANSCEIVER_TXDISABLE_ATTR_ID(19), + TRANSCEIVER_TXDISABLE_ATTR_ID(20), + TRANSCEIVER_TXDISABLE_ATTR_ID(21), + TRANSCEIVER_TXDISABLE_ATTR_ID(22), + TRANSCEIVER_TXDISABLE_ATTR_ID(23), + TRANSCEIVER_TXDISABLE_ATTR_ID(24), + TRANSCEIVER_TXDISABLE_ATTR_ID(25), + TRANSCEIVER_TXDISABLE_ATTR_ID(26), + TRANSCEIVER_TXDISABLE_ATTR_ID(27), + TRANSCEIVER_TXDISABLE_ATTR_ID(28), + TRANSCEIVER_TXDISABLE_ATTR_ID(29), + TRANSCEIVER_TXDISABLE_ATTR_ID(30), + TRANSCEIVER_TXDISABLE_ATTR_ID(31), + TRANSCEIVER_TXDISABLE_ATTR_ID(32), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(35), + TRANSCEIVER_TXDISABLE_ATTR_ID(36), + TRANSCEIVER_TXDISABLE_ATTR_ID(37), + TRANSCEIVER_TXDISABLE_ATTR_ID(38), + TRANSCEIVER_TXDISABLE_ATTR_ID(39), + TRANSCEIVER_TXDISABLE_ATTR_ID(40), + TRANSCEIVER_TXDISABLE_ATTR_ID(41), + TRANSCEIVER_TXDISABLE_ATTR_ID(42), + TRANSCEIVER_TXDISABLE_ATTR_ID(43), + TRANSCEIVER_TXDISABLE_ATTR_ID(44), + TRANSCEIVER_TXDISABLE_ATTR_ID(45), + TRANSCEIVER_TXDISABLE_ATTR_ID(46), + TRANSCEIVER_TXDISABLE_ATTR_ID(47), + TRANSCEIVER_TXDISABLE_ATTR_ID(48), + TRANSCEIVER_RXLOS_ATTR_ID(1), + TRANSCEIVER_RXLOS_ATTR_ID(2), + TRANSCEIVER_RXLOS_ATTR_ID(3), + TRANSCEIVER_RXLOS_ATTR_ID(4), + TRANSCEIVER_RXLOS_ATTR_ID(5), + TRANSCEIVER_RXLOS_ATTR_ID(6), + TRANSCEIVER_RXLOS_ATTR_ID(7), + TRANSCEIVER_RXLOS_ATTR_ID(8), + TRANSCEIVER_RXLOS_ATTR_ID(9), + TRANSCEIVER_RXLOS_ATTR_ID(10), + TRANSCEIVER_RXLOS_ATTR_ID(11), + TRANSCEIVER_RXLOS_ATTR_ID(12), + TRANSCEIVER_RXLOS_ATTR_ID(13), + TRANSCEIVER_RXLOS_ATTR_ID(14), + TRANSCEIVER_RXLOS_ATTR_ID(15), + TRANSCEIVER_RXLOS_ATTR_ID(16), + TRANSCEIVER_RXLOS_ATTR_ID(17), + TRANSCEIVER_RXLOS_ATTR_ID(18), + TRANSCEIVER_RXLOS_ATTR_ID(19), + TRANSCEIVER_RXLOS_ATTR_ID(20), + TRANSCEIVER_RXLOS_ATTR_ID(21), + TRANSCEIVER_RXLOS_ATTR_ID(22), + TRANSCEIVER_RXLOS_ATTR_ID(23), + TRANSCEIVER_RXLOS_ATTR_ID(24), + TRANSCEIVER_RXLOS_ATTR_ID(25), + TRANSCEIVER_RXLOS_ATTR_ID(26), + TRANSCEIVER_RXLOS_ATTR_ID(27), + TRANSCEIVER_RXLOS_ATTR_ID(28), + TRANSCEIVER_RXLOS_ATTR_ID(29), + TRANSCEIVER_RXLOS_ATTR_ID(30), + TRANSCEIVER_RXLOS_ATTR_ID(31), + TRANSCEIVER_RXLOS_ATTR_ID(32), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(35), + TRANSCEIVER_RXLOS_ATTR_ID(36), + TRANSCEIVER_RXLOS_ATTR_ID(37), + TRANSCEIVER_RXLOS_ATTR_ID(38), + TRANSCEIVER_RXLOS_ATTR_ID(39), + TRANSCEIVER_RXLOS_ATTR_ID(40), + TRANSCEIVER_RXLOS_ATTR_ID(41), + TRANSCEIVER_RXLOS_ATTR_ID(42), + TRANSCEIVER_RXLOS_ATTR_ID(43), + TRANSCEIVER_RXLOS_ATTR_ID(44), + TRANSCEIVER_RXLOS_ATTR_ID(45), + TRANSCEIVER_RXLOS_ATTR_ID(46), + TRANSCEIVER_RXLOS_ATTR_ID(47), + TRANSCEIVER_RXLOS_ATTR_ID(48), + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(5), + TRANSCEIVER_TXFAULT_ATTR_ID(6), + TRANSCEIVER_TXFAULT_ATTR_ID(7), + TRANSCEIVER_TXFAULT_ATTR_ID(8), + TRANSCEIVER_TXFAULT_ATTR_ID(9), + TRANSCEIVER_TXFAULT_ATTR_ID(10), + TRANSCEIVER_TXFAULT_ATTR_ID(11), + TRANSCEIVER_TXFAULT_ATTR_ID(12), + TRANSCEIVER_TXFAULT_ATTR_ID(13), + TRANSCEIVER_TXFAULT_ATTR_ID(14), + TRANSCEIVER_TXFAULT_ATTR_ID(15), + TRANSCEIVER_TXFAULT_ATTR_ID(16), + TRANSCEIVER_TXFAULT_ATTR_ID(17), + TRANSCEIVER_TXFAULT_ATTR_ID(18), + TRANSCEIVER_TXFAULT_ATTR_ID(19), + TRANSCEIVER_TXFAULT_ATTR_ID(20), + TRANSCEIVER_TXFAULT_ATTR_ID(21), + TRANSCEIVER_TXFAULT_ATTR_ID(22), + TRANSCEIVER_TXFAULT_ATTR_ID(23), + TRANSCEIVER_TXFAULT_ATTR_ID(24), + TRANSCEIVER_TXFAULT_ATTR_ID(25), + TRANSCEIVER_TXFAULT_ATTR_ID(26), + TRANSCEIVER_TXFAULT_ATTR_ID(27), + TRANSCEIVER_TXFAULT_ATTR_ID(28), + TRANSCEIVER_TXFAULT_ATTR_ID(29), + TRANSCEIVER_TXFAULT_ATTR_ID(30), + TRANSCEIVER_TXFAULT_ATTR_ID(31), + TRANSCEIVER_TXFAULT_ATTR_ID(32), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(35), + TRANSCEIVER_TXFAULT_ATTR_ID(36), + TRANSCEIVER_TXFAULT_ATTR_ID(37), + TRANSCEIVER_TXFAULT_ATTR_ID(38), + TRANSCEIVER_TXFAULT_ATTR_ID(39), + TRANSCEIVER_TXFAULT_ATTR_ID(40), + TRANSCEIVER_TXFAULT_ATTR_ID(41), + TRANSCEIVER_TXFAULT_ATTR_ID(42), + TRANSCEIVER_TXFAULT_ATTR_ID(43), + TRANSCEIVER_TXFAULT_ATTR_ID(44), + TRANSCEIVER_TXFAULT_ATTR_ID(45), + TRANSCEIVER_TXFAULT_ATTR_ID(46), + TRANSCEIVER_TXFAULT_ATTR_ID(47), + TRANSCEIVER_TXFAULT_ATTR_ID(48), +}; + +/* 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 set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +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 int as5712_54x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as5712_54x_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_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##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_tx_disable_##index.dev_attr.attr, \ + &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); +/* 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_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(35); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(36); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(37); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(38); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(39); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(40); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(41); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(42); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(43); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(44); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(45); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(46); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(47); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(48); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54); + +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); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(35); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(36); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(37); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(38); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(39); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(40); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(41); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(42); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(43); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(44); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(45); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); + +static struct attribute *as5712_54x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5712_54x_cpld1_group = { + .attrs = as5712_54x_cpld1_attributes, +}; + +static struct attribute *as5712_54x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.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_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_SFP_TRANSCEIVER_ATTR(1), + DECLARE_SFP_TRANSCEIVER_ATTR(2), + DECLARE_SFP_TRANSCEIVER_ATTR(3), + DECLARE_SFP_TRANSCEIVER_ATTR(4), + DECLARE_SFP_TRANSCEIVER_ATTR(5), + DECLARE_SFP_TRANSCEIVER_ATTR(6), + DECLARE_SFP_TRANSCEIVER_ATTR(7), + DECLARE_SFP_TRANSCEIVER_ATTR(8), + DECLARE_SFP_TRANSCEIVER_ATTR(9), + DECLARE_SFP_TRANSCEIVER_ATTR(10), + DECLARE_SFP_TRANSCEIVER_ATTR(11), + DECLARE_SFP_TRANSCEIVER_ATTR(12), + DECLARE_SFP_TRANSCEIVER_ATTR(13), + DECLARE_SFP_TRANSCEIVER_ATTR(14), + DECLARE_SFP_TRANSCEIVER_ATTR(15), + DECLARE_SFP_TRANSCEIVER_ATTR(16), + DECLARE_SFP_TRANSCEIVER_ATTR(17), + DECLARE_SFP_TRANSCEIVER_ATTR(18), + DECLARE_SFP_TRANSCEIVER_ATTR(19), + DECLARE_SFP_TRANSCEIVER_ATTR(20), + DECLARE_SFP_TRANSCEIVER_ATTR(21), + DECLARE_SFP_TRANSCEIVER_ATTR(22), + DECLARE_SFP_TRANSCEIVER_ATTR(23), + DECLARE_SFP_TRANSCEIVER_ATTR(24), + NULL +}; + +static const struct attribute_group as5712_54x_cpld2_group = { + .attrs = as5712_54x_cpld2_attributes, +}; + +static struct attribute *as5712_54x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.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(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_TRANSCEIVER_PRESENT_ATTR(35), + DECLARE_TRANSCEIVER_PRESENT_ATTR(36), + DECLARE_TRANSCEIVER_PRESENT_ATTR(37), + DECLARE_TRANSCEIVER_PRESENT_ATTR(38), + DECLARE_TRANSCEIVER_PRESENT_ATTR(39), + DECLARE_TRANSCEIVER_PRESENT_ATTR(40), + DECLARE_TRANSCEIVER_PRESENT_ATTR(41), + DECLARE_TRANSCEIVER_PRESENT_ATTR(42), + DECLARE_TRANSCEIVER_PRESENT_ATTR(43), + DECLARE_TRANSCEIVER_PRESENT_ATTR(44), + DECLARE_TRANSCEIVER_PRESENT_ATTR(45), + DECLARE_TRANSCEIVER_PRESENT_ATTR(46), + DECLARE_TRANSCEIVER_PRESENT_ATTR(47), + DECLARE_TRANSCEIVER_PRESENT_ATTR(48), + DECLARE_TRANSCEIVER_PRESENT_ATTR(49), + DECLARE_TRANSCEIVER_PRESENT_ATTR(50), + DECLARE_TRANSCEIVER_PRESENT_ATTR(51), + DECLARE_TRANSCEIVER_PRESENT_ATTR(52), + DECLARE_TRANSCEIVER_PRESENT_ATTR(53), + DECLARE_TRANSCEIVER_PRESENT_ATTR(54), + DECLARE_SFP_TRANSCEIVER_ATTR(25), + DECLARE_SFP_TRANSCEIVER_ATTR(26), + DECLARE_SFP_TRANSCEIVER_ATTR(27), + DECLARE_SFP_TRANSCEIVER_ATTR(28), + DECLARE_SFP_TRANSCEIVER_ATTR(29), + DECLARE_SFP_TRANSCEIVER_ATTR(30), + DECLARE_SFP_TRANSCEIVER_ATTR(31), + DECLARE_SFP_TRANSCEIVER_ATTR(32), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(35), + DECLARE_SFP_TRANSCEIVER_ATTR(36), + DECLARE_SFP_TRANSCEIVER_ATTR(37), + DECLARE_SFP_TRANSCEIVER_ATTR(38), + DECLARE_SFP_TRANSCEIVER_ATTR(39), + DECLARE_SFP_TRANSCEIVER_ATTR(40), + DECLARE_SFP_TRANSCEIVER_ATTR(41), + DECLARE_SFP_TRANSCEIVER_ATTR(42), + DECLARE_SFP_TRANSCEIVER_ATTR(43), + DECLARE_SFP_TRANSCEIVER_ATTR(44), + DECLARE_SFP_TRANSCEIVER_ATTR(45), + DECLARE_SFP_TRANSCEIVER_ATTR(46), + DECLARE_SFP_TRANSCEIVER_ATTR(47), + DECLARE_SFP_TRANSCEIVER_ATTR(48), + NULL +}; + +static const struct attribute_group as5712_54x_cpld3_group = { + .attrs = as5712_54x_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status, num_regs = 0; + u8 values[4] = {0}; + u8 regs[] = {0x6, 0x7, 0x8, 0x14}; + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + num_regs = (data->type == as5712_54x_cpld2) ? 3 : 4; + + for (i = 0; i < num_regs; i++) { + status = as5712_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 54 in order */ + if (data->type == as5712_54x_cpld2) { + status = sprintf(buf, "%.2x %.2x %.2x\n", + values[0], values[1], values[2]); + } + else { /* as5712_54x_cpld3 */ + values[3] &= 0x3F; + status = sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3]); + } + + return status; + +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; + u8 values[3] = {0}; + u8 regs[] = {0xF, 0x10, 0x11}; + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as5712_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 24 in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", values[0], values[1], values[2]); + +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 as5712_54x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x8; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33 ... MODULE_PRESENT_40: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_PRESENT_33); + break; + case MODULE_PRESENT_41 ... MODULE_PRESENT_48: + reg = 0x8; + mask = 0x1 << (attr->index - MODULE_PRESENT_41); + break; + case MODULE_PRESENT_49: + reg = 0x14; + mask = 0x1; + break; + case MODULE_PRESENT_50: + reg = 0x14; + mask = 0x4; + break; + case MODULE_PRESENT_51: + reg = 0x14; + mask = 0x10; + break; + case MODULE_PRESENT_52: + reg = 0x14; + mask = 0x2; + break; + case MODULE_PRESENT_53: + reg = 0x14; + mask = 0x8; + break; + case MODULE_PRESENT_54: + reg = 0x14; + mask = 0x20; + break; + case MODULE_TXFAULT_1 ... MODULE_TXFAULT_8: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_TXFAULT_1); + break; + case MODULE_TXFAULT_9 ... MODULE_TXFAULT_16: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_TXFAULT_9); + break; + case MODULE_TXFAULT_17 ... MODULE_TXFAULT_24: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_TXFAULT_17); + break; + case MODULE_TXFAULT_25 ... MODULE_TXFAULT_32: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_TXFAULT_25); + break; + case MODULE_TXFAULT_33 ... MODULE_TXFAULT_40: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_TXFAULT_33); + break; + case MODULE_TXFAULT_41 ... MODULE_TXFAULT_48: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_TXFAULT_41); + break; + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + case MODULE_RXLOS_1 ... MODULE_RXLOS_8: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_RXLOS_1); + break; + case MODULE_RXLOS_9 ... MODULE_RXLOS_16: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_RXLOS_9); + break; + case MODULE_RXLOS_17 ... MODULE_RXLOS_24: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_RXLOS_17); + break; + case MODULE_RXLOS_25 ... MODULE_RXLOS_32: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_RXLOS_25); + break; + case MODULE_RXLOS_33 ... MODULE_RXLOS_40: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_RXLOS_33); + break; + case MODULE_RXLOS_41 ... MODULE_RXLOS_48: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_RXLOS_41); + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_54) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as5712_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as5712_54x_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as5712_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as5712_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +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 as5712_54x_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 = as5712_54x_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; +} /* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() for this as they will try to lock adapter a second time */ -static int accton_i2c_cpld_mux_reg_write(struct i2c_adapter *adap, +static int as5712_54x_cpld_mux_reg_write(struct i2c_adapter *adap, struct i2c_client *client, u8 val) { -#if 0 - int ret = -ENODEV; - - //if (adap->algo->master_xfer) { - if (0) - struct i2c_msg msg; - char buf[2]; - - msg.addr = client->addr; - msg.flags = 0; - msg.len = 2; - buf[0] = 0x2; - buf[1] = val; - msg.buf = buf; - ret = adap->algo->master_xfer(adap, &msg, 1); - } - else { - union i2c_smbus_data data; - ret = adap->algo->smbus_xfer(adap, client->addr, - client->flags, - I2C_SMBUS_WRITE, - 0x2, I2C_SMBUS_BYTE, &data); - } - - return ret; -#else unsigned long orig_jiffies; unsigned short flags; union i2c_smbus_data data; @@ -184,38 +947,37 @@ static int accton_i2c_cpld_mux_reg_write(struct i2c_adapter *adap, } return res; -#endif } -static int accton_i2c_cpld_mux_select_chan(struct i2c_adapter *adap, +static int as5712_54x_cpld_mux_select_chan(struct i2c_adapter *adap, void *client, u32 chan) { - struct accton_i2c_cpld_mux *data = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_get_clientdata(client); u8 regval; int ret = 0; regval = chan; /* Only select the channel if its different from the last channel */ if (data->last_chan != regval) { - ret = accton_i2c_cpld_mux_reg_write(adap, client, regval); + ret = as5712_54x_cpld_mux_reg_write(adap, client, regval); data->last_chan = regval; } return ret; } -static int accton_i2c_cpld_mux_deselect_mux(struct i2c_adapter *adap, +static int as5712_54x_cpld_mux_deselect_mux(struct i2c_adapter *adap, void *client, u32 chan) { - struct accton_i2c_cpld_mux *data = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_get_clientdata(client); /* Deselect active channel */ data->last_chan = chips[data->type].deselectChan; - return accton_i2c_cpld_mux_reg_write(adap, client, data->last_chan); + return as5712_54x_cpld_mux_reg_write(adap, client, data->last_chan); } -static void accton_i2c_cpld_add_client(struct i2c_client *client) +static void as5712_54x_cpld_add_client(struct i2c_client *client) { struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); @@ -231,7 +993,7 @@ static void accton_i2c_cpld_add_client(struct i2c_client *client) mutex_unlock(&list_lock); } -static void accton_i2c_cpld_remove_client(struct i2c_client *client) +static void as5712_54x_cpld_remove_client(struct i2c_client *client) { struct list_head *list_node = NULL; struct cpld_client_node *cpld_node = NULL; @@ -257,125 +1019,181 @@ static void accton_i2c_cpld_remove_client(struct i2c_client *client) mutex_unlock(&list_lock); } -static ssize_t show_cpld_version(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) { - u8 reg = 0x1; - struct i2c_client *client; - int len; + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); - client = to_i2c_client(dev); - len = sprintf(buf, "%d", i2c_smbus_read_byte_data(client, reg)); - - return len; + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); } -static struct device_attribute ver = __ATTR(version, 0600, show_cpld_version, NULL); - /* * I2C init/probing/exit functions */ -static int accton_i2c_cpld_mux_probe(struct i2c_client *client, +static int as5712_54x_cpld_mux_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); int chan=0; - struct accton_i2c_cpld_mux *data; + struct as5712_54x_cpld_data *data; int ret = -ENODEV; + const struct attribute_group *group = NULL; if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) - goto err; + goto exit; - data = kzalloc(sizeof(struct accton_i2c_cpld_mux), GFP_KERNEL); + data = kzalloc(sizeof(struct as5712_54x_cpld_data), GFP_KERNEL); if (!data) { ret = -ENOMEM; - goto err; + goto exit; } i2c_set_clientdata(client, data); - -#if 0 - /* Write the mux register at addr to verify - * that the mux is in fact present. - */ - if (i2c_smbus_write_byte(client, 0) < 0) { - dev_warn(&client->dev, "probe failed\n"); - goto exit_free; - } -#endif - + mutex_init(&data->update_lock); data->type = id->driver_data; if (data->type == as5712_54x_cpld2 || data->type == as5712_54x_cpld3) { data->last_chan = chips[data->type].deselectChan; /* force the first selection */ - /* Now create an adapter for each channel */ - for (chan = 0; chan < chips[data->type].nchans; chan++) { -#if 0 - int idx; -#endif - data->virt_adaps[chan] = i2c_add_mux_adapter(adap, &client->dev, client, 0, chan, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) - I2C_CLASS_HWMON | I2C_CLASS_SPD, -#endif - accton_i2c_cpld_mux_select_chan, - accton_i2c_cpld_mux_deselect_mux); + /* Now create an adapter for each channel */ + for (chan = 0; chan < chips[data->type].nchans; chan++) { + data->virt_adaps[chan] = i2c_add_mux_adapter(adap, &client->dev, client, 0, chan, 0, + as5712_54x_cpld_mux_select_chan, + as5712_54x_cpld_mux_deselect_mux); - if (data->virt_adaps[chan] == NULL) { - ret = -ENODEV; - dev_err(&client->dev, "failed to register multiplexed adapter %d\n", chan); - goto virt_reg_failed; + if (data->virt_adaps[chan] == NULL) { + ret = -ENODEV; + dev_err(&client->dev, "failed to register multiplexed adapter %d\n", chan); + goto exit_mux_register; + } } -#if 0 - idx = (data->type - as5712_54x_cpld2) * NUM_OF_CPLD2_CHANS + chan; - mux_adap_map[idx] = data->virt_adaps[chan]->nr; -#endif + dev_info(&client->dev, "registered %d multiplexed busses for I2C mux %s\n", + chan, client->name); } - dev_info(&client->dev, "registered %d multiplexed busses for I2C mux %s\n", - chan, client->name); + /* Register sysfs hooks */ + switch (data->type) { + case as5712_54x_cpld1: + group = &as5712_54x_cpld1_group; + break; + case as5712_54x_cpld2: + group = &as5712_54x_cpld2_group; + break; + case as5712_54x_cpld3: + group = &as5712_54x_cpld3_group; + + /* Bring QSFPs out of reset */ + as5712_54x_cpld_write_internal(client, 0x15, 0x3F); + break; + default: + break; } - accton_i2c_cpld_add_client(client); + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_mux_register; + } + } - ret = sysfs_create_file(&client->dev.kobj, &ver.attr); - if (ret) - goto virt_reg_failed; + as5712_54x_cpld_add_client(client); return 0; -virt_reg_failed: +exit_mux_register: for (chan--; chan >= 0; chan--) { i2c_del_mux_adapter(data->virt_adaps[chan]); } - - kfree(data); -err: + kfree(data); +exit: return ret; } -static int accton_i2c_cpld_mux_remove(struct i2c_client *client) +static int as5712_54x_cpld_mux_remove(struct i2c_client *client) { - struct accton_i2c_cpld_mux *data = i2c_get_clientdata(client); + struct as5712_54x_cpld_data *data = i2c_get_clientdata(client); const struct chip_desc *chip = &chips[data->type]; int chan; + const struct attribute_group *group = NULL; - sysfs_remove_file(&client->dev.kobj, &ver.attr); + as5712_54x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as5712_54x_cpld1: + group = &as5712_54x_cpld1_group; + break; + case as5712_54x_cpld2: + group = &as5712_54x_cpld2_group; + break; + case as5712_54x_cpld3: + group = &as5712_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } for (chan = 0; chan < chip->nchans; ++chan) { - if (data->virt_adaps[chan]) { - i2c_del_mux_adapter(data->virt_adaps[chan]); - data->virt_adaps[chan] = NULL; - } + if (data->virt_adaps[chan]) { + i2c_del_mux_adapter(data->virt_adaps[chan]); + data->virt_adaps[chan] = NULL; + } } kfree(data); - accton_i2c_cpld_remove_client(client); return 0; } -int as5712_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg) +static int as5712_54x_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 as5712_54x_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 as5712_54x_cpld_read(unsigned short cpld_addr, u8 reg) { struct list_head *list_node = NULL; struct cpld_client_node *cpld_node = NULL; @@ -385,21 +1203,21 @@ int as5712_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg) list_for_each(list_node, &cpld_client_list) { - cpld_node = list_entry(list_node, struct cpld_client_node, 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; - } + if (cpld_node->client->addr == cpld_addr) { + ret = as5712_54x_cpld_read_internal(cpld_node->client, reg); + break; + } } mutex_unlock(&list_lock); return ret; } -EXPORT_SYMBOL(as5712_54x_i2c_cpld_read); +EXPORT_SYMBOL(as5712_54x_cpld_read); -int as5712_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +int as5712_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) { struct list_head *list_node = NULL; struct cpld_client_node *cpld_node = NULL; @@ -409,60 +1227,45 @@ int as5712_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) list_for_each(list_node, &cpld_client_list) { - cpld_node = list_entry(list_node, struct cpld_client_node, 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; - } + if (cpld_node->client->addr == cpld_addr) { + ret = as5712_54x_cpld_write_internal(cpld_node->client, reg, value); + break; + } } mutex_unlock(&list_lock); return ret; } -EXPORT_SYMBOL(as5712_54x_i2c_cpld_write); +EXPORT_SYMBOL(as5712_54x_cpld_write); -#if 0 -int accton_i2c_cpld_mux_get_index(int adap_index) -{ - int i; - - for (i = 0; i < NUM_OF_ALL_CPLD_CHANS; i++) { - if (mux_adap_map[i] == adap_index) { - return i; - } - } - - return -EINVAL; -} -EXPORT_SYMBOL(accton_i2c_cpld_mux_get_index); -#endif - -static struct i2c_driver accton_i2c_cpld_mux_driver = { +static struct i2c_driver as5712_54x_cpld_mux_driver = { .driver = { .name = "as5712_54x_cpld", .owner = THIS_MODULE, }, - .probe = accton_i2c_cpld_mux_probe, - .remove = accton_i2c_cpld_mux_remove, - .id_table = accton_i2c_cpld_mux_id, + .probe = as5712_54x_cpld_mux_probe, + .remove = as5712_54x_cpld_mux_remove, + .id_table = as5712_54x_cpld_mux_id, }; -static int __init accton_i2c_cpld_mux_init(void) +static int __init as5712_54x_cpld_mux_init(void) { mutex_init(&list_lock); - return i2c_add_driver(&accton_i2c_cpld_mux_driver); + return i2c_add_driver(&as5712_54x_cpld_mux_driver); } -static void __exit accton_i2c_cpld_mux_exit(void) +static void __exit as5712_54x_cpld_mux_exit(void) { - i2c_del_driver(&accton_i2c_cpld_mux_driver); + i2c_del_driver(&as5712_54x_cpld_mux_driver); } MODULE_AUTHOR("Brandon Chuang "); MODULE_DESCRIPTION("Accton I2C CPLD mux driver"); MODULE_LICENSE("GPL"); -module_init(accton_i2c_cpld_mux_init); -module_exit(accton_i2c_cpld_mux_exit); +module_init(as5712_54x_cpld_mux_init); +module_exit(as5712_54x_cpld_mux_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-fan.c b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-fan.c index d6ffe7b6..db81a1a8 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-fan.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-fan.c @@ -131,8 +131,8 @@ static ssize_t fan_set_duty_cycle(struct device *dev, static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); -extern int as5712_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg); -extern int as5712_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +extern int as5712_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5712_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); /*******************/ @@ -258,12 +258,12 @@ static const struct attribute_group accton_as5712_54x_fan_group = { static int accton_as5712_54x_fan_read_value(u8 reg) { - return as5712_54x_i2c_cpld_read(0x60, reg); + return as5712_54x_cpld_read(0x60, reg); } static int accton_as5712_54x_fan_write_value(u8 reg, u8 value) { - return as5712_54x_i2c_cpld_write(0x60, reg, value); + return as5712_54x_cpld_write(0x60, reg, value); } static void accton_as5712_54x_fan_update_device(struct device *dev) @@ -394,11 +394,6 @@ static int __init accton_as5712_54x_fan_init(void) { int ret; - extern int platform_accton_as5712_54x(void); - if(!platform_accton_as5712_54x()) { - return -ENODEV; - } - ret = platform_driver_register(&accton_as5712_54x_fan_driver); if (ret < 0) { goto exit; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-leds.c b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-leds.c index cf8868e5..36704987 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-leds.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-leds.c @@ -29,8 +29,8 @@ #include #include -extern int as5712_54x_i2c_cpld_read (unsigned short cpld_addr, u8 reg); -extern int as5712_54x_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +extern int as5712_54x_cpld_read (unsigned short cpld_addr, u8 reg); +extern int as5712_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); extern void led_classdev_unregister(struct led_classdev *led_cdev); extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); @@ -220,12 +220,12 @@ static u8 led_light_mode_to_reg_val(enum led_type type, static int accton_as5712_54x_led_read_value(u8 reg) { - return as5712_54x_i2c_cpld_read(0x60, reg); + return as5712_54x_cpld_read(0x60, reg); } static int accton_as5712_54x_led_write_value(u8 reg, u8 value) { - return as5712_54x_i2c_cpld_write(0x60, reg, value); + return as5712_54x_cpld_write(0x60, reg, value); } static void accton_as5712_54x_led_update(void) @@ -552,10 +552,6 @@ static int __init accton_as5712_54x_led_init(void) { int ret; - extern int platform_accton_as5712_54x(void); - if(!platform_accton_as5712_54x()) { - return -ENODEV; - } ret = platform_driver_register(&accton_as5712_54x_led_driver); if (ret < 0) { goto exit; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-psu.c index 52269933..af0c0c01 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-psu.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-psu.c @@ -43,7 +43,7 @@ static ssize_t show_index(struct device *dev, struct device_attribute *da, char 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 as5712_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); -extern int as5712_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5712_54x_cpld_read(unsigned short cpld_addr, u8 reg); static int as5712_54x_psu_model_name_get(struct device *dev); /* Addresses scanned @@ -329,7 +329,7 @@ static struct as5712_54x_psu_data *as5712_54x_psu_update_device(struct device *d /* Read psu status */ - status = as5712_54x_i2c_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); + status = as5712_54x_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET); if (status < 0) { dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status); @@ -349,24 +349,9 @@ exit: return data; } -static int __init as5712_54x_psu_init(void) -{ - extern int platform_accton_as5712_54x(void); - if(!platform_accton_as5712_54x()) { - return -ENODEV; - } - return i2c_add_driver(&as5712_54x_psu_driver); -} - -static void __exit as5712_54x_psu_exit(void) -{ - i2c_del_driver(&as5712_54x_psu_driver); -} +module_i2c_driver(as5712_54x_psu_driver); MODULE_AUTHOR("Brandon Chuang "); MODULE_DESCRIPTION("accton as5712_54x_psu driver"); MODULE_LICENSE("GPL"); -module_init(as5712_54x_psu_init); -module_exit(as5712_54x_psu_exit); - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-sfp.c deleted file mode 100644 index 8202b39e..00000000 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/modules/builds/x86-64-accton-as5712-54x-sfp.c +++ /dev/null @@ -1,1882 +0,0 @@ -/* - * SFP driver for accton as5712_54x 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 "as5712_54x_sfp" - -#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 54 -#define EEPROM_NAME "sfp_eeprom" -#define EEPROM_SIZE 256 /* 256 byte eeprom */ -#define BIT_INDEX(i) (1ULL << (i)) -#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ -#define I2C_RW_RETRY_COUNT 10 -#define I2C_RW_RETRY_INTERVAL 60 /* ms */ - -#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 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 SFF8436_RX_LOS_ADDR 3 -#define SFF8436_TX_FAULT_ADDR 4 -#define SFF8436_TX_DISABLE_ADDR 86 - -#define MULTIPAGE_SUPPORT 1 - -#if (MULTIPAGE_SUPPORT == 1) -/* fundamental unit of addressing for SFF_8472/SFF_8436 */ -#define SFF_8436_PAGE_SIZE 128 -/* - * The current 8436 (QSFP) spec provides for only 4 supported - * pages (pages 0-3). - * This driver is prepared to support more, but needs a register in the - * EEPROM to indicate how many pages are supported before it is safe - * to implement more pages in the driver. - */ -#define SFF_8436_SPECED_PAGES 4 -#define SFF_8436_EEPROM_SIZE ((1 + SFF_8436_SPECED_PAGES) * SFF_8436_PAGE_SIZE) -#define SFF_8436_EEPROM_UNPAGED_SIZE (2 * SFF_8436_PAGE_SIZE) -/* - * The current 8472 (SFP) spec provides for only 3 supported - * pages (pages 0-2). - * This driver is prepared to support more, but needs a register in the - * EEPROM to indicate how many pages are supported before it is safe - * to implement more pages in the driver. - */ -#define SFF_8472_SPECED_PAGES 3 -#define SFF_8472_EEPROM_SIZE ((3 + SFF_8472_SPECED_PAGES) * SFF_8436_PAGE_SIZE) -#define SFF_8472_EEPROM_UNPAGED_SIZE (4 * SFF_8436_PAGE_SIZE) - -/* a few constants to find our way around the EEPROM */ -#define SFF_8436_PAGE_SELECT_REG 0x7F -#define SFF_8436_PAGEABLE_REG 0x02 -#define SFF_8436_NOT_PAGEABLE (1<<2) -#define SFF_8472_PAGEABLE_REG 0x40 -#define SFF_8472_PAGEABLE (1<<4) - -/* - * This parameter is to help this driver avoid blocking other drivers out - * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C - * clock, one 256 byte read takes about 1/43 second which is excessive; - * but the 1/170 second it takes at 400 kHz may be quite reasonable; and - * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. - * - * This value is forced to be a power of two so that writes align on pages. - */ -static unsigned io_limit = SFF_8436_PAGE_SIZE; - -/* - * specs often allow 5 msec for a page write, sometimes 20 msec; - * it's important to recover from write timeouts. - */ -static unsigned write_timeout = 25; - -typedef enum qsfp_opcode { - QSFP_READ_OP = 0, - QSFP_WRITE_OP = 1 -} qsfp_opcode_e; -#endif - -static ssize_t show_port_number(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_eeprom_read(struct i2c_client *, u8, u8 *,int); -static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); -extern int as5712_54x_i2c_cpld_read(unsigned short cpld_addr, u8 reg); -extern int as5712_54x_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_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_loss, 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_is_present.dev_attr.attr, - &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, - &sensor_dev_attr_sfp_rx_loss.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_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_is_present.dev_attr.attr, - &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, - &sensor_dev_attr_sfp_rx_loss.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, - NULL -}; - -/* Platform dependent +++ */ -/* The table maps active port to cpld port. - * Array index 0 is for active port 1, - * index 1 for active port 2, and so on. - * The array content implies cpld port index. - */ -static const u8 cpld_to_front_port_table[] = -{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 52, 50, 53, 51, 54}; -#define CPLD_PORT_TO_FRONT_PORT(port) (cpld_to_front_port_table[port]) - -enum port_numbers { -as5712_54x_port1, as5712_54x_port2, as5712_54x_port3, as5712_54x_port4, -as5712_54x_port5, as5712_54x_port6, as5712_54x_port7, as5712_54x_port8, -as5712_54x_port9, as5712_54x_port10, as5712_54x_port11, as5712_54x_port12, -as5712_54x_port13, as5712_54x_port14, as5712_54x_port15, as5712_54x_port16, -as5712_54x_port17, as5712_54x_port18, as5712_54x_port19, as5712_54x_port20, -as5712_54x_port21, as5712_54x_port22, as5712_54x_port23, as5712_54x_port24, -as5712_54x_port25, as5712_54x_port26, as5712_54x_port27, as5712_54x_port28, -as5712_54x_port29, as5712_54x_port30, as5712_54x_port31, as5712_54x_port32, -as5712_54x_port33, as5712_54x_port34, as5712_54x_port35, as5712_54x_port36, -as5712_54x_port37, as5712_54x_port38, as5712_54x_port39, as5712_54x_port40, -as5712_54x_port41, as5712_54x_port42, as5712_54x_port43, as5712_54x_port44, -as5712_54x_port45, as5712_54x_port46, as5712_54x_port47, as5712_54x_port48, -as5712_54x_port49, as5712_54x_port52, as5712_54x_port50, as5712_54x_port53, -as5712_54x_port51, as5712_54x_port54 -}; - -#define I2C_DEV_ID(x) { #x, x} - -static const struct i2c_device_id sfp_device_id[] = { -I2C_DEV_ID(as5712_54x_port1), -I2C_DEV_ID(as5712_54x_port2), -I2C_DEV_ID(as5712_54x_port3), -I2C_DEV_ID(as5712_54x_port4), -I2C_DEV_ID(as5712_54x_port5), -I2C_DEV_ID(as5712_54x_port6), -I2C_DEV_ID(as5712_54x_port7), -I2C_DEV_ID(as5712_54x_port8), -I2C_DEV_ID(as5712_54x_port9), -I2C_DEV_ID(as5712_54x_port10), -I2C_DEV_ID(as5712_54x_port11), -I2C_DEV_ID(as5712_54x_port12), -I2C_DEV_ID(as5712_54x_port13), -I2C_DEV_ID(as5712_54x_port14), -I2C_DEV_ID(as5712_54x_port15), -I2C_DEV_ID(as5712_54x_port16), -I2C_DEV_ID(as5712_54x_port17), -I2C_DEV_ID(as5712_54x_port18), -I2C_DEV_ID(as5712_54x_port19), -I2C_DEV_ID(as5712_54x_port20), -I2C_DEV_ID(as5712_54x_port21), -I2C_DEV_ID(as5712_54x_port22), -I2C_DEV_ID(as5712_54x_port23), -I2C_DEV_ID(as5712_54x_port24), -I2C_DEV_ID(as5712_54x_port25), -I2C_DEV_ID(as5712_54x_port26), -I2C_DEV_ID(as5712_54x_port27), -I2C_DEV_ID(as5712_54x_port28), -I2C_DEV_ID(as5712_54x_port29), -I2C_DEV_ID(as5712_54x_port30), -I2C_DEV_ID(as5712_54x_port31), -I2C_DEV_ID(as5712_54x_port32), -I2C_DEV_ID(as5712_54x_port33), -I2C_DEV_ID(as5712_54x_port34), -I2C_DEV_ID(as5712_54x_port35), -I2C_DEV_ID(as5712_54x_port36), -I2C_DEV_ID(as5712_54x_port37), -I2C_DEV_ID(as5712_54x_port38), -I2C_DEV_ID(as5712_54x_port39), -I2C_DEV_ID(as5712_54x_port40), -I2C_DEV_ID(as5712_54x_port41), -I2C_DEV_ID(as5712_54x_port42), -I2C_DEV_ID(as5712_54x_port43), -I2C_DEV_ID(as5712_54x_port44), -I2C_DEV_ID(as5712_54x_port45), -I2C_DEV_ID(as5712_54x_port46), -I2C_DEV_ID(as5712_54x_port47), -I2C_DEV_ID(as5712_54x_port48), -I2C_DEV_ID(as5712_54x_port49), -I2C_DEV_ID(as5712_54x_port50), -I2C_DEV_ID(as5712_54x_port51), -I2C_DEV_ID(as5712_54x_port52), -I2C_DEV_ID(as5712_54x_port53), -I2C_DEV_ID(as5712_54x_port54), -{ /* LIST END */ } -}; -MODULE_DEVICE_TABLE(i2c, sfp_device_id); -/* Platform dependent --- */ - -enum driver_type_e { - DRIVER_TYPE_SFP_MSA, - 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; -#if (MULTIPAGE_SUPPORT == 1) - struct i2c_client *ddm_client; /* dummy client instance for 0xA2 */ -#endif -}; - -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 */ - u64 present; /* present status, bit0:port0, bit1:port1 and so on */ - - struct sfp_msa_data *msa; - struct qsfp_data *qsfp; - - struct i2c_client *client; -#if (MULTIPAGE_SUPPORT == 1) - int use_smbus; - u8 *writebuf; - unsigned write_max; -#endif -}; - -#if (MULTIPAGE_SUPPORT == 1) -static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, - char *buf, loff_t off, size_t len, qsfp_opcode_e opcode); -#endif -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, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); -} - -/* Platform dependent +++ */ -static struct sfp_port_data *sfp_update_present(struct i2c_client *client) -{ - int i = 0, j = 0, status = -1; - u8 reg; - unsigned short cpld_addr; - struct sfp_port_data *data = i2c_get_clientdata(client); - - DEBUG_PRINT("Starting sfp present status update"); - mutex_lock(&data->update_lock); - data->present = 0; - - /* Read present status of port 1~48(SFP port) */ - for (i = 0; i < 2; i++) { - for (j = 0; j < 3; j++) { - cpld_addr = 0x61+i; - reg = 0x6+j; - status = as5712_54x_i2c_cpld_read(cpld_addr, reg); - - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); - goto exit; - } - - DEBUG_PRINT("Present status = 0x%lx\r\n", data->present); - data->present |= (u64)status << ((i*24) + (j%3)*8); - } - } - - /* Read present status of port 49-54(QSFP port) */ - cpld_addr = 0x62; - reg = 0x14; - status = as5712_54x_i2c_cpld_read(cpld_addr, reg); - - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); - goto exit; - } - else { - data->present |= (u64)status << 48; - } - - 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, j = 0; - int status = -1; - - if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { - return data; - } - - DEBUG_PRINT("Starting as5712_54x 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 1~48(SFP port) */ - for (i = 0; i < 2; i++) { - for (j = 0; j < 9; j++) { - u8 reg; - unsigned short cpld_addr; - reg = 0x9+j; - cpld_addr = 0x61+i; - - status = as5712_54x_i2c_cpld_read(cpld_addr, reg); - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); - goto exit; - } - - data->msa->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); - } - } - - data->msa->valid = 1; - data->msa->last_updated = jiffies; - -exit: - mutex_unlock(&data->update_lock); - return (status < 0) ? ERR_PTR(status) : data; -} - -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); - unsigned short cpld_addr = 0; - u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; - long disable; - int error; - - if (data->driver_type == DRIVER_TYPE_QSFP) { - return qsfp_set_tx_disable(dev, da, buf, count); - } - - error = kstrtol(buf, 10, &disable); - if (error) { - return error; - } - - mutex_lock(&data->update_lock); - - if(data->port < 24) { - cpld_addr = 0x61; - cpld_reg = 0xC + data->port / 8; - cpld_bit = 1 << (data->port % 8); - } - else { /* port 24 ~ 48 */ - cpld_addr = 0x62; - cpld_reg = 0xC + (data->port - 24) / 8; - cpld_bit = 1 << (data->port % 8); - } - - /* Read current status */ - cpld_val = as5712_54x_i2c_cpld_read(cpld_addr, cpld_reg); - - /* Update tx_disable status */ - if (disable) { - data->msa->status[1] |= BIT_INDEX(data->port); - cpld_val |= cpld_bit; - } - else { - data->msa->status[1] &= ~BIT_INDEX(data->port); - cpld_val &= ~cpld_bit; - } - - as5712_54x_i2c_cpld_write(cpld_addr, cpld_reg, cpld_val); - mutex_unlock(&data->update_lock); - return count; -} -/* Platform dependent --- */ - -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)) ? 0 : 1; /* 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) { - int i; - u8 values[7] = {0}; - struct sfp_port_data *data = sfp_update_present(client); - - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - for (i = 0; i < ARRAY_SIZE(values); i++) { - values[i] = ~(u8)(data->present >> (i * 8)); - } - - /* Return values 1 -> 54 in order */ - return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", - values[0], values[1], values[2], - values[3], values[4], values[5], - values[6] & 0x3F); - } - 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", present); - } -} -/* Platform dependent --- */ - -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) { - if (disable) { - data->qsfp->status[1] |= 0xF; - } - else { - data->qsfp->status[1] &= ~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; -} - -/* 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 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); - - 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) { - int i = 0; - u8 values[6] = {0}; - - for (i = 0; i < ARRAY_SIZE(values); i++) { - values[i] = (u8)(data->msa->status[2] >> (i * 8)); - } - - /** Return values 1 -> 48 in order */ - return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", - values[0], values[1], values[2], - values[3], values[4], values[5]); - } - - 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", 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 - - -} - -#if (MULTIPAGE_SUPPORT == 0) -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; -} -#endif - -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; - } - -#if (MULTIPAGE_SUPPORT == 1) - return sfp_port_read_write(data, buf, off, count, QSFP_WRITE_OP); -#else - return sfp_port_write(data, buf, off, count); -#endif -} - -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 -} - -#if (MULTIPAGE_SUPPORT == 1) -/*-------------------------------------------------------------------------*/ -/* - * This routine computes the addressing information to be used for - * a given r/w request. - * - * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), - * the page, and the offset. - * - * Handles both SFP and QSFP. - * For SFP, offset 0-255 are on client[0], >255 is on client[1] - * Offset 256-383 are on the lower half of client[1] - * Pages are accessible on the upper half of client[1]. - * Offset >383 are in 128 byte pages mapped into the upper half - * - * For QSFP, all offsets are on client[0] - * offset 0-127 are on the lower half of client[0] (no paging) - * Pages are accessible on the upper half of client[1]. - * Offset >127 are in 128 byte pages mapped into the upper half - * - * Callers must not read/write beyond the end of a client or a page - * without recomputing the client/page. Hence offset (within page) - * plus length must be less than or equal to 128. (Note that this - * routine does not have access to the length of the call, hence - * cannot do the validity check.) - * - * Offset within Lower Page 00h and Upper Page 00h are not recomputed - */ -static uint8_t sff_8436_translate_offset(struct sfp_port_data *port_data, - loff_t *offset, struct i2c_client **client) -{ - unsigned page = 0; - - *client = port_data->client; - - /* if SFP style, offset > 255, shift to i2c addr 0x51 */ - if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { - if (*offset > 255) { - /* like QSFP, but shifted to client[1] */ - *client = port_data->msa->ddm_client; - *offset -= 256; - } - } - - /* - * if offset is in the range 0-128... - * page doesn't matter (using lower half), return 0. - * offset is already correct (don't add 128 to get to paged area) - */ - if (*offset < SFF_8436_PAGE_SIZE) - return page; - - /* note, page will always be positive since *offset >= 128 */ - page = (*offset >> 7)-1; - /* 0x80 places the offset in the top half, offset is last 7 bits */ - *offset = SFF_8436_PAGE_SIZE + (*offset & 0x7f); - - return page; /* note also returning client and offset */ -} - -static ssize_t sff_8436_eeprom_read(struct sfp_port_data *port_data, - struct i2c_client *client, - char *buf, unsigned offset, size_t count) -{ - struct i2c_msg msg[2]; - u8 msgbuf[2]; - unsigned long timeout, read_time; - int status, i; - - memset(msg, 0, sizeof(msg)); - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /*smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* - * When we have a better choice than SMBus calls, use a - * combined I2C message. Write address; then read up to - * io_limit data bytes. msgbuf is u8 and will cast to our - * needs. - */ - i = 0; - msgbuf[i++] = offset; - - msg[0].addr = client->addr; - msg[0].buf = msgbuf; - msg[0].len = i; - - msg[1].addr = client->addr; - msg[1].flags = I2C_M_RD; - msg[1].buf = buf; - msg[1].len = count; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - read_time = jiffies; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_read_i2c_block_data(client, offset, - count, buf); - break; - case I2C_SMBUS_WORD_DATA: - status = i2c_smbus_read_word_data(client, offset); - if (status >= 0) { - buf[0] = status & 0xff; - if (count == 2) - buf[1] = status >> 8; - status = count; - } - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_read_byte_data(client, offset); - if (status >= 0) { - buf[0] = status; - status = count; - } - break; - default: - status = i2c_transfer(client->adapter, msg, 2); - if (status == 2) - status = count; - } - - dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", - count, offset, status, jiffies); - - if (status == count) /* happy path */ - return count; - - if (status == -ENXIO) /* no module present */ - return status; - - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); - } while (time_before(read_time, timeout)); - - return -ETIMEDOUT; -} - -static ssize_t sff_8436_eeprom_write(struct sfp_port_data *port_data, - struct i2c_client *client, - const char *buf, - unsigned offset, size_t count) -{ - struct i2c_msg msg; - ssize_t status; - unsigned long timeout, write_time; - unsigned next_page_start; - int i = 0; - - /* write max is at most a page - * (In this driver, write_max is actually one byte!) - */ - if (count > port_data->write_max) - count = port_data->write_max; - - /* shorten count if necessary to avoid crossing page boundary */ - next_page_start = roundup(offset + 1, SFF_8436_PAGE_SIZE); - if (offset + count > next_page_start) - count = next_page_start - offset; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /*smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* If we'll use I2C calls for I/O, set up the message */ - msg.addr = client->addr; - msg.flags = 0; - - /* msg.buf is u8 and casts will mask the values */ - msg.buf = port_data->writebuf; - - msg.buf[i++] = offset; - memcpy(&msg.buf[i], buf, count); - msg.len = i + count; - break; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - write_time = jiffies; - - switch (port_data->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_write_i2c_block_data(client, - offset, count, buf); - if (status == 0) - status = count; - break; - case I2C_SMBUS_WORD_DATA: - if (count == 2) { - status = i2c_smbus_write_word_data(client, - offset, (u16)((buf[0])|(buf[1] << 8))); - } else { - /* count = 1 */ - status = i2c_smbus_write_byte_data(client, - offset, buf[0]); - } - if (status == 0) - status = count; - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_write_byte_data(client, offset, - buf[0]); - if (status == 0) - status = count; - break; - default: - status = i2c_transfer(client->adapter, &msg, 1); - if (status == 1) - status = count; - break; - } - - dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", - count, offset, (long int) status, jiffies); - - if (status == count) - return count; - - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); - } while (time_before(write_time, timeout)); - - return -ETIMEDOUT; -} - - -static ssize_t sff_8436_eeprom_update_client(struct sfp_port_data *port_data, - char *buf, loff_t off, - size_t count, qsfp_opcode_e opcode) -{ - struct i2c_client *client; - ssize_t retval = 0; - u8 page = 0; - loff_t phy_offset = off; - int ret = 0; - - page = sff_8436_translate_offset(port_data, &phy_offset, &client); - - dev_dbg(&client->dev, - "sff_8436_eeprom_update_client off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", - off, page, phy_offset, (long int) count, opcode); - if (page > 0) { - ret = sff_8436_eeprom_write(port_data, client, &page, - SFF_8436_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_dbg(&client->dev, - "Write page register for page %d failed ret:%d!\n", - page, ret); - return ret; - } - } - - while (count) { - ssize_t status; - - if (opcode == QSFP_READ_OP) { - status = sff_8436_eeprom_read(port_data, client, - buf, phy_offset, count); - } else { - status = sff_8436_eeprom_write(port_data, client, - buf, phy_offset, count); - } - if (status <= 0) { - if (retval == 0) - retval = status; - break; - } - buf += status; - phy_offset += status; - count -= status; - retval += status; - } - - - if (page > 0) { - /* return the page register to page 0 (why?) */ - page = 0; - ret = sff_8436_eeprom_write(port_data, client, &page, - SFF_8436_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_err(&client->dev, - "Restore page register to page %d failed ret:%d!\n", - page, ret); - return ret; - } - } - return retval; -} - - -/* - * Figure out if this access is within the range of supported pages. - * Note this is called on every access because we don't know if the - * module has been replaced since the last call. - * If/when modules support more pages, this is the routine to update - * to validate and allow access to additional pages. - * - * Returns updated len for this access: - * - entire access is legal, original len is returned. - * - access begins legal but is too long, len is truncated to fit. - * - initial offset exceeds supported pages, return -EINVAL - */ -static ssize_t sff_8436_page_legal(struct sfp_port_data *port_data, - loff_t off, size_t len) -{ - struct i2c_client *client = port_data->client; - u8 regval; - int status; - size_t maxlen; - - if (off < 0) return -EINVAL; - if (port_data->driver_type == DRIVER_TYPE_SFP_MSA) { - /* SFP case */ - if ((off + len) <= 256) return len; - /* if no pages needed, we're good */ - //if ((off + len) <= SFF_8472_EEPROM_UNPAGED_SIZE) return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= SFF_8472_EEPROM_SIZE) return -EINVAL; - - /* Check if ddm is supported */ - status = sff_8436_eeprom_read(port_data, client, ®val, - SFF8472_DIAG_MON_TYPE_ADDR, 1); - if (status < 0) return status; /* error out (no module?) */ - if (!(regval & SFF8472_DIAG_MON_TYPE_DDM_MASK)) { - if (off >= 256) return -EINVAL; - maxlen = 256 - off; - } - else { - /* in between, are pages supported? */ - status = sff_8436_eeprom_read(port_data, client, ®val, - SFF_8472_PAGEABLE_REG, 1); - if (status < 0) return status; /* error out (no module?) */ - if (regval & SFF_8472_PAGEABLE) { - /* Pages supported, trim len to the end of pages */ - maxlen = SFF_8472_EEPROM_SIZE - off; - } else { - /* pages not supported, trim len to unpaged size */ - if (off >= SFF_8472_EEPROM_UNPAGED_SIZE) return -EINVAL; - maxlen = SFF_8472_EEPROM_UNPAGED_SIZE - off; - } - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, SFP, off %lld len %ld\n", - off, (long int) len); - } - else if (port_data->driver_type == DRIVER_TYPE_QSFP) { - /* QSFP case */ - /* if no pages needed, we're good */ - if ((off + len) <= SFF_8436_EEPROM_UNPAGED_SIZE) return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= SFF_8436_EEPROM_SIZE) return -EINVAL; - /* in between, are pages supported? */ - status = sff_8436_eeprom_read(port_data, client, ®val, - SFF_8436_PAGEABLE_REG, 1); - if (status < 0) return status; /* error out (no module?) */ - if (regval & SFF_8436_NOT_PAGEABLE) { - /* pages not supported, trim len to unpaged size */ - if (off >= SFF_8436_EEPROM_UNPAGED_SIZE) return -EINVAL; - maxlen = SFF_8436_EEPROM_UNPAGED_SIZE - off; - } else { - /* Pages supported, trim len to the end of pages */ - maxlen = SFF_8436_EEPROM_SIZE - off; - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, QSFP, off %lld len %ld\n", - off, (long int) len); - } - else { - return -EINVAL; - } - return len; -} - - -static ssize_t sfp_port_read_write(struct sfp_port_data *port_data, - char *buf, loff_t off, size_t len, qsfp_opcode_e opcode) -{ - struct i2c_client *client = port_data->client; - int chunk; - int status = 0; - ssize_t retval; - size_t pending_len = 0, chunk_len = 0; - loff_t chunk_offset = 0, chunk_start_offset = 0; - - if (unlikely(!len)) - return len; - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&port_data->update_lock); - - /* - * Confirm this access fits within the device suppored addr range - */ - len = sff_8436_page_legal(port_data, off, len); - if (len < 0) { - status = len; - goto err; - } - - /* - * For each (128 byte) chunk involved in this request, issue a - * separate call to sff_eeprom_update_client(), to - * ensure that each access recalculates the client/page - * and writes the page register as needed. - * Note that chunk to page mapping is confusing, is different for - * QSFP and SFP, and never needs to be done. Don't try! - */ - pending_len = len; /* amount remaining to transfer */ - retval = 0; /* amount transferred */ - for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { - - /* - * Compute the offset and number of bytes to be read/write - * - * 1. start at offset 0 (within the chunk), and read/write - * the entire chunk - * 2. start at offset 0 (within the chunk) and read/write less - * than entire chunk - * 3. start at an offset not equal to 0 and read/write the rest - * of the chunk - * 4. start at an offset not equal to 0 and read/write less than - * (end of chunk - offset) - */ - chunk_start_offset = chunk * SFF_8436_PAGE_SIZE; - - if (chunk_start_offset < off) { - chunk_offset = off; - if ((off + pending_len) < (chunk_start_offset + - SFF_8436_PAGE_SIZE)) - chunk_len = pending_len; - else - chunk_len = (chunk+1)*SFF_8436_PAGE_SIZE - off;/*SFF_8436_PAGE_SIZE - off;*/ - } else { - chunk_offset = chunk_start_offset; - if (pending_len > SFF_8436_PAGE_SIZE) - chunk_len = SFF_8436_PAGE_SIZE; - else - chunk_len = pending_len; - } - - dev_dbg(&client->dev, - "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", - off, (long int) len, chunk_start_offset, chunk_offset, - (long int) chunk_len, (long int) pending_len); - - /* - * note: chunk_offset is from the start of the EEPROM, - * not the start of the chunk - */ - status = sff_8436_eeprom_update_client(port_data, buf, - chunk_offset, chunk_len, opcode); - if (status != chunk_len) { - /* This is another 'no device present' path */ - dev_dbg(&client->dev, - "sff_8436_update_client for chunk %d chunk_offset %lld chunk_len %ld failed %d!\n", - chunk, chunk_offset, (long int) chunk_len, status); - goto err; - } - buf += status; - pending_len -= status; - retval += status; - } - mutex_unlock(&port_data->update_lock); - - return retval; - -err: - mutex_unlock(&port_data->update_lock); - - return status; -} - -#else -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; - -} -#endif - -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; - } - -#if (MULTIPAGE_SUPPORT == 1) - return sfp_port_read_write(data, buf, off, count, QSFP_READ_OP); -#else - return sfp_port_read(data, buf, off, count); -#endif -} - -#if (MULTIPAGE_SUPPORT == 1) -static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom, size_t size) -#else -static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) -#endif -{ - 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; -#if (MULTIPAGE_SUPPORT == 1) - eeprom->size = size; -#else - eeprom->size = EEPROM_SIZE; -#endif - - /* 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; -} - - -#if (MULTIPAGE_SUPPORT == 0) -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 -} -#endif - -static const struct attribute_group sfp_msa_group = { - .attrs = sfp_msa_attributes, -}; - -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 (MULTIPAGE_SUPPORT == 0) - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } -#endif - - 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 */ -#if (MULTIPAGE_SUPPORT == 1) - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin, SFF_8436_EEPROM_SIZE); -#else - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); -#endif - if (status) { - goto exit_remove; - } - -#if (MULTIPAGE_SUPPORT == 1) - msa->ddm_client = i2c_new_dummy(client->adapter, client->addr + 1); - if (!msa->ddm_client) { - dev_err(&client->dev, "address 0x%02x unavailable\n", client->addr + 1); - status = -EADDRINUSE; - goto exit_eeprom; - } -#endif - - *data = msa; - dev_info(&client->dev, "sfp msa '%s'\n", client->name); - - return 0; - -exit_eeprom: - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &msa->eeprom.bin); -exit_remove: - sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); -exit_free: - kfree(msa); -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 (MULTIPAGE_SUPPORT == 0) - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } -#endif - - 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 */ -#if (MULTIPAGE_SUPPORT == 1) - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin, SFF_8436_EEPROM_SIZE); -#else - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); -#endif - if (status) { - goto exit_remove; - } - - /* Bring QSFPs out of reset */ - as5712_54x_i2c_cpld_write(0x62, 0x15, 0x3F); - - *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) -{ - int ret = 0; - struct sfp_port_data *data = NULL; - - if (client->addr != SFP_EEPROM_A0_I2C_ADDR) { - return -ENODEV; - } - - if (dev_id->driver_data < as5712_54x_port1 || dev_id->driver_data > as5712_54x_port54) { - return -ENXIO; - } - - data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); - if (!data) { - return -ENOMEM; - } - -#if (MULTIPAGE_SUPPORT == 1) - data->use_smbus = 0; - - /* Use I2C operations unless we're stuck with SMBus extensions. */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { - data->use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_WORD_DATA)) { - data->use_smbus = I2C_SMBUS_WORD_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE_DATA)) { - data->use_smbus = I2C_SMBUS_BYTE_DATA; - } else { - ret = -EPFNOSUPPORT; - goto exit_kfree; - } - } - - if (!data->use_smbus || - (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || - i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_WORD_DATA) || - i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { - /* - * NOTE: AN-2079 - * Finisar recommends that the host implement 1 byte writes - * only since this module only supports 32 byte page boundaries. - * 2 byte writes are acceptable for PE and Vout changes per - * Application Note AN-2071. - */ - unsigned write_max = 1; - - if (write_max > io_limit) - write_max = io_limit; - if (data->use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) - write_max = I2C_SMBUS_BLOCK_MAX; - data->write_max = write_max; - - /* buffer (data + address at the beginning) */ - data->writebuf = kmalloc(write_max + 2, GFP_KERNEL); - if (!data->writebuf) { - ret = -ENOMEM; - goto exit_kfree; - } - } else { - dev_warn(&client->dev, - "cannot write due to controller restrictions."); - } - - if (data->use_smbus == I2C_SMBUS_WORD_DATA || - data->use_smbus == I2C_SMBUS_BYTE_DATA) { - dev_notice(&client->dev, "Falling back to %s reads, " - "performance will suffer\n", data->use_smbus == - I2C_SMBUS_WORD_DATA ? "word" : "byte"); - } -#endif - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - data->port = dev_id->driver_data; - data->client = client; - - if (dev_id->driver_data >= as5712_54x_port1 && dev_id->driver_data <= as5712_54x_port48) { - data->driver_type = DRIVER_TYPE_SFP_MSA; - ret = sfp_msa_probe(client, dev_id, &data->msa); - } - else { /* as5712_54x_portsfp49 ~ as5712_54x_portsfp54 */ - data->driver_type = DRIVER_TYPE_QSFP; - ret = qsfp_probe(client, dev_id, &data->qsfp); - } - - if (ret < 0) { - goto exit_kfree_buf; - } - - - return ret; - -exit_kfree_buf: -#if (MULTIPAGE_SUPPORT == 1) - if (data->writebuf) kfree(data->writebuf); -#endif - -exit_kfree: - kfree(data); - return ret; -} -/* 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); -#if (MULTIPAGE_SUPPORT == 1) - i2c_unregister_device(data->ddm_client); -#endif - sysfs_remove_group(&client->dev.kobj, &sfp_msa_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) -{ - int ret = 0; - 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_QSFP: - return qfp_remove(client, data->qsfp); - } - -#if (MULTIPAGE_SUPPORT == 1) - if (data->writebuf) - kfree(data->writebuf); -#endif - kfree(data); - return ret; -} - -/* 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 as5712_54x_sfp driver"); -MODULE_LICENSE("GPL"); - -module_init(sfp_init); -module_exit(sfp_exit); - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/sfpi.c index 560f5762..c44d8a38 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/onlp/builds/src/module/src/sfpi.c @@ -24,20 +24,24 @@ * ***********************************************************/ #include - -#include /* For O_RDWR && open */ -#include -#include -#include -#include #include -#include "platform_lib.h" +#include +#include "x86_64_accton_as5712_54x_int.h" +#include "x86_64_accton_as5712_54x_log.h" -#define MAX_SFP_PATH 64 -static char sfp_node_path[MAX_SFP_PATH] = {0}; #define CPLD_MUX_BUS_START_INDEX 2 -static int front_port_to_cpld_mux_index(int port) +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/0-00%d/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/0-00%d/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/0-00%d/module_tx_fault_%d" +#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/0-00%d/module_tx_disable_%d" +#define MODULE_PRESENT_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/0-0061/module_present_all" +#define MODULE_PRESENT_ALL_ATTR_CPLD3 "/sys/bus/i2c/devices/0-0062/module_present_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/0-0061/module_rx_los_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD3 "/sys/bus/i2c/devices/0-0062/module_rx_los_all" + +static int front_port_bus_index(int port) { int rport = 0; @@ -63,38 +67,6 @@ static int front_port_to_cpld_mux_index(int port) return (rport + CPLD_MUX_BUS_START_INDEX); } -static int -as5712_54x_sfp_node_read_int(char *node_path, int *value, int data_len) -{ - int ret = 0; - char buf[8] = {0}; - *value = 0; - - ret = deviceNodeReadString(node_path, buf, sizeof(buf), data_len); - - if (ret == 0) { - *value = atoi(buf); - } - - return ret; -} - -static char* -as5712_54x_sfp_get_port_path_addr(int port, int addr, char *node_name) -{ - sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-00%d/%s", - front_port_to_cpld_mux_index(port), addr, - node_name); - return sfp_node_path; -} - -static char* -as5712_54x_sfp_get_port_path(int port, char *node_name) -{ - return as5712_54x_sfp_get_port_path_addr(port, 50, node_name); -} - - /************************************************************ * * SFPI Entry Points @@ -203,10 +175,10 @@ onlp_sfpi_is_present(int port) * Return < 0 if error. */ int present; - char* path = as5712_54x_sfp_get_port_path(port, "sfp_is_present"); - - if (as5712_54x_sfp_node_read_int(path, &present, 1) != 0) { - AIM_LOG_INFO("Unable to read present status from port(%d)\r\n", port); + int addr = (port < 24) ? 61 : 62; + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } @@ -217,29 +189,35 @@ int onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) { uint32_t bytes[7]; - char* path; FILE* fp; - path = as5712_54x_sfp_get_port_path(0, "sfp_is_present_all"); - fp = fopen(path, "r"); - + /* Read present status of port 0~23 */ + fp = fopen(MODULE_PRESENT_ALL_ATTR_CPLD2, "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 CPLD2."); return ONLP_STATUS_E_INTERNAL; } - int count = fscanf(fp, "%x %x %x %x %x %x %x", - bytes+0, - bytes+1, - bytes+2, - bytes+3, - bytes+4, - bytes+5, - bytes+6 - ); + + int count = fscanf(fp, "%x %x %x", bytes+0, bytes+1, bytes+2); fclose(fp); - if(count != AIM_ARRAYSIZE(bytes)) { + if(count != 3) { /* 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 CPLD2."); + return ONLP_STATUS_E_INTERNAL; + } + + /* Read present status of port 24~53 */ + fp = fopen(MODULE_PRESENT_ALL_ATTR_CPLD3, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD3."); + return ONLP_STATUS_E_INTERNAL; + } + + count = fscanf(fp, "%x %x %x %x", bytes+3, bytes+4, bytes+5, bytes+6); + fclose(fp); + if(count != 4) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD3."); return ONLP_STATUS_E_INTERNAL; } @@ -268,33 +246,39 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) int onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) { - uint32_t bytes[7]; - char* path; + uint32_t bytes[6]; + uint32_t *ptr = bytes; FILE* fp; - path = as5712_54x_sfp_get_port_path(0, "sfp_rx_los_all"); - fp = fopen(path, "r"); + /* Read present status of port 0~23 */ + int addr, i = 0; - if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file."); - return ONLP_STATUS_E_INTERNAL; - } - int count = fscanf(fp, "%x %x %x %x %x %x", - bytes+0, - bytes+1, - bytes+2, - bytes+3, - bytes+4, - bytes+5 - ); - fclose(fp); - if(count != 6) { - AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file."); - return ONLP_STATUS_E_INTERNAL; + for (addr = 61; addr <= 62; addr++) { + if (addr == 61) { + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD2, "r"); + } + else { + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD3, "r"); + } + + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD(0x%d)", addr); + return ONLP_STATUS_E_INTERNAL; + } + + int count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2); + fclose(fp); + if(count != 3) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields from the module_rx_los_all device file of CPLD(0x%d)", addr); + return ONLP_STATUS_E_INTERNAL; + } + + ptr += count; } /* Convert to 64 bit integer in port order */ - int i = 0; + i = 0; uint64_t rx_los_all = 0 ; for(i = 5; i >= 0; i--) { rx_los_all <<= 8; @@ -315,18 +299,22 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) int onlp_sfpi_eeprom_read(int port, uint8_t data[256]) { - char* path = as5712_54x_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) { - AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); + 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; } @@ -336,11 +324,26 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) int onlp_sfpi_dom_read(int port, uint8_t data[256]) { - char* path = as5712_54x_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; } @@ -350,28 +353,28 @@ onlp_sfpi_dom_read(int port, uint8_t data[256]) int onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) { - int bus = front_port_to_cpld_mux_index(port); + int bus = front_port_bus_index(port); return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE); } int onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) { - int bus = front_port_to_cpld_mux_index(port); + int bus = front_port_bus_index(port); return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); } int onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) { - int bus = front_port_to_cpld_mux_index(port); + int bus = front_port_bus_index(port); return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE); } int onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) { - int bus = front_port_to_cpld_mux_index(port); + int bus = front_port_bus_index(port); return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); } @@ -384,13 +387,13 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) return ONLP_STATUS_E_UNSUPPORTED; } + int addr = (port < 24) ? 61 : 62; + switch(control) { case ONLP_SFP_CONTROL_TX_DISABLE: { - char* path = as5712_54x_sfp_get_port_path(port, "sfp_tx_disable"); - - if (deviceNodeWriteInt(path, value, 0) != 0) { + if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -412,19 +415,18 @@ int onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { int rv; - char* path = NULL; if (port < 0 || port >= 48) { return ONLP_STATUS_E_UNSUPPORTED; } + int addr = (port < 24) ? 61 : 62; + switch(control) { case ONLP_SFP_CONTROL_RX_LOS: { - path = as5712_54x_sfp_get_port_path(port, "sfp_rx_loss"); - - if (as5712_54x_sfp_node_read_int(path, value, 1) != 0) { + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -436,9 +438,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_FAULT: { - path = as5712_54x_sfp_get_port_path(port, "sfp_tx_fault"); - - if (as5712_54x_sfp_node_read_int(path, value, 1) != 0) { + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -450,9 +450,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_DISABLE: { - path = as5712_54x_sfp_get_port_path(port, "sfp_tx_disable"); - - if (as5712_54x_sfp_node_read_int(path, value, 0) != 0) { + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/platform-config/r0/src/python/x86_64_accton_as5712_54x_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/platform-config/r0/src/python/x86_64_accton_as5712_54x_r0/__init__.py index 810419ce..48c9970e 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/platform-config/r0/src/python/x86_64_accton_as5712_54x_r0/__init__.py +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5712-54x/platform-config/r0/src/python/x86_64_accton_as5712_54x_r0/__init__.py @@ -9,9 +9,10 @@ class OnlPlatform_x86_64_accton_as5712_54x_r0(OnlPlatformAccton, SYS_OBJECT_ID=".5712.54" def baseconfig(self): + self.insmod('optoe') self.insmod('cpr_4011_4mxx') self.insmod("ym2651y") - for m in [ 'cpld', 'fan', 'psu', 'leds', 'sfp' ]: + for m in [ 'cpld', 'fan', 'psu', 'leds' ]: self.insmod("x86-64-accton-as5712-54x-%s.ko" % m) ########### initialize I2C bus 0 ########### @@ -25,15 +26,22 @@ class OnlPlatform_x86_64_accton_as5712_54x_r0(OnlPlatformAccton, ) # initialize SFP devices for port in range(1, 49): - self.new_i2c_device('as5712_54x_port%d' % port, 0x50, port+1) + self.new_i2c_device('optoe2', 0x50, port+1) + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port+1), shell=True) # Initialize QSFP devices - self.new_i2c_device('as5712_54x_port49', 0x50, 50) - self.new_i2c_device('as5712_54x_port52', 0x50, 51) - self.new_i2c_device('as5712_54x_port50', 0x50, 52) - self.new_i2c_device('as5712_54x_port53', 0x50, 53) - self.new_i2c_device('as5712_54x_port51', 0x50, 54) - self.new_i2c_device('as5712_54x_port54', 0x50, 55) + self.new_i2c_device('optoe1', 0x50, 50) + self.new_i2c_device('optoe1', 0x50, 51) + self.new_i2c_device('optoe1', 0x50, 52) + self.new_i2c_device('optoe1', 0x50, 53) + self.new_i2c_device('optoe1', 0x50, 54) + self.new_i2c_device('optoe1', 0x50, 55) + subprocess.call('echo port49 > /sys/bus/i2c/devices/50-0050/port_name', shell=True) + subprocess.call('echo port52 > /sys/bus/i2c/devices/51-0050/port_name', shell=True) + subprocess.call('echo port50 > /sys/bus/i2c/devices/52-0050/port_name', shell=True) + subprocess.call('echo port53 > /sys/bus/i2c/devices/53-0050/port_name', shell=True) + subprocess.call('echo port51 > /sys/bus/i2c/devices/54-0050/port_name', shell=True) + subprocess.call('echo port54 > /sys/bus/i2c/devices/55-0050/port_name', shell=True) ########### initialize I2C bus 1 ########### self.new_i2c_devices(