+/**
+ * s2io_mdio_write - Function to write in to MDIO registers
+ * @mmd_type : MMD type value (PMA/PMD/WIS/PCS/PHYXS)
+ * @addr : address value
+ * @value : data value
+ * @dev : pointer to net_device structure
+ * Description:
+ * This function is used to write values to the MDIO registers
+ * NONE
+ */
+static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value, struct net_device *dev)
+{
+ u64 val64 = 0x0;
+ nic_t *sp = dev->priv;
+ XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+
+ //address transaction
+ val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+ | MDIO_MMD_DEV_ADDR(mmd_type)
+ | MDIO_MMS_PRT_ADDR(0x0);
+ writeq(val64, &bar0->mdio_control);
+ val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+ writeq(val64, &bar0->mdio_control);
+ udelay(100);
+
+ //Data transaction
+ val64 = 0x0;
+ val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+ | MDIO_MMD_DEV_ADDR(mmd_type)
+ | MDIO_MMS_PRT_ADDR(0x0)
+ | MDIO_MDIO_DATA(value)
+ | MDIO_OP(MDIO_OP_WRITE_TRANS);
+ writeq(val64, &bar0->mdio_control);
+ val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+ writeq(val64, &bar0->mdio_control);
+ udelay(100);
+
+ val64 = 0x0;
+ val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+ | MDIO_MMD_DEV_ADDR(mmd_type)
+ | MDIO_MMS_PRT_ADDR(0x0)
+ | MDIO_OP(MDIO_OP_READ_TRANS);
+ writeq(val64, &bar0->mdio_control);
+ val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+ writeq(val64, &bar0->mdio_control);
+ udelay(100);
+
+}
+
+/**
+ * s2io_mdio_read - Function to write in to MDIO registers
+ * @mmd_type : MMD type value (PMA/PMD/WIS/PCS/PHYXS)
+ * @addr : address value
+ * @dev : pointer to net_device structure
+ * Description:
+ * This function is used to read values to the MDIO registers
+ * NONE
+ */
+static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev)
+{
+ u64 val64 = 0x0;
+ u64 rval64 = 0x0;
+ nic_t *sp = dev->priv;
+ XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+
+ /* address transaction */
+ val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+ | MDIO_MMD_DEV_ADDR(mmd_type)
+ | MDIO_MMS_PRT_ADDR(0x0);
+ writeq(val64, &bar0->mdio_control);
+ val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+ writeq(val64, &bar0->mdio_control);
+ udelay(100);
+
+ /* Data transaction */
+ val64 = 0x0;
+ val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+ | MDIO_MMD_DEV_ADDR(mmd_type)
+ | MDIO_MMS_PRT_ADDR(0x0)
+ | MDIO_OP(MDIO_OP_READ_TRANS);
+ writeq(val64, &bar0->mdio_control);
+ val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+ writeq(val64, &bar0->mdio_control);
+ udelay(100);
+
+ /* Read the value from regs */
+ rval64 = readq(&bar0->mdio_control);
+ rval64 = rval64 & 0xFFFF0000;
+ rval64 = rval64 >> 16;
+ return rval64;
+}
+/**
+ * s2io_chk_xpak_counter - Function to check the status of the xpak counters
+ * @counter : couter value to be updated
+ * @flag : flag to indicate the status
+ * @type : counter type
+ * Description:
+ * This function is to check the status of the xpak counters value
+ * NONE
+ */
+
+static void s2io_chk_xpak_counter(u64 *counter, u64 * regs_stat, u32 index, u16 flag, u16 type)
+{
+ u64 mask = 0x3;
+ u64 val64;
+ int i;
+ for(i = 0; i <index; i++)
+ mask = mask << 0x2;
+
+ if(flag > 0)
+ {
+ *counter = *counter + 1;
+ val64 = *regs_stat & mask;
+ val64 = val64 >> (index * 0x2);
+ val64 = val64 + 1;
+ if(val64 == 3)
+ {
+ switch(type)
+ {
+ case 1:
+ DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
+ "service. Excessive temperatures may "
+ "result in premature transceiver "
+ "failure \n");
+ break;
+ case 2:
+ DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
+ "service Excessive bias currents may "
+ "indicate imminent laser diode "
+ "failure \n");
+ break;
+ case 3:
+ DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
+ "service Excessive laser output "
+ "power may saturate far-end "
+ "receiver\n");
+ break;
+ default:
+ DBG_PRINT(ERR_DBG, "Incorrect XPAK Alarm "
+ "type \n");
+ }
+ val64 = 0x0;
+ }
+ val64 = val64 << (index * 0x2);
+ *regs_stat = (*regs_stat & (~mask)) | (val64);
+
+ } else {
+ *regs_stat = *regs_stat & (~mask);
+ }
+}
+
+/**
+ * s2io_updt_xpak_counter - Function to update the xpak counters
+ * @dev : pointer to net_device struct
+ * Description:
+ * This function is to upate the status of the xpak counters value
+ * NONE
+ */
+static void s2io_updt_xpak_counter(struct net_device *dev)
+{
+ u16 flag = 0x0;
+ u16 type = 0x0;
+ u16 val16 = 0x0;
+ u64 val64 = 0x0;
+ u64 addr = 0x0;
+
+ nic_t *sp = dev->priv;
+ StatInfo_t *stat_info = sp->mac_control.stats_info;
+
+ /* Check the communication with the MDIO slave */
+ addr = 0x0000;
+ val64 = 0x0;
+ val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+ if((val64 == 0xFFFF) || (val64 == 0x0000))
+ {
+ DBG_PRINT(ERR_DBG, "ERR: MDIO slave access failed - "
+ "Returned %llx\n", (unsigned long long)val64);
+ return;
+ }
+
+ /* Check for the expecte value of 2040 at PMA address 0x0000 */
+ if(val64 != 0x2040)
+ {
+ DBG_PRINT(ERR_DBG, "Incorrect value at PMA address 0x0000 - ");
+ DBG_PRINT(ERR_DBG, "Returned: %llx- Expected: 0x2040\n",
+ (unsigned long long)val64);
+ return;
+ }
+
+ /* Loading the DOM register to MDIO register */
+ addr = 0xA100;
+ s2io_mdio_write(MDIO_MMD_PMA_DEV_ADDR, addr, val16, dev);
+ val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+
+ /* Reading the Alarm flags */
+ addr = 0xA070;
+ val64 = 0x0;
+ val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+
+ flag = CHECKBIT(val64, 0x7);
+ type = 1;
+ s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_transceiver_temp_high,
+ &stat_info->xpak_stat.xpak_regs_stat,
+ 0x0, flag, type);
+
+ if(CHECKBIT(val64, 0x6))
+ stat_info->xpak_stat.alarm_transceiver_temp_low++;
+
+ flag = CHECKBIT(val64, 0x3);
+ type = 2;
+ s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_bias_current_high,
+ &stat_info->xpak_stat.xpak_regs_stat,
+ 0x2, flag, type);
+
+ if(CHECKBIT(val64, 0x2))
+ stat_info->xpak_stat.alarm_laser_bias_current_low++;
+
+ flag = CHECKBIT(val64, 0x1);
+ type = 3;
+ s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_output_power_high,
+ &stat_info->xpak_stat.xpak_regs_stat,
+ 0x4, flag, type);
+
+ if(CHECKBIT(val64, 0x0))
+ stat_info->xpak_stat.alarm_laser_output_power_low++;
+
+ /* Reading the Warning flags */
+ addr = 0xA074;
+ val64 = 0x0;
+ val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+
+ if(CHECKBIT(val64, 0x7))
+ stat_info->xpak_stat.warn_transceiver_temp_high++;
+
+ if(CHECKBIT(val64, 0x6))
+ stat_info->xpak_stat.warn_transceiver_temp_low++;
+
+ if(CHECKBIT(val64, 0x3))
+ stat_info->xpak_stat.warn_laser_bias_current_high++;
+
+ if(CHECKBIT(val64, 0x2))
+ stat_info->xpak_stat.warn_laser_bias_current_low++;
+
+ if(CHECKBIT(val64, 0x1))
+ stat_info->xpak_stat.warn_laser_output_power_high++;
+
+ if(CHECKBIT(val64, 0x0))
+ stat_info->xpak_stat.warn_laser_output_power_low++;
+}
+