Lines Matching +full:firmware +full:- +full:reset
1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2022-2023 Cirrus Logic, Inc. and
15 #include <linux/firmware.h>
20 #include <linux/mfd/cs42l43-regs.h>
441 #define CS42L43_IRQ_OFFSET(reg) ((CS42L43_##reg##_INT) - CS42L43_DECIM_INT)
510 "vdd-a", "vdd-io", "vdd-cp",
513 static const char * const cs42l43_parent_supplies[] = { "vdd-amp" };
516 { .name = "cs42l43-pinctrl", },
517 { .name = "cs42l43-spi", },
519 .name = "cs42l43-codec",
532 static const struct reg_sequence reset[] = { in cs42l43_soft_reset() local
536 reinit_completion(&cs42l43->device_detach); in cs42l43_soft_reset()
539 * Apply cache only because the soft reset will cause the device to in cs42l43_soft_reset()
542 regcache_cache_only(cs42l43->regmap, true); in cs42l43_soft_reset()
543 regmap_multi_reg_write_bypassed(cs42l43->regmap, reset, ARRAY_SIZE(reset)); in cs42l43_soft_reset()
547 if (cs42l43->sdw) { in cs42l43_soft_reset()
551 time = wait_for_completion_timeout(&cs42l43->device_detach, timeout); in cs42l43_soft_reset()
553 dev_err(cs42l43->dev, "Timed out waiting for device detach\n"); in cs42l43_soft_reset()
554 return -ETIMEDOUT; in cs42l43_soft_reset()
558 return -EAGAIN; in cs42l43_soft_reset()
562 * This function is essentially a no-op on I2C, but will wait for the device to
567 if (!cs42l43->attached) { in cs42l43_wait_for_attach()
571 time = wait_for_completion_timeout(&cs42l43->device_attach, timeout); in cs42l43_wait_for_attach()
573 dev_err(cs42l43->dev, "Timed out waiting for device re-attach\n"); in cs42l43_wait_for_attach()
574 return -ETIMEDOUT; in cs42l43_wait_for_attach()
578 regcache_cache_only(cs42l43->regmap, false); in cs42l43_wait_for_attach()
581 if (cs42l43->sdw) in cs42l43_wait_for_attach()
582 regmap_write(cs42l43->regmap, CS42L43_OSC_DIV_SEL, in cs42l43_wait_for_attach()
589 * This function will advance the firmware into boot stage 3 from boot stage 2.
590 * Boot stage 3 is required to send commands to the firmware. This is achieved
591 * by setting the firmware NEED configuration register to zero, this indicates
592 * no configuration is required forcing the firmware to advance to boot stage 3.
594 * Later revisions of the firmware require the use of an alternative register
606 regmap_write(cs42l43->regmap, need_reg, 0); in cs42l43_mcu_stage_2_3()
608 ret = regmap_read_poll_timeout(cs42l43->regmap, CS42L43_BOOT_STATUS, in cs42l43_mcu_stage_2_3()
612 dev_err(cs42l43->dev, "Failed to move to stage 3: %d, 0x%x\n", ret, val); in cs42l43_mcu_stage_2_3()
616 return -EAGAIN; in cs42l43_mcu_stage_2_3()
620 * This function will return the firmware to boot stage 2 from boot stage 3.
621 * Boot stage 2 is required to apply updates to the firmware. This is achieved
622 * by setting the firmware NEED configuration register to FW_PATCH_NEED_CFG,
624 * firmware will see it is missing a patch configuration and will pause in boot
628 * register here as the driver will only return to boot stage 2 if the firmware
634 regmap_write(cs42l43->regmap, CS42L43_FW_MISSION_CTRL_NEED_CONFIGS, in cs42l43_mcu_stage_3_2()
636 regmap_write(cs42l43->regmap, CS42L43_FW_MISSION_CTRL_HAVE_CONFIGS, 0); in cs42l43_mcu_stage_3_2()
642 * Disable the firmware running on the device such that the driver can access
650 regmap_write(cs42l43->regmap, CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_REG, in cs42l43_mcu_disable()
652 regmap_write(cs42l43->regmap, CS42L43_FW_MISSION_CTRL_MM_CTRL_SELECTION, in cs42l43_mcu_disable()
654 regmap_write(cs42l43->regmap, CS42L43_MCU_SW_INTERRUPT, CS42L43_CONTROL_IND_MASK); in cs42l43_mcu_disable()
655 regmap_write(cs42l43->regmap, CS42L43_MCU_SW_INTERRUPT, 0); in cs42l43_mcu_disable()
657 ret = regmap_read_poll_timeout(cs42l43->regmap, CS42L43_SOFT_INT_SHADOW, val, in cs42l43_mcu_disable()
661 dev_err(cs42l43->dev, "Failed to disable firmware: %d, 0x%x\n", ret, val); in cs42l43_mcu_disable()
665 /* Soft reset to clear any register state the firmware left behind. */ in cs42l43_mcu_disable()
670 * Callback to load firmware updates.
672 static void cs42l43_mcu_load_firmware(const struct firmware *firmware, void *context) in cs42l43_mcu_load_firmware() argument
679 if (!firmware) { in cs42l43_mcu_load_firmware()
680 dev_err(cs42l43->dev, "Failed to load firmware\n"); in cs42l43_mcu_load_firmware()
681 cs42l43->firmware_error = -ENODEV; in cs42l43_mcu_load_firmware()
685 hdr = (const struct cs42l43_patch_header *)&firmware->data[0]; in cs42l43_mcu_load_firmware()
686 loadaddr = le32_to_cpu(hdr->load_addr); in cs42l43_mcu_load_firmware()
688 if (le16_to_cpu(hdr->version) != CS42L43_MCU_UPDATE_FORMAT) { in cs42l43_mcu_load_firmware()
689 dev_err(cs42l43->dev, "Bad firmware file format: %d\n", hdr->version); in cs42l43_mcu_load_firmware()
690 cs42l43->firmware_error = -EINVAL; in cs42l43_mcu_load_firmware()
694 regmap_write(cs42l43->regmap, CS42L43_PATCH_START_ADDR, loadaddr); in cs42l43_mcu_load_firmware()
695 regmap_bulk_write(cs42l43->regmap, loadaddr + CS42L43_MCU_UPDATE_OFFSET, in cs42l43_mcu_load_firmware()
696 &firmware->data[0], firmware->size / sizeof(u32)); in cs42l43_mcu_load_firmware()
698 regmap_write(cs42l43->regmap, CS42L43_MCU_SW_INTERRUPT, CS42L43_PATCH_IND_MASK); in cs42l43_mcu_load_firmware()
699 regmap_write(cs42l43->regmap, CS42L43_MCU_SW_INTERRUPT, 0); in cs42l43_mcu_load_firmware()
701 ret = regmap_read_poll_timeout(cs42l43->regmap, CS42L43_SOFT_INT_SHADOW, val, in cs42l43_mcu_load_firmware()
705 dev_err(cs42l43->dev, "Failed to update firmware: %d, 0x%x\n", ret, val); in cs42l43_mcu_load_firmware()
706 cs42l43->firmware_error = ret; in cs42l43_mcu_load_firmware()
711 release_firmware(firmware); in cs42l43_mcu_load_firmware()
713 complete(&cs42l43->firmware_download); in cs42l43_mcu_load_firmware()
721 * The firmware has two revision numbers bringing either of them up to a in cs42l43_mcu_is_hw_compatible()
726 dev_err(cs42l43->dev, "Firmware too old to support disable\n"); in cs42l43_mcu_is_hw_compatible()
727 return -EINVAL; in cs42l43_mcu_is_hw_compatible()
734 * The process of updating the firmware is split into a series of steps, at the
735 * end of each step a soft reset of the device might be required which will
736 * require the driver to wait for the device to re-attach on the SoundWire bus,
746 regmap_read(cs42l43->regmap, CS42L43_SOFT_INT, &mcu_rev); in cs42l43_mcu_update_step()
748 ret = regmap_read(cs42l43->regmap, CS42L43_BOOT_STATUS, &boot_status); in cs42l43_mcu_update_step()
750 dev_err(cs42l43->dev, "Failed to read boot status: %d\n", ret); in cs42l43_mcu_update_step()
754 ret = regmap_read(cs42l43->regmap, CS42L43_MCU_SW_REV, &mcu_rev); in cs42l43_mcu_update_step()
756 dev_err(cs42l43->dev, "Failed to read firmware revision: %d\n", ret); in cs42l43_mcu_update_step()
769 * The firmware has two revision numbers both of them being at the ROM in cs42l43_mcu_update_step()
780 ret = regmap_read(cs42l43->regmap, CS42L43_BOOT_CONTROL, &secure_cfg); in cs42l43_mcu_update_step()
782 dev_err(cs42l43->dev, "Failed to read security settings: %d\n", ret); in cs42l43_mcu_update_step()
786 cs42l43->hw_lock = secure_cfg & CS42L43_LOCK_HW_STS_MASK; in cs42l43_mcu_update_step()
788 if (!patched && cs42l43->hw_lock) { in cs42l43_mcu_update_step()
789 dev_err(cs42l43->dev, "Unpatched secure device\n"); in cs42l43_mcu_update_step()
790 return -EPERM; in cs42l43_mcu_update_step()
793 dev_dbg(cs42l43->dev, "Firmware(0x%x, 0x%x) in boot stage %d\n", in cs42l43_mcu_update_step()
800 "cs42l43.bin", cs42l43->dev, in cs42l43_mcu_update_step()
804 dev_err(cs42l43->dev, "Failed to request firmware: %d\n", ret); in cs42l43_mcu_update_step()
808 wait_for_completion(&cs42l43->firmware_download); in cs42l43_mcu_update_step()
810 if (cs42l43->firmware_error) in cs42l43_mcu_update_step()
811 return cs42l43->firmware_error; in cs42l43_mcu_update_step()
813 return -EAGAIN; in cs42l43_mcu_update_step()
830 dev_err(cs42l43->dev, "Invalid boot status: %d\n", boot_status); in cs42l43_mcu_update_step()
831 return -EINVAL; in cs42l43_mcu_update_step()
836 * Update the firmware running on the device.
844 if (ret != -EAGAIN) in cs42l43_mcu_update()
852 dev_err(cs42l43->dev, "Failed retrying update\n"); in cs42l43_mcu_update()
853 return -ETIMEDOUT; in cs42l43_mcu_update()
862 if (cs42l43->sdw) in cs42l43_irq_config()
863 cs42l43->irq = cs42l43->sdw->irq; in cs42l43_irq_config()
865 cs42l43->irq_chip = cs42l43_irq_chip; in cs42l43_irq_config()
866 cs42l43->irq_chip.irq_drv_data = cs42l43; in cs42l43_irq_config()
868 irq_data = irq_get_irq_data(cs42l43->irq); in cs42l43_irq_config()
870 dev_err(cs42l43->dev, "Invalid IRQ: %d\n", cs42l43->irq); in cs42l43_irq_config()
871 return -EINVAL; in cs42l43_irq_config()
889 ret = devm_regmap_add_irq_chip(cs42l43->dev, cs42l43->regmap, in cs42l43_irq_config()
890 cs42l43->irq, irq_flags, 0, in cs42l43_irq_config()
891 &cs42l43->irq_chip, &cs42l43->irq_data); in cs42l43_irq_config()
893 dev_err(cs42l43->dev, "Failed to add IRQ chip: %d\n", ret); in cs42l43_irq_config()
897 dev_dbg(cs42l43->dev, "Configured IRQ %d with flags 0x%lx\n", in cs42l43_irq_config()
898 cs42l43->irq, irq_flags); in cs42l43_irq_config()
913 ret = regmap_read(cs42l43->regmap, CS42L43_DEVID, &devid); in cs42l43_boot_work()
915 dev_err(cs42l43->dev, "Failed to read devid: %d\n", ret); in cs42l43_boot_work()
923 dev_err(cs42l43->dev, "Unrecognised devid: 0x%06x\n", devid); in cs42l43_boot_work()
927 ret = regmap_read(cs42l43->regmap, CS42L43_REVID, &revid); in cs42l43_boot_work()
929 dev_err(cs42l43->dev, "Failed to read rev: %d\n", ret); in cs42l43_boot_work()
933 ret = regmap_read(cs42l43->regmap, CS42L43_OTP_REVISION_ID, &otp); in cs42l43_boot_work()
935 dev_err(cs42l43->dev, "Failed to read otp rev: %d\n", ret); in cs42l43_boot_work()
939 dev_info(cs42l43->dev, in cs42l43_boot_work()
946 ret = regmap_register_patch(cs42l43->regmap, cs42l43_reva_patch, in cs42l43_boot_work()
949 dev_err(cs42l43->dev, "Failed to apply register patch: %d\n", ret); in cs42l43_boot_work()
957 ret = devm_mfd_add_devices(cs42l43->dev, PLATFORM_DEVID_NONE, in cs42l43_boot_work()
961 dev_err(cs42l43->dev, "Failed to add subdevices: %d\n", ret); in cs42l43_boot_work()
965 pm_runtime_mark_last_busy(cs42l43->dev); in cs42l43_boot_work()
966 pm_runtime_put_autosuspend(cs42l43->dev); in cs42l43_boot_work()
971 pm_runtime_put_sync(cs42l43->dev); in cs42l43_boot_work()
978 ret = regulator_enable(cs42l43->vdd_p); in cs42l43_power_up()
980 dev_err(cs42l43->dev, "Failed to enable vdd-p: %d\n", ret); in cs42l43_power_up()
984 /* vdd-p must be on for 50uS before any other supply */ in cs42l43_power_up()
987 gpiod_set_raw_value_cansleep(cs42l43->reset, 1); in cs42l43_power_up()
989 ret = regulator_bulk_enable(CS42L43_N_SUPPLIES, cs42l43->core_supplies); in cs42l43_power_up()
991 dev_err(cs42l43->dev, "Failed to enable core supplies: %d\n", ret); in cs42l43_power_up()
995 ret = regulator_enable(cs42l43->vdd_d); in cs42l43_power_up()
997 dev_err(cs42l43->dev, "Failed to enable vdd-d: %d\n", ret); in cs42l43_power_up()
1006 regulator_bulk_disable(CS42L43_N_SUPPLIES, cs42l43->core_supplies); in cs42l43_power_up()
1008 gpiod_set_raw_value_cansleep(cs42l43->reset, 0); in cs42l43_power_up()
1009 regulator_disable(cs42l43->vdd_p); in cs42l43_power_up()
1018 ret = regulator_disable(cs42l43->vdd_d); in cs42l43_power_down()
1020 dev_err(cs42l43->dev, "Failed to disable vdd-d: %d\n", ret); in cs42l43_power_down()
1024 ret = regulator_bulk_disable(CS42L43_N_SUPPLIES, cs42l43->core_supplies); in cs42l43_power_down()
1026 dev_err(cs42l43->dev, "Failed to disable core supplies: %d\n", ret); in cs42l43_power_down()
1030 gpiod_set_raw_value_cansleep(cs42l43->reset, 0); in cs42l43_power_down()
1032 ret = regulator_disable(cs42l43->vdd_p); in cs42l43_power_down()
1034 dev_err(cs42l43->dev, "Failed to disable vdd-p: %d\n", ret); in cs42l43_power_down()
1045 cancel_work_sync(&cs42l43->boot_work); in cs42l43_dev_remove()
1054 dev_set_drvdata(cs42l43->dev, cs42l43); in cs42l43_dev_probe()
1056 mutex_init(&cs42l43->pll_lock); in cs42l43_dev_probe()
1057 init_completion(&cs42l43->device_attach); in cs42l43_dev_probe()
1058 init_completion(&cs42l43->device_detach); in cs42l43_dev_probe()
1059 init_completion(&cs42l43->firmware_download); in cs42l43_dev_probe()
1060 INIT_WORK(&cs42l43->boot_work, cs42l43_boot_work); in cs42l43_dev_probe()
1062 regcache_cache_only(cs42l43->regmap, true); in cs42l43_dev_probe()
1064 cs42l43->reset = devm_gpiod_get_optional(cs42l43->dev, "reset", GPIOD_OUT_HIGH); in cs42l43_dev_probe()
1065 if (IS_ERR(cs42l43->reset)) in cs42l43_dev_probe()
1066 return dev_err_probe(cs42l43->dev, PTR_ERR(cs42l43->reset), in cs42l43_dev_probe()
1067 "Failed to get reset\n"); in cs42l43_dev_probe()
1069 gpiod_set_raw_value_cansleep(cs42l43->reset, 0); in cs42l43_dev_probe()
1071 cs42l43->vdd_p = devm_regulator_get(cs42l43->dev, "vdd-p"); in cs42l43_dev_probe()
1072 if (IS_ERR(cs42l43->vdd_p)) in cs42l43_dev_probe()
1073 return dev_err_probe(cs42l43->dev, PTR_ERR(cs42l43->vdd_p), in cs42l43_dev_probe()
1074 "Failed to get vdd-p\n"); in cs42l43_dev_probe()
1076 cs42l43->vdd_d = devm_regulator_get(cs42l43->dev, "vdd-d"); in cs42l43_dev_probe()
1077 if (IS_ERR(cs42l43->vdd_d)) in cs42l43_dev_probe()
1078 return dev_err_probe(cs42l43->dev, PTR_ERR(cs42l43->vdd_d), in cs42l43_dev_probe()
1079 "Failed to get vdd-d\n"); in cs42l43_dev_probe()
1084 cs42l43->core_supplies[i].supply = cs42l43_core_supplies[i]; in cs42l43_dev_probe()
1086 ret = devm_regulator_bulk_get(cs42l43->dev, CS42L43_N_SUPPLIES, in cs42l43_dev_probe()
1087 cs42l43->core_supplies); in cs42l43_dev_probe()
1089 return dev_err_probe(cs42l43->dev, ret, in cs42l43_dev_probe()
1096 ret = devm_add_action_or_reset(cs42l43->dev, cs42l43_dev_remove, cs42l43); in cs42l43_dev_probe()
1100 pm_runtime_set_autosuspend_delay(cs42l43->dev, CS42L43_AUTOSUSPEND_TIME_MS); in cs42l43_dev_probe()
1101 pm_runtime_use_autosuspend(cs42l43->dev); in cs42l43_dev_probe()
1102 pm_runtime_set_active(cs42l43->dev); in cs42l43_dev_probe()
1107 pm_runtime_get_noresume(cs42l43->dev); in cs42l43_dev_probe()
1108 ret = devm_pm_runtime_enable(cs42l43->dev); in cs42l43_dev_probe()
1112 queue_work(system_long_wq, &cs42l43->boot_work); in cs42l43_dev_probe()
1143 dev_err(cs42l43->dev, "Failed to resume for suspend: %d\n", ret); in cs42l43_suspend()
1147 /* The IRQs will be re-enabled on resume by the cache sync */ in cs42l43_suspend()
1148 ret = regmap_multi_reg_write_bypassed(cs42l43->regmap, in cs42l43_suspend()
1151 dev_err(cs42l43->dev, "Failed to mask IRQs: %d\n", ret); in cs42l43_suspend()
1157 dev_err(cs42l43->dev, "Failed to force suspend: %d\n", ret); in cs42l43_suspend()
1168 disable_irq(cs42l43->irq); in cs42l43_suspend()
1177 enable_irq(cs42l43->irq); in cs42l43_suspend_noirq()
1186 disable_irq(cs42l43->irq); in cs42l43_resume_noirq()
1200 enable_irq(cs42l43->irq); in cs42l43_resume()
1204 dev_err(cs42l43->dev, "Failed to force resume: %d\n", ret); in cs42l43_resume()
1220 regcache_cache_only(cs42l43->regmap, true); in cs42l43_runtime_suspend()
1235 ret = regmap_read(cs42l43->regmap, CS42L43_RELID, &reset_canary); in cs42l43_runtime_resume()
1237 dev_err(cs42l43->dev, "Failed to check reset canary: %d\n", ret); in cs42l43_runtime_resume()
1243 * If the canary has cleared the chip has reset, re-handle the in cs42l43_runtime_resume()
1244 * MCU and mark the cache as dirty to indicate the chip reset. in cs42l43_runtime_resume()
1250 regcache_mark_dirty(cs42l43->regmap); in cs42l43_runtime_resume()
1253 ret = regcache_sync(cs42l43->regmap); in cs42l43_runtime_resume()
1255 dev_err(cs42l43->dev, "Failed to restore register cache: %d\n", ret); in cs42l43_runtime_resume()
1262 regcache_cache_only(cs42l43->regmap, true); in cs42l43_runtime_resume()