ASoC: tas6424: Add channel fault reporting
authorAndrew F. Davis <afd@ti.com>
Fri, 31 Aug 2018 15:14:07 +0000 (10:14 -0500)
committerMark Brown <broonie@kernel.org>
Fri, 31 Aug 2018 15:23:54 +0000 (16:23 +0100)
The TAS6426 has a register that reports channel faults such as
overcurrent and continuous DC output. Add reporting of this here.

Signed-off-by: Andrew F. Davis <afd@ti.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/tas6424.c
sound/soc/codecs/tas6424.h

index aac559fffc1a30f6a1a871fd4156c278a7adcd29..36aebdb8f55c5b9540f421235f0c37ef815fd213 100644 (file)
@@ -41,6 +41,7 @@ struct tas6424_data {
        struct regmap *regmap;
        struct regulator_bulk_data supplies[TAS6424_NUM_SUPPLIES];
        struct delayed_work fault_check_work;
+       unsigned int last_cfault;
        unsigned int last_fault1;
        unsigned int last_fault2;
        unsigned int last_warn;
@@ -406,6 +407,51 @@ static void tas6424_fault_check_work(struct work_struct *work)
        unsigned int reg;
        int ret;
 
+       ret = regmap_read(tas6424->regmap, TAS6424_CHANNEL_FAULT, &reg);
+       if (ret < 0) {
+               dev_err(dev, "failed to read CHANNEL_FAULT register: %d\n", ret);
+               goto out;
+       }
+
+       if (!reg) {
+               tas6424->last_cfault = reg;
+               goto check_global_fault1_reg;
+       }
+
+       /*
+        * Only flag errors once for a given occurrence. This is needed as
+        * the TAS6424 will take time clearing the fault condition internally
+        * during which we don't want to bombard the system with the same
+        * error message over and over.
+        */
+       if ((reg & TAS6424_FAULT_OC_CH1) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH1))
+               dev_crit(dev, "experienced a channel 1 overcurrent fault\n");
+
+       if ((reg & TAS6424_FAULT_OC_CH2) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH2))
+               dev_crit(dev, "experienced a channel 2 overcurrent fault\n");
+
+       if ((reg & TAS6424_FAULT_OC_CH3) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH3))
+               dev_crit(dev, "experienced a channel 3 overcurrent fault\n");
+
+       if ((reg & TAS6424_FAULT_OC_CH4) && !(tas6424->last_cfault & TAS6424_FAULT_OC_CH4))
+               dev_crit(dev, "experienced a channel 4 overcurrent fault\n");
+
+       if ((reg & TAS6424_FAULT_DC_CH1) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH1))
+               dev_crit(dev, "experienced a channel 1 DC fault\n");
+
+       if ((reg & TAS6424_FAULT_DC_CH2) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH2))
+               dev_crit(dev, "experienced a channel 2 DC fault\n");
+
+       if ((reg & TAS6424_FAULT_DC_CH3) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH3))
+               dev_crit(dev, "experienced a channel 3 DC fault\n");
+
+       if ((reg & TAS6424_FAULT_DC_CH4) && !(tas6424->last_cfault & TAS6424_FAULT_DC_CH4))
+               dev_crit(dev, "experienced a channel 4 DC fault\n");
+
+       /* Store current fault1 value so we can detect any changes next time */
+       tas6424->last_cfault = reg;
+
+check_global_fault1_reg:
        ret = regmap_read(tas6424->regmap, TAS6424_GLOB_FAULT1, &reg);
        if (ret < 0) {
                dev_err(dev, "failed to read GLOB_FAULT1 register: %d\n", ret);
@@ -429,12 +475,6 @@ static void tas6424_fault_check_work(struct work_struct *work)
                goto check_global_fault2_reg;
        }
 
-       /*
-        * Only flag errors once for a given occurrence. This is needed as
-        * the TAS6424 will take time clearing the fault condition internally
-        * during which we don't want to bombard the system with the same
-        * error message over and over.
-        */
        if ((reg & TAS6424_FAULT_PVDD_OV) && !(tas6424->last_fault1 & TAS6424_FAULT_PVDD_OV))
                dev_crit(dev, "experienced a PVDD overvoltage fault\n");
 
index b5958c45ed0ed07fb4cc723f4d6c8cec0ed468a0..c67a7835ca666ebf6b65609b0c8d7391aecc4850 100644 (file)
 #define TAS6424_LDGBYPASS_SHIFT                0
 #define TAS6424_LDGBYPASS_MASK         BIT(TAS6424_LDGBYPASS_SHIFT)
 
+/* TAS6424_GLOB_FAULT1_REG */
+#define TAS6424_FAULT_OC_CH1           BIT(7)
+#define TAS6424_FAULT_OC_CH2           BIT(6)
+#define TAS6424_FAULT_OC_CH3           BIT(5)
+#define TAS6424_FAULT_OC_CH4           BIT(4)
+#define TAS6424_FAULT_DC_CH1           BIT(3)
+#define TAS6424_FAULT_DC_CH2           BIT(2)
+#define TAS6424_FAULT_DC_CH3           BIT(1)
+#define TAS6424_FAULT_DC_CH4           BIT(0)
+
 /* TAS6424_GLOB_FAULT1_REG */
 #define TAS6424_FAULT_CLOCK            BIT(4)
 #define TAS6424_FAULT_PVDD_OV          BIT(3)