]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/sfc/falcon_boards.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / net / sfc / falcon_boards.c
index cfc6a5b5a4770a3e2c48446b7dc168dbba318ceb..2dd16f0b3ced007ff2aeb761373ce98d40c76af3 100644 (file)
@@ -13,8 +13,6 @@
 #include "phy.h"
 #include "efx.h"
 #include "nic.h"
-#include "regs.h"
-#include "io.h"
 #include "workarounds.h"
 
 /* Macros for unpacking the board revision */
 #define FALCON_BOARD_SFN4112F 0x52
 
 /* Board temperature is about 15°C above ambient when air flow is
- * limited. */
+ * limited.  The maximum acceptable ambient temperature varies
+ * depending on the PHY specifications but the critical temperature
+ * above which we should shut down to avoid damage is 80°C. */
 #define FALCON_BOARD_TEMP_BIAS 15
+#define FALCON_BOARD_TEMP_CRIT (80 + FALCON_BOARD_TEMP_BIAS)
 
 /* SFC4000 datasheet says: 'The maximum permitted junction temperature
  * is 125°C; the thermal design of the environment for the SFC4000
  * should aim to keep this well below 100°C.' */
+#define FALCON_JUNC_TEMP_MIN   0
 #define FALCON_JUNC_TEMP_MAX   90
+#define FALCON_JUNC_TEMP_CRIT  125
 
 /*****************************************************************************
  * Support for LM87 sensor chip used on several boards
  */
+#define LM87_REG_TEMP_HW_INT_LOCK      0x13
+#define LM87_REG_TEMP_HW_EXT_LOCK      0x14
+#define LM87_REG_TEMP_HW_INT           0x17
+#define LM87_REG_TEMP_HW_EXT           0x18
+#define LM87_REG_TEMP_EXT1             0x26
+#define LM87_REG_TEMP_INT              0x27
 #define LM87_REG_ALARMS1               0x41
 #define LM87_REG_ALARMS2               0x42
 #define LM87_IN_LIMITS(nr, _min, _max)                 \
 
 #if defined(CONFIG_SENSORS_LM87) || defined(CONFIG_SENSORS_LM87_MODULE)
 
+static int efx_poke_lm87(struct i2c_client *client, const u8 *reg_values)
+{
+       while (*reg_values) {
+               u8 reg = *reg_values++;
+               u8 value = *reg_values++;
+               int rc = i2c_smbus_write_byte_data(client, reg, value);
+               if (rc)
+                       return rc;
+       }
+       return 0;
+}
+
+static const u8 falcon_lm87_common_regs[] = {
+       LM87_REG_TEMP_HW_INT_LOCK, FALCON_BOARD_TEMP_CRIT,
+       LM87_REG_TEMP_HW_INT, FALCON_BOARD_TEMP_CRIT,
+       LM87_TEMP_EXT1_LIMITS(FALCON_JUNC_TEMP_MIN, FALCON_JUNC_TEMP_MAX),
+       LM87_REG_TEMP_HW_EXT_LOCK, FALCON_JUNC_TEMP_CRIT,
+       LM87_REG_TEMP_HW_EXT, FALCON_JUNC_TEMP_CRIT,
+       0
+};
+
 static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info,
                         const u8 *reg_values)
 {
@@ -67,13 +97,16 @@ static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info,
        if (!client)
                return -EIO;
 
-       while (*reg_values) {
-               u8 reg = *reg_values++;
-               u8 value = *reg_values++;
-               rc = i2c_smbus_write_byte_data(client, reg, value);
-               if (rc)
-                       goto err;
-       }
+       /* Read-to-clear alarm/interrupt status */
+       i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1);
+       i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2);
+
+       rc = efx_poke_lm87(client, reg_values);
+       if (rc)
+               goto err;
+       rc = efx_poke_lm87(client, falcon_lm87_common_regs);
+       if (rc)
+               goto err;
 
        board->hwmon_client = client;
        return 0;
@@ -91,36 +124,56 @@ static void efx_fini_lm87(struct efx_nic *efx)
 static int efx_check_lm87(struct efx_nic *efx, unsigned mask)
 {
        struct i2c_client *client = falcon_board(efx)->hwmon_client;
-       s32 alarms1, alarms2;
+       bool temp_crit, elec_fault, is_failure;
+       u16 alarms;
+       s32 reg;
 
        /* If link is up then do not monitor temperature */
        if (EFX_WORKAROUND_7884(efx) && efx->link_state.up)
                return 0;
 
-       alarms1 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1);
-       alarms2 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2);
-       if (alarms1 < 0)
-               return alarms1;
-       if (alarms2 < 0)
-               return alarms2;
-       alarms1 &= mask;
-       alarms2 &= mask >> 8;
-       if (alarms1 || alarms2) {
+       reg = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1);
+       if (reg < 0)
+               return reg;
+       alarms = reg;
+       reg = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2);
+       if (reg < 0)
+               return reg;
+       alarms |= reg << 8;
+       alarms &= mask;
+
+       temp_crit = false;
+       if (alarms & LM87_ALARM_TEMP_INT) {
+               reg = i2c_smbus_read_byte_data(client, LM87_REG_TEMP_INT);
+               if (reg < 0)
+                       return reg;
+               if (reg > FALCON_BOARD_TEMP_CRIT)
+                       temp_crit = true;
+       }
+       if (alarms & LM87_ALARM_TEMP_EXT1) {
+               reg = i2c_smbus_read_byte_data(client, LM87_REG_TEMP_EXT1);
+               if (reg < 0)
+                       return reg;
+               if (reg > FALCON_JUNC_TEMP_CRIT)
+                       temp_crit = true;
+       }
+       elec_fault = alarms & ~(LM87_ALARM_TEMP_INT | LM87_ALARM_TEMP_EXT1);
+       is_failure = temp_crit || elec_fault;
+
+       if (alarms)
                netif_err(efx, hw, efx->net_dev,
-                         "LM87 detected a hardware failure (status %02x:%02x)"
-                         "%s%s%s\n",
-                         alarms1, alarms2,
-                         (alarms1 & LM87_ALARM_TEMP_INT) ?
+                         "LM87 detected a hardware %s (status %02x:%02x)"
+                         "%s%s%s%s\n",
+                         is_failure ? "failure" : "problem",
+                         alarms & 0xff, alarms >> 8,
+                         (alarms & LM87_ALARM_TEMP_INT) ?
                          "; board is overheating" : "",
-                         (alarms1 & LM87_ALARM_TEMP_EXT1) ?
+                         (alarms & LM87_ALARM_TEMP_EXT1) ?
                          "; controller is overheating" : "",
-                         (alarms1 & ~(LM87_ALARM_TEMP_INT | LM87_ALARM_TEMP_EXT1)
-                          || alarms2) ?
-                         "; electrical fault" : "");
-               return -ERANGE;
-       }
+                         temp_crit ? "; reached critical temperature" : "",
+                         elec_fault ? "; electrical fault" : "");
 
-       return 0;
+       return is_failure ? -ERANGE : 0;
 }
 
 #else /* !CONFIG_SENSORS_LM87 */
@@ -325,7 +378,7 @@ static ssize_t set_phy_flash_cfg(struct device *dev,
                new_mode = old_mode & ~PHY_MODE_SPECIAL;
        else
                new_mode = PHY_MODE_SPECIAL;
-       if (old_mode == new_mode) {
+       if (!((old_mode ^ new_mode) & PHY_MODE_SPECIAL)) {
                err = 0;
        } else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) {
                err = -EBUSY;
@@ -362,10 +415,11 @@ static void sfe4001_fini(struct efx_nic *efx)
 
 static int sfe4001_check_hw(struct efx_nic *efx)
 {
+       struct falcon_nic_data *nic_data = efx->nic_data;
        s32 status;
 
        /* If XAUI link is up then do not monitor */
-       if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required)
+       if (EFX_WORKAROUND_7884(efx) && !nic_data->xmac_poll_required)
                return 0;
 
        /* Check the powered status of the PHY. Lack of power implies that