Skip to content

Commit 20677b3

Browse files
charleskeepaxlag-linaro
authored andcommitted
mfd: cs42l43: Update patching revision check
The firmware can only be patched once. The current code checks if the firmware supports the features required by the driver and then patches if it does not. This could lead to the device being patched twice if the device was patched before the driver took control, but with a firmware that doesn't support the features the driver requires. This would fail but potentially in unpredictable ways. The check should actually check the device is at the ROM version, and patch the device if it is. Then a separate later check should error out if the devices firmware is still too old to be supported. This will at least fail in a clean way with a nice error message. Signed-off-by: Charles Keepax <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Lee Jones <[email protected]>
1 parent aecebbc commit 20677b3

File tree

1 file changed

+30
-6
lines changed

1 file changed

+30
-6
lines changed

drivers/mfd/cs42l43.c

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
#define CS42L43_MCU_UPDATE_TIMEOUT_US 500000
4444
#define CS42L43_MCU_UPDATE_RETRIES 5
4545

46+
#define CS42L43_MCU_ROM_REV 0x2001
47+
#define CS42L43_MCU_ROM_BIOS_REV 0x0000
48+
4649
#define CS42L43_MCU_SUPPORTED_REV 0x2105
4750
#define CS42L43_MCU_SHADOW_REGS_REQUIRED_REV 0x2200
4851
#define CS42L43_MCU_SUPPORTED_BIOS_REV 0x0001
@@ -709,6 +712,23 @@ static void cs42l43_mcu_load_firmware(const struct firmware *firmware, void *con
709712
complete(&cs42l43->firmware_download);
710713
}
711714

715+
static int cs42l43_mcu_is_hw_compatible(struct cs42l43 *cs42l43,
716+
unsigned int mcu_rev,
717+
unsigned int bios_rev)
718+
{
719+
/*
720+
* The firmware has two revision numbers bringing either of them up to a
721+
* supported version will provide the disable the driver requires.
722+
*/
723+
if (mcu_rev < CS42L43_MCU_SUPPORTED_REV &&
724+
bios_rev < CS42L43_MCU_SUPPORTED_BIOS_REV) {
725+
dev_err(cs42l43->dev, "Firmware too old to support disable\n");
726+
return -EINVAL;
727+
}
728+
729+
return 0;
730+
}
731+
712732
/*
713733
* The process of updating the firmware is split into a series of steps, at the
714734
* end of each step a soft reset of the device might be required which will
@@ -745,11 +765,10 @@ static int cs42l43_mcu_update_step(struct cs42l43 *cs42l43)
745765
((mcu_rev & CS42L43_FW_SUBMINOR_REV_MASK) >> 8);
746766

747767
/*
748-
* The firmware has two revision numbers bringing either of them up to a
749-
* supported version will provide the features the driver requires.
768+
* The firmware has two revision numbers both of them being at the ROM
769+
* revision indicates no patch has been applied.
750770
*/
751-
patched = mcu_rev >= CS42L43_MCU_SUPPORTED_REV ||
752-
bios_rev >= CS42L43_MCU_SUPPORTED_BIOS_REV;
771+
patched = mcu_rev != CS42L43_MCU_ROM_REV || bios_rev != CS42L43_MCU_ROM_BIOS_REV;
753772
/*
754773
* Later versions of the firmwware require the driver to access some
755774
* features through a set of shadow registers.
@@ -794,10 +813,15 @@ static int cs42l43_mcu_update_step(struct cs42l43 *cs42l43)
794813
return cs42l43_mcu_stage_2_3(cs42l43, shadow);
795814
}
796815
case CS42L43_MCU_BOOT_STAGE3:
797-
if (patched)
816+
if (patched) {
817+
ret = cs42l43_mcu_is_hw_compatible(cs42l43, mcu_rev, bios_rev);
818+
if (ret)
819+
return ret;
820+
798821
return cs42l43_mcu_disable(cs42l43);
799-
else
822+
} else {
800823
return cs42l43_mcu_stage_3_2(cs42l43);
824+
}
801825
case CS42L43_MCU_BOOT_STAGE4:
802826
return 0;
803827
default:

0 commit comments

Comments
 (0)