1ace6d144SCharles Keepax // SPDX-License-Identifier: GPL-2.0 2ace6d144SCharles Keepax /* 3ace6d144SCharles Keepax * CS42L43 core driver 4ace6d144SCharles Keepax * 5ace6d144SCharles Keepax * Copyright (C) 2022-2023 Cirrus Logic, Inc. and 6ace6d144SCharles Keepax * Cirrus Logic International Semiconductor Ltd. 7ace6d144SCharles Keepax */ 8ace6d144SCharles Keepax 9ace6d144SCharles Keepax #include <linux/bitops.h> 10ace6d144SCharles Keepax #include <linux/build_bug.h> 11ace6d144SCharles Keepax #include <linux/delay.h> 12ace6d144SCharles Keepax #include <linux/err.h> 13ace6d144SCharles Keepax #include <linux/errno.h> 14ace6d144SCharles Keepax #include <linux/firmware.h> 15ace6d144SCharles Keepax #include <linux/jiffies.h> 16ace6d144SCharles Keepax #include <linux/mfd/core.h> 17ace6d144SCharles Keepax #include <linux/mfd/cs42l43-regs.h> 18ace6d144SCharles Keepax #include <linux/module.h> 19ace6d144SCharles Keepax #include <linux/pm_runtime.h> 20ace6d144SCharles Keepax #include <linux/soundwire/sdw.h> 21ace6d144SCharles Keepax 22ace6d144SCharles Keepax #include "cs42l43.h" 23ace6d144SCharles Keepax 24ace6d144SCharles Keepax #define CS42L43_RESET_DELAY 20 25ace6d144SCharles Keepax 26ace6d144SCharles Keepax #define CS42L43_SDW_ATTACH_TIMEOUT 500 27ace6d144SCharles Keepax #define CS42L43_SDW_DETACH_TIMEOUT 100 28ace6d144SCharles Keepax 29ace6d144SCharles Keepax #define CS42L43_MCU_BOOT_STAGE1 1 30ace6d144SCharles Keepax #define CS42L43_MCU_BOOT_STAGE2 2 31ace6d144SCharles Keepax #define CS42L43_MCU_BOOT_STAGE3 3 32ace6d144SCharles Keepax #define CS42L43_MCU_BOOT_STAGE4 4 33ace6d144SCharles Keepax #define CS42L43_MCU_POLL 5000 34ace6d144SCharles Keepax #define CS42L43_MCU_CMD_TIMEOUT 20000 35ace6d144SCharles Keepax #define CS42L43_MCU_UPDATE_FORMAT 3 36ace6d144SCharles Keepax #define CS42L43_MCU_UPDATE_OFFSET 0x100000 37ace6d144SCharles Keepax #define CS42L43_MCU_UPDATE_TIMEOUT 500000 38ace6d144SCharles Keepax #define CS42L43_MCU_UPDATE_RETRIES 5 39ace6d144SCharles Keepax 40ace6d144SCharles Keepax #define CS42L43_MCU_SUPPORTED_REV 0x2105 41ace6d144SCharles Keepax #define CS42L43_MCU_SHADOW_REGS_REQUIRED_REV 0x2200 42ace6d144SCharles Keepax #define CS42L43_MCU_SUPPORTED_BIOS_REV 0x0001 43ace6d144SCharles Keepax 44ace6d144SCharles Keepax #define CS42L43_VDDP_DELAY 50 45ace6d144SCharles Keepax #define CS42L43_VDDD_DELAY 1000 46ace6d144SCharles Keepax 47ace6d144SCharles Keepax #define CS42L43_AUTOSUSPEND_TIME 250 48ace6d144SCharles Keepax 49ace6d144SCharles Keepax struct cs42l43_patch_header { 50ace6d144SCharles Keepax __le16 version; 51ace6d144SCharles Keepax __le16 size; 52ace6d144SCharles Keepax u8 reserved; 53ace6d144SCharles Keepax u8 secure; 54ace6d144SCharles Keepax __le16 bss_size; 55ace6d144SCharles Keepax __le32 apply_addr; 56ace6d144SCharles Keepax __le32 checksum; 57ace6d144SCharles Keepax __le32 sha; 58ace6d144SCharles Keepax __le16 swrev; 59ace6d144SCharles Keepax __le16 patchid; 60ace6d144SCharles Keepax __le16 ipxid; 61ace6d144SCharles Keepax __le16 romver; 62ace6d144SCharles Keepax __le32 load_addr; 63ace6d144SCharles Keepax } __packed; 64ace6d144SCharles Keepax 65ace6d144SCharles Keepax static const struct reg_sequence cs42l43_reva_patch[] = { 66ace6d144SCharles Keepax { 0x4000, 0x00000055 }, 67ace6d144SCharles Keepax { 0x4000, 0x000000AA }, 68ace6d144SCharles Keepax { 0x10084, 0x00000000 }, 69ace6d144SCharles Keepax { 0x1741C, 0x00CD2000 }, 70ace6d144SCharles Keepax { 0x1718C, 0x00000003 }, 71ace6d144SCharles Keepax { 0x4000, 0x00000000 }, 72ace6d144SCharles Keepax { CS42L43_CCM_BLK_CLK_CONTROL, 0x00000002 }, 73ace6d144SCharles Keepax { CS42L43_HPPATHVOL, 0x011B011B }, 74ace6d144SCharles Keepax { CS42L43_OSC_DIV_SEL, 0x00000001 }, 75ace6d144SCharles Keepax { CS42L43_DACCNFG2, 0x00000005 }, 76ace6d144SCharles Keepax { CS42L43_MIC_DETECT_CONTROL_ANDROID, 0x80790079 }, 77ace6d144SCharles Keepax { CS42L43_RELID, 0x0000000F }, 78ace6d144SCharles Keepax }; 79ace6d144SCharles Keepax 80ace6d144SCharles Keepax const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS] = { 81ace6d144SCharles Keepax { CS42L43_DRV_CTRL1, 0x000186C0 }, 82ace6d144SCharles Keepax { CS42L43_DRV_CTRL3, 0x286DB018 }, 83ace6d144SCharles Keepax { CS42L43_DRV_CTRL4, 0x000006D8 }, 84ace6d144SCharles Keepax { CS42L43_DRV_CTRL_5, 0x136C00C0 }, 85ace6d144SCharles Keepax { CS42L43_GPIO_CTRL1, 0x00000707 }, 86ace6d144SCharles Keepax { CS42L43_GPIO_CTRL2, 0x00000000 }, 87ace6d144SCharles Keepax { CS42L43_GPIO_FN_SEL, 0x00000000 }, 88ace6d144SCharles Keepax { CS42L43_MCLK_SRC_SEL, 0x00000000 }, 89ace6d144SCharles Keepax { CS42L43_SAMPLE_RATE1, 0x00000003 }, 90ace6d144SCharles Keepax { CS42L43_SAMPLE_RATE2, 0x00000003 }, 91ace6d144SCharles Keepax { CS42L43_SAMPLE_RATE3, 0x00000003 }, 92ace6d144SCharles Keepax { CS42L43_SAMPLE_RATE4, 0x00000003 }, 93ace6d144SCharles Keepax { CS42L43_PLL_CONTROL, 0x00000000 }, 94ace6d144SCharles Keepax { CS42L43_FS_SELECT1, 0x00000000 }, 95ace6d144SCharles Keepax { CS42L43_FS_SELECT2, 0x00000000 }, 96ace6d144SCharles Keepax { CS42L43_FS_SELECT3, 0x00000000 }, 97ace6d144SCharles Keepax { CS42L43_FS_SELECT4, 0x00000000 }, 98ace6d144SCharles Keepax { CS42L43_PDM_CONTROL, 0x00000000 }, 99ace6d144SCharles Keepax { CS42L43_ASP_CLK_CONFIG1, 0x00010001 }, 100ace6d144SCharles Keepax { CS42L43_ASP_CLK_CONFIG2, 0x00000000 }, 101ace6d144SCharles Keepax { CS42L43_OSC_DIV_SEL, 0x00000001 }, 102ace6d144SCharles Keepax { CS42L43_ADC_B_CTRL1, 0x00000000 }, 103ace6d144SCharles Keepax { CS42L43_ADC_B_CTRL2, 0x00000000 }, 104ace6d144SCharles Keepax { CS42L43_DECIM_HPF_WNF_CTRL1, 0x00000001 }, 105ace6d144SCharles Keepax { CS42L43_DECIM_HPF_WNF_CTRL2, 0x00000001 }, 106ace6d144SCharles Keepax { CS42L43_DECIM_HPF_WNF_CTRL3, 0x00000001 }, 107ace6d144SCharles Keepax { CS42L43_DECIM_HPF_WNF_CTRL4, 0x00000001 }, 108ace6d144SCharles Keepax { CS42L43_DMIC_PDM_CTRL, 0x00000000 }, 109ace6d144SCharles Keepax { CS42L43_DECIM_VOL_CTRL_CH1_CH2, 0x20122012 }, 110ace6d144SCharles Keepax { CS42L43_DECIM_VOL_CTRL_CH3_CH4, 0x20122012 }, 111ace6d144SCharles Keepax { CS42L43_INTP_VOLUME_CTRL1, 0x00000180 }, 112ace6d144SCharles Keepax { CS42L43_INTP_VOLUME_CTRL2, 0x00000180 }, 113ace6d144SCharles Keepax { CS42L43_AMP1_2_VOL_RAMP, 0x00000022 }, 114ace6d144SCharles Keepax { CS42L43_ASP_CTRL, 0x00000004 }, 115ace6d144SCharles Keepax { CS42L43_ASP_FSYNC_CTRL1, 0x000000FA }, 116ace6d144SCharles Keepax { CS42L43_ASP_FSYNC_CTRL2, 0x00000001 }, 117ace6d144SCharles Keepax { CS42L43_ASP_FSYNC_CTRL3, 0x00000000 }, 118ace6d144SCharles Keepax { CS42L43_ASP_FSYNC_CTRL4, 0x000001F4 }, 119ace6d144SCharles Keepax { CS42L43_ASP_DATA_CTRL, 0x0000003A }, 120ace6d144SCharles Keepax { CS42L43_ASP_RX_EN, 0x00000000 }, 121ace6d144SCharles Keepax { CS42L43_ASP_TX_EN, 0x00000000 }, 122ace6d144SCharles Keepax { CS42L43_ASP_RX_CH1_CTRL, 0x00170001 }, 123ace6d144SCharles Keepax { CS42L43_ASP_RX_CH2_CTRL, 0x00170031 }, 124ace6d144SCharles Keepax { CS42L43_ASP_RX_CH3_CTRL, 0x00170061 }, 125ace6d144SCharles Keepax { CS42L43_ASP_RX_CH4_CTRL, 0x00170091 }, 126ace6d144SCharles Keepax { CS42L43_ASP_RX_CH5_CTRL, 0x001700C1 }, 127ace6d144SCharles Keepax { CS42L43_ASP_RX_CH6_CTRL, 0x001700F1 }, 128ace6d144SCharles Keepax { CS42L43_ASP_TX_CH1_CTRL, 0x00170001 }, 129ace6d144SCharles Keepax { CS42L43_ASP_TX_CH2_CTRL, 0x00170031 }, 130ace6d144SCharles Keepax { CS42L43_ASP_TX_CH3_CTRL, 0x00170061 }, 131ace6d144SCharles Keepax { CS42L43_ASP_TX_CH4_CTRL, 0x00170091 }, 132ace6d144SCharles Keepax { CS42L43_ASP_TX_CH5_CTRL, 0x001700C1 }, 133ace6d144SCharles Keepax { CS42L43_ASP_TX_CH6_CTRL, 0x001700F1 }, 134*30d1366bSMaciej Strozek { CS42L43_ASPTX1_INPUT, 0x00000000 }, 135*30d1366bSMaciej Strozek { CS42L43_ASPTX2_INPUT, 0x00000000 }, 136*30d1366bSMaciej Strozek { CS42L43_ASPTX3_INPUT, 0x00000000 }, 137*30d1366bSMaciej Strozek { CS42L43_ASPTX4_INPUT, 0x00000000 }, 138*30d1366bSMaciej Strozek { CS42L43_ASPTX5_INPUT, 0x00000000 }, 139*30d1366bSMaciej Strozek { CS42L43_ASPTX6_INPUT, 0x00000000 }, 140*30d1366bSMaciej Strozek { CS42L43_SWIRE_DP1_CH1_INPUT, 0x00000000 }, 141*30d1366bSMaciej Strozek { CS42L43_SWIRE_DP1_CH2_INPUT, 0x00000000 }, 142*30d1366bSMaciej Strozek { CS42L43_SWIRE_DP1_CH3_INPUT, 0x00000000 }, 143*30d1366bSMaciej Strozek { CS42L43_SWIRE_DP1_CH4_INPUT, 0x00000000 }, 144*30d1366bSMaciej Strozek { CS42L43_SWIRE_DP2_CH1_INPUT, 0x00000000 }, 145*30d1366bSMaciej Strozek { CS42L43_SWIRE_DP2_CH2_INPUT, 0x00000000 }, 146*30d1366bSMaciej Strozek { CS42L43_SWIRE_DP3_CH1_INPUT, 0x00000000 }, 147*30d1366bSMaciej Strozek { CS42L43_SWIRE_DP3_CH2_INPUT, 0x00000000 }, 148*30d1366bSMaciej Strozek { CS42L43_SWIRE_DP4_CH1_INPUT, 0x00000000 }, 149*30d1366bSMaciej Strozek { CS42L43_SWIRE_DP4_CH2_INPUT, 0x00000000 }, 150*30d1366bSMaciej Strozek { CS42L43_ASRC_INT1_INPUT1, 0x00000000 }, 151*30d1366bSMaciej Strozek { CS42L43_ASRC_INT2_INPUT1, 0x00000000 }, 152*30d1366bSMaciej Strozek { CS42L43_ASRC_INT3_INPUT1, 0x00000000 }, 153*30d1366bSMaciej Strozek { CS42L43_ASRC_INT4_INPUT1, 0x00000000 }, 154*30d1366bSMaciej Strozek { CS42L43_ASRC_DEC1_INPUT1, 0x00000000 }, 155*30d1366bSMaciej Strozek { CS42L43_ASRC_DEC2_INPUT1, 0x00000000 }, 156*30d1366bSMaciej Strozek { CS42L43_ASRC_DEC3_INPUT1, 0x00000000 }, 157*30d1366bSMaciej Strozek { CS42L43_ASRC_DEC4_INPUT1, 0x00000000 }, 158*30d1366bSMaciej Strozek { CS42L43_ISRC1INT1_INPUT1, 0x00000000 }, 159*30d1366bSMaciej Strozek { CS42L43_ISRC1INT2_INPUT1, 0x00000000 }, 160*30d1366bSMaciej Strozek { CS42L43_ISRC1DEC1_INPUT1, 0x00000000 }, 161*30d1366bSMaciej Strozek { CS42L43_ISRC1DEC2_INPUT1, 0x00000000 }, 162*30d1366bSMaciej Strozek { CS42L43_ISRC2INT1_INPUT1, 0x00000000 }, 163*30d1366bSMaciej Strozek { CS42L43_ISRC2INT2_INPUT1, 0x00000000 }, 164*30d1366bSMaciej Strozek { CS42L43_ISRC2DEC1_INPUT1, 0x00000000 }, 165*30d1366bSMaciej Strozek { CS42L43_ISRC2DEC2_INPUT1, 0x00000000 }, 166ace6d144SCharles Keepax { CS42L43_EQ1MIX_INPUT1, 0x00800000 }, 167ace6d144SCharles Keepax { CS42L43_EQ1MIX_INPUT2, 0x00800000 }, 168ace6d144SCharles Keepax { CS42L43_EQ1MIX_INPUT3, 0x00800000 }, 169ace6d144SCharles Keepax { CS42L43_EQ1MIX_INPUT4, 0x00800000 }, 170ace6d144SCharles Keepax { CS42L43_EQ2MIX_INPUT1, 0x00800000 }, 171ace6d144SCharles Keepax { CS42L43_EQ2MIX_INPUT2, 0x00800000 }, 172ace6d144SCharles Keepax { CS42L43_EQ2MIX_INPUT3, 0x00800000 }, 173ace6d144SCharles Keepax { CS42L43_EQ2MIX_INPUT4, 0x00800000 }, 174*30d1366bSMaciej Strozek { CS42L43_SPDIF1_INPUT1, 0x00000000 }, 175*30d1366bSMaciej Strozek { CS42L43_SPDIF2_INPUT1, 0x00000000 }, 176ace6d144SCharles Keepax { CS42L43_AMP1MIX_INPUT1, 0x00800000 }, 177ace6d144SCharles Keepax { CS42L43_AMP1MIX_INPUT2, 0x00800000 }, 178ace6d144SCharles Keepax { CS42L43_AMP1MIX_INPUT3, 0x00800000 }, 179ace6d144SCharles Keepax { CS42L43_AMP1MIX_INPUT4, 0x00800000 }, 180ace6d144SCharles Keepax { CS42L43_AMP2MIX_INPUT1, 0x00800000 }, 181ace6d144SCharles Keepax { CS42L43_AMP2MIX_INPUT2, 0x00800000 }, 182ace6d144SCharles Keepax { CS42L43_AMP2MIX_INPUT3, 0x00800000 }, 183ace6d144SCharles Keepax { CS42L43_AMP2MIX_INPUT4, 0x00800000 }, 184ace6d144SCharles Keepax { CS42L43_AMP3MIX_INPUT1, 0x00800000 }, 185ace6d144SCharles Keepax { CS42L43_AMP3MIX_INPUT2, 0x00800000 }, 186ace6d144SCharles Keepax { CS42L43_AMP3MIX_INPUT3, 0x00800000 }, 187ace6d144SCharles Keepax { CS42L43_AMP3MIX_INPUT4, 0x00800000 }, 188ace6d144SCharles Keepax { CS42L43_AMP4MIX_INPUT1, 0x00800000 }, 189ace6d144SCharles Keepax { CS42L43_AMP4MIX_INPUT2, 0x00800000 }, 190ace6d144SCharles Keepax { CS42L43_AMP4MIX_INPUT3, 0x00800000 }, 191ace6d144SCharles Keepax { CS42L43_AMP4MIX_INPUT4, 0x00800000 }, 192ace6d144SCharles Keepax { CS42L43_ASRC_INT_ENABLES, 0x00000100 }, 193ace6d144SCharles Keepax { CS42L43_ASRC_DEC_ENABLES, 0x00000100 }, 194ace6d144SCharles Keepax { CS42L43_PDNCNTL, 0x00000000 }, 195ace6d144SCharles Keepax { CS42L43_RINGSENSE_DEB_CTRL, 0x0000001B }, 196ace6d144SCharles Keepax { CS42L43_TIPSENSE_DEB_CTRL, 0x0000001B }, 197ace6d144SCharles Keepax { CS42L43_HS2, 0x050106F3 }, 198ace6d144SCharles Keepax { CS42L43_STEREO_MIC_CTRL, 0x00000000 }, 199ace6d144SCharles Keepax { CS42L43_STEREO_MIC_CLAMP_CTRL, 0x00000001 }, 200ace6d144SCharles Keepax { CS42L43_BLOCK_EN2, 0x00000000 }, 201ace6d144SCharles Keepax { CS42L43_BLOCK_EN3, 0x00000000 }, 202ace6d144SCharles Keepax { CS42L43_BLOCK_EN4, 0x00000000 }, 203ace6d144SCharles Keepax { CS42L43_BLOCK_EN5, 0x00000000 }, 204ace6d144SCharles Keepax { CS42L43_BLOCK_EN6, 0x00000000 }, 205ace6d144SCharles Keepax { CS42L43_BLOCK_EN7, 0x00000000 }, 206ace6d144SCharles Keepax { CS42L43_BLOCK_EN8, 0x00000000 }, 207ace6d144SCharles Keepax { CS42L43_BLOCK_EN9, 0x00000000 }, 208ace6d144SCharles Keepax { CS42L43_BLOCK_EN10, 0x00000000 }, 209ace6d144SCharles Keepax { CS42L43_BLOCK_EN11, 0x00000000 }, 210ace6d144SCharles Keepax { CS42L43_TONE_CH1_CTRL, 0x00000000 }, 211ace6d144SCharles Keepax { CS42L43_TONE_CH2_CTRL, 0x00000000 }, 212ace6d144SCharles Keepax { CS42L43_MIC_DETECT_CONTROL_1, 0x00000003 }, 213ace6d144SCharles Keepax { CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL, 0x02000003 }, 214ace6d144SCharles Keepax { CS42L43_MIC_DETECT_CONTROL_ANDROID, 0x80790079 }, 215ace6d144SCharles Keepax { CS42L43_ISRC1_CTRL, 0x00000000 }, 216ace6d144SCharles Keepax { CS42L43_ISRC2_CTRL, 0x00000000 }, 217ace6d144SCharles Keepax { CS42L43_CTRL_REG, 0x00000006 }, 218ace6d144SCharles Keepax { CS42L43_FDIV_FRAC, 0x40000000 }, 219ace6d144SCharles Keepax { CS42L43_CAL_RATIO, 0x00000080 }, 220ace6d144SCharles Keepax { CS42L43_SPI_CLK_CONFIG1, 0x00000000 }, 221ace6d144SCharles Keepax { CS42L43_SPI_CONFIG1, 0x00000000 }, 222ace6d144SCharles Keepax { CS42L43_SPI_CONFIG2, 0x00000000 }, 223ace6d144SCharles Keepax { CS42L43_SPI_CONFIG3, 0x00000001 }, 224ace6d144SCharles Keepax { CS42L43_SPI_CONFIG4, 0x00000000 }, 225ace6d144SCharles Keepax { CS42L43_TRAN_CONFIG3, 0x00000000 }, 226ace6d144SCharles Keepax { CS42L43_TRAN_CONFIG4, 0x00000000 }, 227ace6d144SCharles Keepax { CS42L43_TRAN_CONFIG5, 0x00000000 }, 228ace6d144SCharles Keepax { CS42L43_TRAN_CONFIG6, 0x00000000 }, 229ace6d144SCharles Keepax { CS42L43_TRAN_CONFIG7, 0x00000000 }, 230ace6d144SCharles Keepax { CS42L43_TRAN_CONFIG8, 0x00000000 }, 231ace6d144SCharles Keepax { CS42L43_DACCNFG1, 0x00000008 }, 232ace6d144SCharles Keepax { CS42L43_DACCNFG2, 0x00000005 }, 233ace6d144SCharles Keepax { CS42L43_HPPATHVOL, 0x011B011B }, 234ace6d144SCharles Keepax { CS42L43_PGAVOL, 0x00003470 }, 235ace6d144SCharles Keepax { CS42L43_LOADDETENA, 0x00000000 }, 236ace6d144SCharles Keepax { CS42L43_CTRL, 0x00000037 }, 237ace6d144SCharles Keepax { CS42L43_COEFF_DATA_IN0, 0x00000000 }, 238ace6d144SCharles Keepax { CS42L43_COEFF_RD_WR0, 0x00000000 }, 239ace6d144SCharles Keepax { CS42L43_START_EQZ0, 0x00000000 }, 240ace6d144SCharles Keepax { CS42L43_MUTE_EQ_IN0, 0x00000000 }, 241ace6d144SCharles Keepax { CS42L43_DECIM_MASK, 0x0000000F }, 242ace6d144SCharles Keepax { CS42L43_EQ_MIX_MASK, 0x0000000F }, 243ace6d144SCharles Keepax { CS42L43_ASP_MASK, 0x000000FF }, 244ace6d144SCharles Keepax { CS42L43_PLL_MASK, 0x00000003 }, 245ace6d144SCharles Keepax { CS42L43_SOFT_MASK, 0x0000FFFF }, 246ace6d144SCharles Keepax { CS42L43_SWIRE_MASK, 0x00007FFF }, 247ace6d144SCharles Keepax { CS42L43_MSM_MASK, 0x00000FFF }, 248ace6d144SCharles Keepax { CS42L43_ACC_DET_MASK, 0x00000FFF }, 249ace6d144SCharles Keepax { CS42L43_I2C_TGT_MASK, 0x00000003 }, 250ace6d144SCharles Keepax { CS42L43_SPI_MSTR_MASK, 0x00000007 }, 251ace6d144SCharles Keepax { CS42L43_SW_TO_SPI_BRIDGE_MASK, 0x00000001 }, 252ace6d144SCharles Keepax { CS42L43_OTP_MASK, 0x00000007 }, 253ace6d144SCharles Keepax { CS42L43_CLASS_D_AMP_MASK, 0x00003FFF }, 254ace6d144SCharles Keepax { CS42L43_GPIO_INT_MASK, 0x0000003F }, 255ace6d144SCharles Keepax { CS42L43_ASRC_MASK, 0x0000000F }, 256ace6d144SCharles Keepax { CS42L43_HPOUT_MASK, 0x00000003 }, 257ace6d144SCharles Keepax }; 258ace6d144SCharles Keepax EXPORT_SYMBOL_NS_GPL(cs42l43_reg_default, MFD_CS42L43); 259ace6d144SCharles Keepax 260ace6d144SCharles Keepax bool cs42l43_readable_register(struct device *dev, unsigned int reg) 261ace6d144SCharles Keepax { 262ace6d144SCharles Keepax switch (reg) { 263ace6d144SCharles Keepax case CS42L43_DEVID: 264ace6d144SCharles Keepax case CS42L43_REVID: 265ace6d144SCharles Keepax case CS42L43_RELID: 266ace6d144SCharles Keepax case CS42L43_SFT_RESET: 267ace6d144SCharles Keepax case CS42L43_DRV_CTRL1: 268ace6d144SCharles Keepax case CS42L43_DRV_CTRL3: 269ace6d144SCharles Keepax case CS42L43_DRV_CTRL4: 270ace6d144SCharles Keepax case CS42L43_DRV_CTRL_5: 271ace6d144SCharles Keepax case CS42L43_GPIO_CTRL1: 272ace6d144SCharles Keepax case CS42L43_GPIO_CTRL2: 273ace6d144SCharles Keepax case CS42L43_GPIO_STS: 274ace6d144SCharles Keepax case CS42L43_GPIO_FN_SEL: 275ace6d144SCharles Keepax case CS42L43_MCLK_SRC_SEL: 276ace6d144SCharles Keepax case CS42L43_SAMPLE_RATE1 ... CS42L43_SAMPLE_RATE4: 277ace6d144SCharles Keepax case CS42L43_PLL_CONTROL: 278ace6d144SCharles Keepax case CS42L43_FS_SELECT1 ... CS42L43_FS_SELECT4: 279ace6d144SCharles Keepax case CS42L43_PDM_CONTROL: 280ace6d144SCharles Keepax case CS42L43_ASP_CLK_CONFIG1 ... CS42L43_ASP_CLK_CONFIG2: 281ace6d144SCharles Keepax case CS42L43_OSC_DIV_SEL: 282ace6d144SCharles Keepax case CS42L43_ADC_B_CTRL1 ... CS42L43_ADC_B_CTRL2: 283ace6d144SCharles Keepax case CS42L43_DECIM_HPF_WNF_CTRL1 ... CS42L43_DECIM_HPF_WNF_CTRL4: 284ace6d144SCharles Keepax case CS42L43_DMIC_PDM_CTRL: 285ace6d144SCharles Keepax case CS42L43_DECIM_VOL_CTRL_CH1_CH2 ... CS42L43_DECIM_VOL_CTRL_CH3_CH4: 286ace6d144SCharles Keepax case CS42L43_INTP_VOLUME_CTRL1 ... CS42L43_INTP_VOLUME_CTRL2: 287ace6d144SCharles Keepax case CS42L43_AMP1_2_VOL_RAMP: 288ace6d144SCharles Keepax case CS42L43_ASP_CTRL: 289ace6d144SCharles Keepax case CS42L43_ASP_FSYNC_CTRL1 ... CS42L43_ASP_FSYNC_CTRL4: 290ace6d144SCharles Keepax case CS42L43_ASP_DATA_CTRL: 291ace6d144SCharles Keepax case CS42L43_ASP_RX_EN ... CS42L43_ASP_TX_EN: 292ace6d144SCharles Keepax case CS42L43_ASP_RX_CH1_CTRL ... CS42L43_ASP_RX_CH6_CTRL: 293ace6d144SCharles Keepax case CS42L43_ASP_TX_CH1_CTRL ... CS42L43_ASP_TX_CH6_CTRL: 294ace6d144SCharles Keepax case CS42L43_OTP_REVISION_ID: 295ace6d144SCharles Keepax case CS42L43_ASPTX1_INPUT: 296ace6d144SCharles Keepax case CS42L43_ASPTX2_INPUT: 297ace6d144SCharles Keepax case CS42L43_ASPTX3_INPUT: 298ace6d144SCharles Keepax case CS42L43_ASPTX4_INPUT: 299ace6d144SCharles Keepax case CS42L43_ASPTX5_INPUT: 300ace6d144SCharles Keepax case CS42L43_ASPTX6_INPUT: 301ace6d144SCharles Keepax case CS42L43_SWIRE_DP1_CH1_INPUT: 302ace6d144SCharles Keepax case CS42L43_SWIRE_DP1_CH2_INPUT: 303ace6d144SCharles Keepax case CS42L43_SWIRE_DP1_CH3_INPUT: 304ace6d144SCharles Keepax case CS42L43_SWIRE_DP1_CH4_INPUT: 305ace6d144SCharles Keepax case CS42L43_SWIRE_DP2_CH1_INPUT: 306ace6d144SCharles Keepax case CS42L43_SWIRE_DP2_CH2_INPUT: 307ace6d144SCharles Keepax case CS42L43_SWIRE_DP3_CH1_INPUT: 308ace6d144SCharles Keepax case CS42L43_SWIRE_DP3_CH2_INPUT: 309ace6d144SCharles Keepax case CS42L43_SWIRE_DP4_CH1_INPUT: 310ace6d144SCharles Keepax case CS42L43_SWIRE_DP4_CH2_INPUT: 311ace6d144SCharles Keepax case CS42L43_ASRC_INT1_INPUT1: 312ace6d144SCharles Keepax case CS42L43_ASRC_INT2_INPUT1: 313ace6d144SCharles Keepax case CS42L43_ASRC_INT3_INPUT1: 314ace6d144SCharles Keepax case CS42L43_ASRC_INT4_INPUT1: 315ace6d144SCharles Keepax case CS42L43_ASRC_DEC1_INPUT1: 316ace6d144SCharles Keepax case CS42L43_ASRC_DEC2_INPUT1: 317ace6d144SCharles Keepax case CS42L43_ASRC_DEC3_INPUT1: 318ace6d144SCharles Keepax case CS42L43_ASRC_DEC4_INPUT1: 319ace6d144SCharles Keepax case CS42L43_ISRC1INT1_INPUT1: 320ace6d144SCharles Keepax case CS42L43_ISRC1INT2_INPUT1: 321ace6d144SCharles Keepax case CS42L43_ISRC1DEC1_INPUT1: 322ace6d144SCharles Keepax case CS42L43_ISRC1DEC2_INPUT1: 323ace6d144SCharles Keepax case CS42L43_ISRC2INT1_INPUT1: 324ace6d144SCharles Keepax case CS42L43_ISRC2INT2_INPUT1: 325ace6d144SCharles Keepax case CS42L43_ISRC2DEC1_INPUT1: 326ace6d144SCharles Keepax case CS42L43_ISRC2DEC2_INPUT1: 327ace6d144SCharles Keepax case CS42L43_EQ1MIX_INPUT1 ... CS42L43_EQ1MIX_INPUT4: 328ace6d144SCharles Keepax case CS42L43_EQ2MIX_INPUT1 ... CS42L43_EQ2MIX_INPUT4: 329ace6d144SCharles Keepax case CS42L43_SPDIF1_INPUT1: 330ace6d144SCharles Keepax case CS42L43_SPDIF2_INPUT1: 331ace6d144SCharles Keepax case CS42L43_AMP1MIX_INPUT1 ... CS42L43_AMP1MIX_INPUT4: 332ace6d144SCharles Keepax case CS42L43_AMP2MIX_INPUT1 ... CS42L43_AMP2MIX_INPUT4: 333ace6d144SCharles Keepax case CS42L43_AMP3MIX_INPUT1 ... CS42L43_AMP3MIX_INPUT4: 334ace6d144SCharles Keepax case CS42L43_AMP4MIX_INPUT1 ... CS42L43_AMP4MIX_INPUT4: 335ace6d144SCharles Keepax case CS42L43_ASRC_INT_ENABLES ... CS42L43_ASRC_DEC_ENABLES: 336ace6d144SCharles Keepax case CS42L43_PDNCNTL: 337ace6d144SCharles Keepax case CS42L43_RINGSENSE_DEB_CTRL: 338ace6d144SCharles Keepax case CS42L43_TIPSENSE_DEB_CTRL: 339ace6d144SCharles Keepax case CS42L43_TIP_RING_SENSE_INTERRUPT_STATUS: 340ace6d144SCharles Keepax case CS42L43_HS2: 341ace6d144SCharles Keepax case CS42L43_HS_STAT: 342ace6d144SCharles Keepax case CS42L43_MCU_SW_INTERRUPT: 343ace6d144SCharles Keepax case CS42L43_STEREO_MIC_CTRL: 344ace6d144SCharles Keepax case CS42L43_STEREO_MIC_CLAMP_CTRL: 345ace6d144SCharles Keepax case CS42L43_BLOCK_EN2 ... CS42L43_BLOCK_EN11: 346ace6d144SCharles Keepax case CS42L43_TONE_CH1_CTRL ... CS42L43_TONE_CH2_CTRL: 347ace6d144SCharles Keepax case CS42L43_MIC_DETECT_CONTROL_1: 348ace6d144SCharles Keepax case CS42L43_DETECT_STATUS_1: 349ace6d144SCharles Keepax case CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL: 350ace6d144SCharles Keepax case CS42L43_MIC_DETECT_CONTROL_ANDROID: 351ace6d144SCharles Keepax case CS42L43_ISRC1_CTRL: 352ace6d144SCharles Keepax case CS42L43_ISRC2_CTRL: 353ace6d144SCharles Keepax case CS42L43_CTRL_REG: 354ace6d144SCharles Keepax case CS42L43_FDIV_FRAC: 355ace6d144SCharles Keepax case CS42L43_CAL_RATIO: 356ace6d144SCharles Keepax case CS42L43_SPI_CLK_CONFIG1: 357ace6d144SCharles Keepax case CS42L43_SPI_CONFIG1 ... CS42L43_SPI_CONFIG4: 358ace6d144SCharles Keepax case CS42L43_SPI_STATUS1 ... CS42L43_SPI_STATUS2: 359ace6d144SCharles Keepax case CS42L43_TRAN_CONFIG1 ... CS42L43_TRAN_CONFIG8: 360ace6d144SCharles Keepax case CS42L43_TRAN_STATUS1 ... CS42L43_TRAN_STATUS3: 361ace6d144SCharles Keepax case CS42L43_TX_DATA: 362ace6d144SCharles Keepax case CS42L43_RX_DATA: 363ace6d144SCharles Keepax case CS42L43_DACCNFG1 ... CS42L43_DACCNFG2: 364ace6d144SCharles Keepax case CS42L43_HPPATHVOL: 365ace6d144SCharles Keepax case CS42L43_PGAVOL: 366ace6d144SCharles Keepax case CS42L43_LOADDETRESULTS: 367ace6d144SCharles Keepax case CS42L43_LOADDETENA: 368ace6d144SCharles Keepax case CS42L43_CTRL: 369ace6d144SCharles Keepax case CS42L43_COEFF_DATA_IN0: 370ace6d144SCharles Keepax case CS42L43_COEFF_RD_WR0: 371ace6d144SCharles Keepax case CS42L43_INIT_DONE0: 372ace6d144SCharles Keepax case CS42L43_START_EQZ0: 373ace6d144SCharles Keepax case CS42L43_MUTE_EQ_IN0: 374ace6d144SCharles Keepax case CS42L43_DECIM_INT ... CS42L43_HPOUT_INT: 375ace6d144SCharles Keepax case CS42L43_DECIM_MASK ... CS42L43_HPOUT_MASK: 376ace6d144SCharles Keepax case CS42L43_DECIM_INT_SHADOW ... CS42L43_HP_OUT_SHADOW: 377ace6d144SCharles Keepax case CS42L43_BOOT_CONTROL: 378ace6d144SCharles Keepax case CS42L43_BLOCK_EN: 379ace6d144SCharles Keepax case CS42L43_SHUTTER_CONTROL: 380ace6d144SCharles Keepax case CS42L43_MCU_SW_REV ... CS42L43_MCU_RAM_MAX: 381ace6d144SCharles Keepax return true; 382ace6d144SCharles Keepax default: 383ace6d144SCharles Keepax return false; 384ace6d144SCharles Keepax } 385ace6d144SCharles Keepax } 386ace6d144SCharles Keepax EXPORT_SYMBOL_NS_GPL(cs42l43_readable_register, MFD_CS42L43); 387ace6d144SCharles Keepax 388ace6d144SCharles Keepax bool cs42l43_precious_register(struct device *dev, unsigned int reg) 389ace6d144SCharles Keepax { 390ace6d144SCharles Keepax switch (reg) { 391ace6d144SCharles Keepax case CS42L43_SFT_RESET: 392ace6d144SCharles Keepax case CS42L43_TX_DATA: 393ace6d144SCharles Keepax case CS42L43_RX_DATA: 394ace6d144SCharles Keepax case CS42L43_DECIM_INT ... CS42L43_HPOUT_INT: 395ace6d144SCharles Keepax case CS42L43_MCU_SW_REV ... CS42L43_MCU_RAM_MAX: 396ace6d144SCharles Keepax return true; 397ace6d144SCharles Keepax default: 398ace6d144SCharles Keepax return false; 399ace6d144SCharles Keepax } 400ace6d144SCharles Keepax } 401ace6d144SCharles Keepax EXPORT_SYMBOL_NS_GPL(cs42l43_precious_register, MFD_CS42L43); 402ace6d144SCharles Keepax 403ace6d144SCharles Keepax bool cs42l43_volatile_register(struct device *dev, unsigned int reg) 404ace6d144SCharles Keepax { 405ace6d144SCharles Keepax switch (reg) { 406ace6d144SCharles Keepax case CS42L43_DEVID: 407ace6d144SCharles Keepax case CS42L43_REVID: 408ace6d144SCharles Keepax case CS42L43_RELID: 409ace6d144SCharles Keepax case CS42L43_GPIO_STS: 410ace6d144SCharles Keepax case CS42L43_OTP_REVISION_ID: 411ace6d144SCharles Keepax case CS42L43_TIP_RING_SENSE_INTERRUPT_STATUS: 412ace6d144SCharles Keepax case CS42L43_HS_STAT: 413ace6d144SCharles Keepax case CS42L43_MCU_SW_INTERRUPT: 414ace6d144SCharles Keepax case CS42L43_DETECT_STATUS_1: 415ace6d144SCharles Keepax case CS42L43_SPI_STATUS1 ... CS42L43_SPI_STATUS2: 416ace6d144SCharles Keepax case CS42L43_TRAN_CONFIG1 ... CS42L43_TRAN_CONFIG2: 417ace6d144SCharles Keepax case CS42L43_TRAN_CONFIG8: 418ace6d144SCharles Keepax case CS42L43_TRAN_STATUS1 ... CS42L43_TRAN_STATUS3: 419ace6d144SCharles Keepax case CS42L43_LOADDETRESULTS: 420ace6d144SCharles Keepax case CS42L43_INIT_DONE0: 421ace6d144SCharles Keepax case CS42L43_DECIM_INT_SHADOW ... CS42L43_HP_OUT_SHADOW: 422ace6d144SCharles Keepax case CS42L43_BOOT_CONTROL: 423ace6d144SCharles Keepax case CS42L43_BLOCK_EN: 424ace6d144SCharles Keepax return true; 425ace6d144SCharles Keepax default: 426ace6d144SCharles Keepax return cs42l43_precious_register(dev, reg); 427ace6d144SCharles Keepax } 428ace6d144SCharles Keepax } 429ace6d144SCharles Keepax EXPORT_SYMBOL_NS_GPL(cs42l43_volatile_register, MFD_CS42L43); 430ace6d144SCharles Keepax 431ace6d144SCharles Keepax #define CS42L43_IRQ_OFFSET(reg) ((CS42L43_##reg##_INT) - CS42L43_DECIM_INT) 432ace6d144SCharles Keepax 433ace6d144SCharles Keepax #define CS42L43_IRQ_REG(name, reg) REGMAP_IRQ_REG(CS42L43_##name, \ 434ace6d144SCharles Keepax CS42L43_IRQ_OFFSET(reg), \ 435ace6d144SCharles Keepax CS42L43_##name##_INT_MASK) 436ace6d144SCharles Keepax 437ace6d144SCharles Keepax static const struct regmap_irq cs42l43_regmap_irqs[] = { 438ace6d144SCharles Keepax CS42L43_IRQ_REG(PLL_LOST_LOCK, PLL), 439ace6d144SCharles Keepax CS42L43_IRQ_REG(PLL_READY, PLL), 440ace6d144SCharles Keepax 441ace6d144SCharles Keepax CS42L43_IRQ_REG(HP_STARTUP_DONE, MSM), 442ace6d144SCharles Keepax CS42L43_IRQ_REG(HP_SHUTDOWN_DONE, MSM), 443ace6d144SCharles Keepax CS42L43_IRQ_REG(HSDET_DONE, MSM), 444ace6d144SCharles Keepax CS42L43_IRQ_REG(TIPSENSE_UNPLUG_DB, MSM), 445ace6d144SCharles Keepax CS42L43_IRQ_REG(TIPSENSE_PLUG_DB, MSM), 446ace6d144SCharles Keepax CS42L43_IRQ_REG(RINGSENSE_UNPLUG_DB, MSM), 447ace6d144SCharles Keepax CS42L43_IRQ_REG(RINGSENSE_PLUG_DB, MSM), 448ace6d144SCharles Keepax CS42L43_IRQ_REG(TIPSENSE_UNPLUG_PDET, MSM), 449ace6d144SCharles Keepax CS42L43_IRQ_REG(TIPSENSE_PLUG_PDET, MSM), 450ace6d144SCharles Keepax CS42L43_IRQ_REG(RINGSENSE_UNPLUG_PDET, MSM), 451ace6d144SCharles Keepax CS42L43_IRQ_REG(RINGSENSE_PLUG_PDET, MSM), 452ace6d144SCharles Keepax 453ace6d144SCharles Keepax CS42L43_IRQ_REG(HS2_BIAS_SENSE, ACC_DET), 454ace6d144SCharles Keepax CS42L43_IRQ_REG(HS1_BIAS_SENSE, ACC_DET), 455ace6d144SCharles Keepax CS42L43_IRQ_REG(DC_DETECT1_FALSE, ACC_DET), 456ace6d144SCharles Keepax CS42L43_IRQ_REG(DC_DETECT1_TRUE, ACC_DET), 457ace6d144SCharles Keepax CS42L43_IRQ_REG(HSBIAS_CLAMPED, ACC_DET), 458ace6d144SCharles Keepax CS42L43_IRQ_REG(HS3_4_BIAS_SENSE, ACC_DET), 459ace6d144SCharles Keepax 460ace6d144SCharles Keepax CS42L43_IRQ_REG(AMP2_CLK_STOP_FAULT, CLASS_D_AMP), 461ace6d144SCharles Keepax CS42L43_IRQ_REG(AMP1_CLK_STOP_FAULT, CLASS_D_AMP), 462ace6d144SCharles Keepax CS42L43_IRQ_REG(AMP2_VDDSPK_FAULT, CLASS_D_AMP), 463ace6d144SCharles Keepax CS42L43_IRQ_REG(AMP1_VDDSPK_FAULT, CLASS_D_AMP), 464ace6d144SCharles Keepax CS42L43_IRQ_REG(AMP2_SHUTDOWN_DONE, CLASS_D_AMP), 465ace6d144SCharles Keepax CS42L43_IRQ_REG(AMP1_SHUTDOWN_DONE, CLASS_D_AMP), 466ace6d144SCharles Keepax CS42L43_IRQ_REG(AMP2_STARTUP_DONE, CLASS_D_AMP), 467ace6d144SCharles Keepax CS42L43_IRQ_REG(AMP1_STARTUP_DONE, CLASS_D_AMP), 468ace6d144SCharles Keepax CS42L43_IRQ_REG(AMP2_THERM_SHDN, CLASS_D_AMP), 469ace6d144SCharles Keepax CS42L43_IRQ_REG(AMP1_THERM_SHDN, CLASS_D_AMP), 470ace6d144SCharles Keepax CS42L43_IRQ_REG(AMP2_THERM_WARN, CLASS_D_AMP), 471ace6d144SCharles Keepax CS42L43_IRQ_REG(AMP1_THERM_WARN, CLASS_D_AMP), 472ace6d144SCharles Keepax CS42L43_IRQ_REG(AMP2_SCDET, CLASS_D_AMP), 473ace6d144SCharles Keepax CS42L43_IRQ_REG(AMP1_SCDET, CLASS_D_AMP), 474ace6d144SCharles Keepax 475ace6d144SCharles Keepax CS42L43_IRQ_REG(GPIO3_FALL, GPIO), 476ace6d144SCharles Keepax CS42L43_IRQ_REG(GPIO3_RISE, GPIO), 477ace6d144SCharles Keepax CS42L43_IRQ_REG(GPIO2_FALL, GPIO), 478ace6d144SCharles Keepax CS42L43_IRQ_REG(GPIO2_RISE, GPIO), 479ace6d144SCharles Keepax CS42L43_IRQ_REG(GPIO1_FALL, GPIO), 480ace6d144SCharles Keepax CS42L43_IRQ_REG(GPIO1_RISE, GPIO), 481ace6d144SCharles Keepax 482ace6d144SCharles Keepax CS42L43_IRQ_REG(HP_ILIMIT, HPOUT), 483ace6d144SCharles Keepax CS42L43_IRQ_REG(HP_LOADDET_DONE, HPOUT), 484ace6d144SCharles Keepax }; 485ace6d144SCharles Keepax 486ace6d144SCharles Keepax static const struct regmap_irq_chip cs42l43_irq_chip = { 487ace6d144SCharles Keepax .name = "cs42l43", 488ace6d144SCharles Keepax 489ace6d144SCharles Keepax .status_base = CS42L43_DECIM_INT, 490ace6d144SCharles Keepax .mask_base = CS42L43_DECIM_MASK, 491ace6d144SCharles Keepax .num_regs = 16, 492ace6d144SCharles Keepax 493ace6d144SCharles Keepax .irqs = cs42l43_regmap_irqs, 494ace6d144SCharles Keepax .num_irqs = ARRAY_SIZE(cs42l43_regmap_irqs), 495ace6d144SCharles Keepax 496ace6d144SCharles Keepax .runtime_pm = true, 497ace6d144SCharles Keepax }; 498ace6d144SCharles Keepax 499ace6d144SCharles Keepax static const char * const cs42l43_core_supplies[] = { 500ace6d144SCharles Keepax "vdd-a", "vdd-io", "vdd-cp", 501ace6d144SCharles Keepax }; 502ace6d144SCharles Keepax 503ace6d144SCharles Keepax static const char * const cs42l43_parent_supplies[] = { "vdd-amp" }; 504ace6d144SCharles Keepax 505ace6d144SCharles Keepax static const struct mfd_cell cs42l43_devs[] = { 506ace6d144SCharles Keepax { .name = "cs42l43-pinctrl", }, 507ace6d144SCharles Keepax { .name = "cs42l43-spi", }, 508ace6d144SCharles Keepax { 509ace6d144SCharles Keepax .name = "cs42l43-codec", 510ace6d144SCharles Keepax .parent_supplies = cs42l43_parent_supplies, 511ace6d144SCharles Keepax .num_parent_supplies = ARRAY_SIZE(cs42l43_parent_supplies), 512ace6d144SCharles Keepax }, 513ace6d144SCharles Keepax }; 514ace6d144SCharles Keepax 515ace6d144SCharles Keepax /* 516ace6d144SCharles Keepax * If the device is connected over Soundwire, as well as soft resetting the 517ace6d144SCharles Keepax * device, this function will also way for the device to detach from the bus 518ace6d144SCharles Keepax * before returning. 519ace6d144SCharles Keepax */ 520ace6d144SCharles Keepax static int cs42l43_soft_reset(struct cs42l43 *cs42l43) 521ace6d144SCharles Keepax { 522ace6d144SCharles Keepax static const struct reg_sequence reset[] = { 523ace6d144SCharles Keepax { CS42L43_SFT_RESET, CS42L43_SFT_RESET_VAL }, 524ace6d144SCharles Keepax }; 525ace6d144SCharles Keepax 526ace6d144SCharles Keepax reinit_completion(&cs42l43->device_detach); 527ace6d144SCharles Keepax 528ace6d144SCharles Keepax /* 529ace6d144SCharles Keepax * Apply cache only because the soft reset will cause the device to 530ace6d144SCharles Keepax * detach from the soundwire bus. 531ace6d144SCharles Keepax */ 532ace6d144SCharles Keepax regcache_cache_only(cs42l43->regmap, true); 533ace6d144SCharles Keepax regmap_multi_reg_write_bypassed(cs42l43->regmap, reset, ARRAY_SIZE(reset)); 534ace6d144SCharles Keepax 535ace6d144SCharles Keepax msleep(CS42L43_RESET_DELAY); 536ace6d144SCharles Keepax 537ace6d144SCharles Keepax if (cs42l43->sdw) { 538ace6d144SCharles Keepax unsigned long timeout = msecs_to_jiffies(CS42L43_SDW_DETACH_TIMEOUT); 539ace6d144SCharles Keepax unsigned long time; 540ace6d144SCharles Keepax 541ace6d144SCharles Keepax time = wait_for_completion_timeout(&cs42l43->device_detach, timeout); 542ace6d144SCharles Keepax if (!time) { 543ace6d144SCharles Keepax dev_err(cs42l43->dev, "Timed out waiting for device detach\n"); 544ace6d144SCharles Keepax return -ETIMEDOUT; 545ace6d144SCharles Keepax } 546ace6d144SCharles Keepax } 547ace6d144SCharles Keepax 548ace6d144SCharles Keepax return -EAGAIN; 549ace6d144SCharles Keepax } 550ace6d144SCharles Keepax 551ace6d144SCharles Keepax /* 552ace6d144SCharles Keepax * This function is essentially a no-op on I2C, but will wait for the device to 553ace6d144SCharles Keepax * attach when the device is used on a SoundWire bus. 554ace6d144SCharles Keepax */ 555ace6d144SCharles Keepax static int cs42l43_wait_for_attach(struct cs42l43 *cs42l43) 556ace6d144SCharles Keepax { 557ace6d144SCharles Keepax if (!cs42l43->attached) { 558ace6d144SCharles Keepax unsigned long timeout = msecs_to_jiffies(CS42L43_SDW_ATTACH_TIMEOUT); 559ace6d144SCharles Keepax unsigned long time; 560ace6d144SCharles Keepax 561ace6d144SCharles Keepax time = wait_for_completion_timeout(&cs42l43->device_attach, timeout); 562ace6d144SCharles Keepax if (!time) { 563ace6d144SCharles Keepax dev_err(cs42l43->dev, "Timed out waiting for device re-attach\n"); 564ace6d144SCharles Keepax return -ETIMEDOUT; 565ace6d144SCharles Keepax } 566ace6d144SCharles Keepax } 567ace6d144SCharles Keepax 568ace6d144SCharles Keepax regcache_cache_only(cs42l43->regmap, false); 569ace6d144SCharles Keepax 570ace6d144SCharles Keepax /* The hardware requires enabling OSC_DIV before doing any SoundWire reads. */ 571ace6d144SCharles Keepax if (cs42l43->sdw) 572ace6d144SCharles Keepax regmap_write(cs42l43->regmap, CS42L43_OSC_DIV_SEL, 573ace6d144SCharles Keepax CS42L43_OSC_DIV2_EN_MASK); 574ace6d144SCharles Keepax 575ace6d144SCharles Keepax return 0; 576ace6d144SCharles Keepax } 577ace6d144SCharles Keepax 578ace6d144SCharles Keepax /* 579ace6d144SCharles Keepax * This function will advance the firmware into boot stage 3 from boot stage 2. 580ace6d144SCharles Keepax * Boot stage 3 is required to send commands to the firmware. This is achieved 581ace6d144SCharles Keepax * by setting the firmware NEED configuration register to zero, this indicates 582ace6d144SCharles Keepax * no configuration is required forcing the firmware to advance to boot stage 3. 583ace6d144SCharles Keepax * 584ace6d144SCharles Keepax * Later revisions of the firmware require the use of an alternative register 585ace6d144SCharles Keepax * for this purpose, which is indicated through the shadow flag. 586ace6d144SCharles Keepax */ 587ace6d144SCharles Keepax static int cs42l43_mcu_stage_2_3(struct cs42l43 *cs42l43, bool shadow) 588ace6d144SCharles Keepax { 589ace6d144SCharles Keepax unsigned int need_reg = CS42L43_NEED_CONFIGS; 590ace6d144SCharles Keepax unsigned int val; 591ace6d144SCharles Keepax int ret; 592ace6d144SCharles Keepax 593ace6d144SCharles Keepax if (shadow) 594ace6d144SCharles Keepax need_reg = CS42L43_FW_SH_BOOT_CFG_NEED_CONFIGS; 595ace6d144SCharles Keepax 596ace6d144SCharles Keepax regmap_write(cs42l43->regmap, need_reg, 0); 597ace6d144SCharles Keepax 598ace6d144SCharles Keepax ret = regmap_read_poll_timeout(cs42l43->regmap, CS42L43_BOOT_STATUS, 599ace6d144SCharles Keepax val, (val == CS42L43_MCU_BOOT_STAGE3), 600ace6d144SCharles Keepax CS42L43_MCU_POLL, CS42L43_MCU_CMD_TIMEOUT); 601ace6d144SCharles Keepax if (ret) { 602ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to move to stage 3: %d, 0x%x\n", ret, val); 603ace6d144SCharles Keepax return ret; 604ace6d144SCharles Keepax } 605ace6d144SCharles Keepax 606ace6d144SCharles Keepax return -EAGAIN; 607ace6d144SCharles Keepax } 608ace6d144SCharles Keepax 609ace6d144SCharles Keepax /* 610ace6d144SCharles Keepax * This function will return the firmware to boot stage 2 from boot stage 3. 611ace6d144SCharles Keepax * Boot stage 2 is required to apply updates to the firmware. This is achieved 612ace6d144SCharles Keepax * by setting the firmware NEED configuration register to FW_PATCH_NEED_CFG, 613ace6d144SCharles Keepax * setting the HAVE configuration register to 0, and soft resetting. The 614ace6d144SCharles Keepax * firmware will see it is missing a patch configuration and will pause in boot 615ace6d144SCharles Keepax * stage 2. 616ace6d144SCharles Keepax * 617ace6d144SCharles Keepax * Note: Unlike cs42l43_mcu_stage_2_3 there is no need to consider the shadow 618ace6d144SCharles Keepax * register here as the driver will only return to boot stage 2 if the firmware 619ace6d144SCharles Keepax * requires update which means the revision does not include shadow register 620ace6d144SCharles Keepax * support. 621ace6d144SCharles Keepax */ 622ace6d144SCharles Keepax static int cs42l43_mcu_stage_3_2(struct cs42l43 *cs42l43) 623ace6d144SCharles Keepax { 624ace6d144SCharles Keepax regmap_write(cs42l43->regmap, CS42L43_FW_MISSION_CTRL_NEED_CONFIGS, 625ace6d144SCharles Keepax CS42L43_FW_PATCH_NEED_CFG_MASK); 626ace6d144SCharles Keepax regmap_write(cs42l43->regmap, CS42L43_FW_MISSION_CTRL_HAVE_CONFIGS, 0); 627ace6d144SCharles Keepax 628ace6d144SCharles Keepax return cs42l43_soft_reset(cs42l43); 629ace6d144SCharles Keepax } 630ace6d144SCharles Keepax 631ace6d144SCharles Keepax /* 632ace6d144SCharles Keepax * Disable the firmware running on the device such that the driver can access 633ace6d144SCharles Keepax * the registers without fear of the MCU changing them under it. 634ace6d144SCharles Keepax */ 635ace6d144SCharles Keepax static int cs42l43_mcu_disable(struct cs42l43 *cs42l43) 636ace6d144SCharles Keepax { 637ace6d144SCharles Keepax unsigned int val; 638ace6d144SCharles Keepax int ret; 639ace6d144SCharles Keepax 640ace6d144SCharles Keepax regmap_write(cs42l43->regmap, CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_REG, 641ace6d144SCharles Keepax CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_DISABLE_VAL); 642ace6d144SCharles Keepax regmap_write(cs42l43->regmap, CS42L43_FW_MISSION_CTRL_MM_CTRL_SELECTION, 643ace6d144SCharles Keepax CS42L43_FW_MM_CTRL_MCU_SEL_MASK); 644ace6d144SCharles Keepax regmap_write(cs42l43->regmap, CS42L43_MCU_SW_INTERRUPT, CS42L43_CONTROL_IND_MASK); 645ace6d144SCharles Keepax regmap_write(cs42l43->regmap, CS42L43_MCU_SW_INTERRUPT, 0); 646ace6d144SCharles Keepax 647ace6d144SCharles Keepax ret = regmap_read_poll_timeout(cs42l43->regmap, CS42L43_SOFT_INT_SHADOW, val, 648ace6d144SCharles Keepax (val & CS42L43_CONTROL_APPLIED_INT_MASK), 649ace6d144SCharles Keepax CS42L43_MCU_POLL, CS42L43_MCU_CMD_TIMEOUT); 650ace6d144SCharles Keepax if (ret) { 651ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to disable firmware: %d, 0x%x\n", ret, val); 652ace6d144SCharles Keepax return ret; 653ace6d144SCharles Keepax } 654ace6d144SCharles Keepax 655ace6d144SCharles Keepax /* Soft reset to clear any register state the firmware left behind. */ 656ace6d144SCharles Keepax return cs42l43_soft_reset(cs42l43); 657ace6d144SCharles Keepax } 658ace6d144SCharles Keepax 659ace6d144SCharles Keepax /* 660ace6d144SCharles Keepax * Callback to load firmware updates. 661ace6d144SCharles Keepax */ 662ace6d144SCharles Keepax static void cs42l43_mcu_load_firmware(const struct firmware *firmware, void *context) 663ace6d144SCharles Keepax { 664ace6d144SCharles Keepax struct cs42l43 *cs42l43 = context; 665ace6d144SCharles Keepax const struct cs42l43_patch_header *hdr; 666ace6d144SCharles Keepax unsigned int loadaddr, val; 667ace6d144SCharles Keepax int ret; 668ace6d144SCharles Keepax 669ace6d144SCharles Keepax if (!firmware) { 670ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to load firmware\n"); 671ace6d144SCharles Keepax cs42l43->firmware_error = -ENODEV; 672ace6d144SCharles Keepax goto err; 673ace6d144SCharles Keepax } 674ace6d144SCharles Keepax 675ace6d144SCharles Keepax hdr = (const struct cs42l43_patch_header *)&firmware->data[0]; 676ace6d144SCharles Keepax loadaddr = le32_to_cpu(hdr->load_addr); 677ace6d144SCharles Keepax 678ace6d144SCharles Keepax if (le16_to_cpu(hdr->version) != CS42L43_MCU_UPDATE_FORMAT) { 679ace6d144SCharles Keepax dev_err(cs42l43->dev, "Bad firmware file format: %d\n", hdr->version); 680ace6d144SCharles Keepax cs42l43->firmware_error = -EINVAL; 681ace6d144SCharles Keepax goto err_release; 682ace6d144SCharles Keepax } 683ace6d144SCharles Keepax 684ace6d144SCharles Keepax regmap_write(cs42l43->regmap, CS42L43_PATCH_START_ADDR, loadaddr); 685ace6d144SCharles Keepax regmap_bulk_write(cs42l43->regmap, loadaddr + CS42L43_MCU_UPDATE_OFFSET, 686ace6d144SCharles Keepax &firmware->data[0], firmware->size / sizeof(u32)); 687ace6d144SCharles Keepax 688ace6d144SCharles Keepax regmap_write(cs42l43->regmap, CS42L43_MCU_SW_INTERRUPT, CS42L43_PATCH_IND_MASK); 689ace6d144SCharles Keepax regmap_write(cs42l43->regmap, CS42L43_MCU_SW_INTERRUPT, 0); 690ace6d144SCharles Keepax 691ace6d144SCharles Keepax ret = regmap_read_poll_timeout(cs42l43->regmap, CS42L43_SOFT_INT_SHADOW, val, 692ace6d144SCharles Keepax (val & CS42L43_PATCH_APPLIED_INT_MASK), 693ace6d144SCharles Keepax CS42L43_MCU_POLL, CS42L43_MCU_UPDATE_TIMEOUT); 694ace6d144SCharles Keepax if (ret) { 695ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to update firmware: %d, 0x%x\n", ret, val); 696ace6d144SCharles Keepax cs42l43->firmware_error = ret; 697ace6d144SCharles Keepax goto err_release; 698ace6d144SCharles Keepax } 699ace6d144SCharles Keepax 700ace6d144SCharles Keepax err_release: 701ace6d144SCharles Keepax release_firmware(firmware); 702ace6d144SCharles Keepax err: 703ace6d144SCharles Keepax complete(&cs42l43->firmware_download); 704ace6d144SCharles Keepax } 705ace6d144SCharles Keepax 706ace6d144SCharles Keepax /* 707ace6d144SCharles Keepax * The process of updating the firmware is split into a series of steps, at the 708ace6d144SCharles Keepax * end of each step a soft reset of the device might be required which will 709ace6d144SCharles Keepax * require the driver to wait for the device to re-attach on the SoundWire bus, 710ace6d144SCharles Keepax * if that control bus is being used. 711ace6d144SCharles Keepax */ 712ace6d144SCharles Keepax static int cs42l43_mcu_update_step(struct cs42l43 *cs42l43) 713ace6d144SCharles Keepax { 714ace6d144SCharles Keepax unsigned int mcu_rev, bios_rev, boot_status, secure_cfg; 715ace6d144SCharles Keepax bool patched, shadow; 716ace6d144SCharles Keepax int ret; 717ace6d144SCharles Keepax 718ace6d144SCharles Keepax /* Clear any stale software interrupt bits. */ 719ace6d144SCharles Keepax regmap_read(cs42l43->regmap, CS42L43_SOFT_INT, &mcu_rev); 720ace6d144SCharles Keepax 721ace6d144SCharles Keepax ret = regmap_read(cs42l43->regmap, CS42L43_BOOT_STATUS, &boot_status); 722ace6d144SCharles Keepax if (ret) { 723ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to read boot status: %d\n", ret); 724ace6d144SCharles Keepax return ret; 725ace6d144SCharles Keepax } 726ace6d144SCharles Keepax 727ace6d144SCharles Keepax ret = regmap_read(cs42l43->regmap, CS42L43_MCU_SW_REV, &mcu_rev); 728ace6d144SCharles Keepax if (ret) { 729ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to read firmware revision: %d\n", ret); 730ace6d144SCharles Keepax return ret; 731ace6d144SCharles Keepax } 732ace6d144SCharles Keepax 733ace6d144SCharles Keepax bios_rev = (((mcu_rev & CS42L43_BIOS_MAJOR_REV_MASK) << 12) | 734ace6d144SCharles Keepax ((mcu_rev & CS42L43_BIOS_MINOR_REV_MASK) << 4) | 735ace6d144SCharles Keepax ((mcu_rev & CS42L43_BIOS_SUBMINOR_REV_MASK) >> 8)) >> 736ace6d144SCharles Keepax CS42L43_BIOS_MAJOR_REV_SHIFT; 737ace6d144SCharles Keepax mcu_rev = ((mcu_rev & CS42L43_FW_MAJOR_REV_MASK) << 12) | 738ace6d144SCharles Keepax ((mcu_rev & CS42L43_FW_MINOR_REV_MASK) << 4) | 739ace6d144SCharles Keepax ((mcu_rev & CS42L43_FW_SUBMINOR_REV_MASK) >> 8); 740ace6d144SCharles Keepax 741ace6d144SCharles Keepax /* 742ace6d144SCharles Keepax * The firmware has two revision numbers bringing either of them up to a 743ace6d144SCharles Keepax * supported version will provide the features the driver requires. 744ace6d144SCharles Keepax */ 745ace6d144SCharles Keepax patched = mcu_rev >= CS42L43_MCU_SUPPORTED_REV || 746ace6d144SCharles Keepax bios_rev >= CS42L43_MCU_SUPPORTED_BIOS_REV; 747ace6d144SCharles Keepax /* 748ace6d144SCharles Keepax * Later versions of the firmwware require the driver to access some 749ace6d144SCharles Keepax * features through a set of shadow registers. 750ace6d144SCharles Keepax */ 751ace6d144SCharles Keepax shadow = mcu_rev >= CS42L43_MCU_SHADOW_REGS_REQUIRED_REV; 752ace6d144SCharles Keepax 753ace6d144SCharles Keepax ret = regmap_read(cs42l43->regmap, CS42L43_BOOT_CONTROL, &secure_cfg); 754ace6d144SCharles Keepax if (ret) { 755ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to read security settings: %d\n", ret); 756ace6d144SCharles Keepax return ret; 757ace6d144SCharles Keepax } 758ace6d144SCharles Keepax 759ace6d144SCharles Keepax cs42l43->hw_lock = secure_cfg & CS42L43_LOCK_HW_STS_MASK; 760ace6d144SCharles Keepax 761ace6d144SCharles Keepax if (!patched && cs42l43->hw_lock) { 762ace6d144SCharles Keepax dev_err(cs42l43->dev, "Unpatched secure device\n"); 763ace6d144SCharles Keepax return -EPERM; 764ace6d144SCharles Keepax } 765ace6d144SCharles Keepax 766ace6d144SCharles Keepax dev_dbg(cs42l43->dev, "Firmware(0x%x, 0x%x) in boot stage %d\n", 767ace6d144SCharles Keepax mcu_rev, bios_rev, boot_status); 768ace6d144SCharles Keepax 769ace6d144SCharles Keepax switch (boot_status) { 770ace6d144SCharles Keepax case CS42L43_MCU_BOOT_STAGE2: 771ace6d144SCharles Keepax if (!patched) { 772ace6d144SCharles Keepax ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, 773ace6d144SCharles Keepax "cs42l43.bin", cs42l43->dev, 774ace6d144SCharles Keepax GFP_KERNEL, cs42l43, 775ace6d144SCharles Keepax cs42l43_mcu_load_firmware); 776ace6d144SCharles Keepax if (ret) { 777ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to request firmware: %d\n", ret); 778ace6d144SCharles Keepax return ret; 779ace6d144SCharles Keepax } 780ace6d144SCharles Keepax 781ace6d144SCharles Keepax wait_for_completion(&cs42l43->firmware_download); 782ace6d144SCharles Keepax 783ace6d144SCharles Keepax if (cs42l43->firmware_error) 784ace6d144SCharles Keepax return cs42l43->firmware_error; 785ace6d144SCharles Keepax 786ace6d144SCharles Keepax return -EAGAIN; 787ace6d144SCharles Keepax } else { 788ace6d144SCharles Keepax return cs42l43_mcu_stage_2_3(cs42l43, shadow); 789ace6d144SCharles Keepax } 790ace6d144SCharles Keepax case CS42L43_MCU_BOOT_STAGE3: 791ace6d144SCharles Keepax if (patched) 792ace6d144SCharles Keepax return cs42l43_mcu_disable(cs42l43); 793ace6d144SCharles Keepax else 794ace6d144SCharles Keepax return cs42l43_mcu_stage_3_2(cs42l43); 795ace6d144SCharles Keepax case CS42L43_MCU_BOOT_STAGE4: 796ace6d144SCharles Keepax return 0; 797ace6d144SCharles Keepax default: 798ace6d144SCharles Keepax dev_err(cs42l43->dev, "Invalid boot status: %d\n", boot_status); 799ace6d144SCharles Keepax return -EINVAL; 800ace6d144SCharles Keepax } 801ace6d144SCharles Keepax } 802ace6d144SCharles Keepax 803ace6d144SCharles Keepax /* 804ace6d144SCharles Keepax * Update the firmware running on the device. 805ace6d144SCharles Keepax */ 806ace6d144SCharles Keepax static int cs42l43_mcu_update(struct cs42l43 *cs42l43) 807ace6d144SCharles Keepax { 808ace6d144SCharles Keepax int i, ret; 809ace6d144SCharles Keepax 810ace6d144SCharles Keepax for (i = 0; i < CS42L43_MCU_UPDATE_RETRIES; i++) { 811ace6d144SCharles Keepax ret = cs42l43_mcu_update_step(cs42l43); 812ace6d144SCharles Keepax if (ret != -EAGAIN) 813ace6d144SCharles Keepax return ret; 814ace6d144SCharles Keepax 815ace6d144SCharles Keepax ret = cs42l43_wait_for_attach(cs42l43); 816ace6d144SCharles Keepax if (ret) 817ace6d144SCharles Keepax return ret; 818ace6d144SCharles Keepax } 819ace6d144SCharles Keepax 820ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed retrying update\n"); 821ace6d144SCharles Keepax return -ETIMEDOUT; 822ace6d144SCharles Keepax } 823ace6d144SCharles Keepax 824ace6d144SCharles Keepax static int cs42l43_irq_config(struct cs42l43 *cs42l43) 825ace6d144SCharles Keepax { 826ace6d144SCharles Keepax struct irq_data *irq_data; 827ace6d144SCharles Keepax unsigned long irq_flags; 828ace6d144SCharles Keepax int ret; 829ace6d144SCharles Keepax 830ace6d144SCharles Keepax if (cs42l43->sdw) 831ace6d144SCharles Keepax cs42l43->irq = cs42l43->sdw->irq; 832ace6d144SCharles Keepax 833ace6d144SCharles Keepax cs42l43->irq_chip = cs42l43_irq_chip; 834ace6d144SCharles Keepax cs42l43->irq_chip.irq_drv_data = cs42l43; 835ace6d144SCharles Keepax 836ace6d144SCharles Keepax irq_data = irq_get_irq_data(cs42l43->irq); 837ace6d144SCharles Keepax if (!irq_data) { 838ace6d144SCharles Keepax dev_err(cs42l43->dev, "Invalid IRQ: %d\n", cs42l43->irq); 839ace6d144SCharles Keepax return -EINVAL; 840ace6d144SCharles Keepax } 841ace6d144SCharles Keepax 842ace6d144SCharles Keepax irq_flags = irqd_get_trigger_type(irq_data); 843ace6d144SCharles Keepax switch (irq_flags) { 844ace6d144SCharles Keepax case IRQF_TRIGGER_LOW: 845ace6d144SCharles Keepax case IRQF_TRIGGER_HIGH: 846ace6d144SCharles Keepax case IRQF_TRIGGER_RISING: 847ace6d144SCharles Keepax case IRQF_TRIGGER_FALLING: 848ace6d144SCharles Keepax break; 849ace6d144SCharles Keepax case IRQ_TYPE_NONE: 850ace6d144SCharles Keepax default: 851ace6d144SCharles Keepax irq_flags = IRQF_TRIGGER_LOW; 852ace6d144SCharles Keepax break; 853ace6d144SCharles Keepax } 854ace6d144SCharles Keepax 855ace6d144SCharles Keepax irq_flags |= IRQF_ONESHOT; 856ace6d144SCharles Keepax 857ace6d144SCharles Keepax ret = devm_regmap_add_irq_chip(cs42l43->dev, cs42l43->regmap, 858ace6d144SCharles Keepax cs42l43->irq, irq_flags, 0, 859ace6d144SCharles Keepax &cs42l43->irq_chip, &cs42l43->irq_data); 860ace6d144SCharles Keepax if (ret) { 861ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to add IRQ chip: %d\n", ret); 862ace6d144SCharles Keepax return ret; 863ace6d144SCharles Keepax } 864ace6d144SCharles Keepax 865ace6d144SCharles Keepax dev_dbg(cs42l43->dev, "Configured IRQ %d with flags 0x%lx\n", 866ace6d144SCharles Keepax cs42l43->irq, irq_flags); 867ace6d144SCharles Keepax 868ace6d144SCharles Keepax return 0; 869ace6d144SCharles Keepax } 870ace6d144SCharles Keepax 871ace6d144SCharles Keepax static void cs42l43_boot_work(struct work_struct *work) 872ace6d144SCharles Keepax { 873ace6d144SCharles Keepax struct cs42l43 *cs42l43 = container_of(work, struct cs42l43, boot_work); 874ace6d144SCharles Keepax unsigned int devid, revid, otp; 875ace6d144SCharles Keepax int ret; 876ace6d144SCharles Keepax 877ace6d144SCharles Keepax ret = cs42l43_wait_for_attach(cs42l43); 878ace6d144SCharles Keepax if (ret) 879ace6d144SCharles Keepax goto err; 880ace6d144SCharles Keepax 881ace6d144SCharles Keepax ret = regmap_read(cs42l43->regmap, CS42L43_DEVID, &devid); 882ace6d144SCharles Keepax if (ret) { 883ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to read devid: %d\n", ret); 884ace6d144SCharles Keepax goto err; 885ace6d144SCharles Keepax } 886ace6d144SCharles Keepax 887ace6d144SCharles Keepax switch (devid) { 888ace6d144SCharles Keepax case CS42L43_DEVID_VAL: 889ace6d144SCharles Keepax break; 890ace6d144SCharles Keepax default: 891ace6d144SCharles Keepax dev_err(cs42l43->dev, "Unrecognised devid: 0x%06x\n", devid); 892ace6d144SCharles Keepax goto err; 893ace6d144SCharles Keepax } 894ace6d144SCharles Keepax 895ace6d144SCharles Keepax ret = regmap_read(cs42l43->regmap, CS42L43_REVID, &revid); 896ace6d144SCharles Keepax if (ret) { 897ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to read rev: %d\n", ret); 898ace6d144SCharles Keepax goto err; 899ace6d144SCharles Keepax } 900ace6d144SCharles Keepax 901ace6d144SCharles Keepax ret = regmap_read(cs42l43->regmap, CS42L43_OTP_REVISION_ID, &otp); 902ace6d144SCharles Keepax if (ret) { 903ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to read otp rev: %d\n", ret); 904ace6d144SCharles Keepax goto err; 905ace6d144SCharles Keepax } 906ace6d144SCharles Keepax 907ace6d144SCharles Keepax dev_info(cs42l43->dev, 908ace6d144SCharles Keepax "devid: 0x%06x, rev: 0x%02x, otp: 0x%02x\n", devid, revid, otp); 909ace6d144SCharles Keepax 910ace6d144SCharles Keepax ret = cs42l43_mcu_update(cs42l43); 911ace6d144SCharles Keepax if (ret) 912ace6d144SCharles Keepax goto err; 913ace6d144SCharles Keepax 914ace6d144SCharles Keepax ret = regmap_register_patch(cs42l43->regmap, cs42l43_reva_patch, 915ace6d144SCharles Keepax ARRAY_SIZE(cs42l43_reva_patch)); 916ace6d144SCharles Keepax if (ret) { 917ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to apply register patch: %d\n", ret); 918ace6d144SCharles Keepax goto err; 919ace6d144SCharles Keepax } 920ace6d144SCharles Keepax 921ace6d144SCharles Keepax ret = cs42l43_irq_config(cs42l43); 922ace6d144SCharles Keepax if (ret) 923ace6d144SCharles Keepax goto err; 924ace6d144SCharles Keepax 925ace6d144SCharles Keepax ret = devm_mfd_add_devices(cs42l43->dev, PLATFORM_DEVID_NONE, 926ace6d144SCharles Keepax cs42l43_devs, ARRAY_SIZE(cs42l43_devs), 927ace6d144SCharles Keepax NULL, 0, NULL); 928ace6d144SCharles Keepax if (ret) { 929ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to add subdevices: %d\n", ret); 930ace6d144SCharles Keepax goto err; 931ace6d144SCharles Keepax } 932ace6d144SCharles Keepax 933ace6d144SCharles Keepax pm_runtime_mark_last_busy(cs42l43->dev); 934ace6d144SCharles Keepax pm_runtime_put_autosuspend(cs42l43->dev); 935ace6d144SCharles Keepax 936ace6d144SCharles Keepax return; 937ace6d144SCharles Keepax 938ace6d144SCharles Keepax err: 939ace6d144SCharles Keepax pm_runtime_put_sync(cs42l43->dev); 940ace6d144SCharles Keepax cs42l43_dev_remove(cs42l43); 941ace6d144SCharles Keepax } 942ace6d144SCharles Keepax 943ace6d144SCharles Keepax static int cs42l43_power_up(struct cs42l43 *cs42l43) 944ace6d144SCharles Keepax { 945ace6d144SCharles Keepax int ret; 946ace6d144SCharles Keepax 947ace6d144SCharles Keepax ret = regulator_enable(cs42l43->vdd_p); 948ace6d144SCharles Keepax if (ret) { 949ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to enable vdd-p: %d\n", ret); 950ace6d144SCharles Keepax return ret; 951ace6d144SCharles Keepax } 952ace6d144SCharles Keepax 953ace6d144SCharles Keepax /* vdd-p must be on for 50uS before any other supply */ 954ace6d144SCharles Keepax usleep_range(CS42L43_VDDP_DELAY, 2 * CS42L43_VDDP_DELAY); 955ace6d144SCharles Keepax 956ace6d144SCharles Keepax gpiod_set_value_cansleep(cs42l43->reset, 1); 957ace6d144SCharles Keepax 958ace6d144SCharles Keepax ret = regulator_bulk_enable(CS42L43_N_SUPPLIES, cs42l43->core_supplies); 959ace6d144SCharles Keepax if (ret) { 960ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to enable core supplies: %d\n", ret); 961ace6d144SCharles Keepax goto err_reset; 962ace6d144SCharles Keepax } 963ace6d144SCharles Keepax 964ace6d144SCharles Keepax ret = regulator_enable(cs42l43->vdd_d); 965ace6d144SCharles Keepax if (ret) { 966ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to enable vdd-d: %d\n", ret); 967ace6d144SCharles Keepax goto err_core_supplies; 968ace6d144SCharles Keepax } 969ace6d144SCharles Keepax 970ace6d144SCharles Keepax usleep_range(CS42L43_VDDD_DELAY, 2 * CS42L43_VDDD_DELAY); 971ace6d144SCharles Keepax 972ace6d144SCharles Keepax return 0; 973ace6d144SCharles Keepax 974ace6d144SCharles Keepax err_core_supplies: 975ace6d144SCharles Keepax regulator_bulk_disable(CS42L43_N_SUPPLIES, cs42l43->core_supplies); 976ace6d144SCharles Keepax err_reset: 977ace6d144SCharles Keepax gpiod_set_value_cansleep(cs42l43->reset, 0); 978ace6d144SCharles Keepax regulator_disable(cs42l43->vdd_p); 979ace6d144SCharles Keepax 980ace6d144SCharles Keepax return ret; 981ace6d144SCharles Keepax } 982ace6d144SCharles Keepax 983ace6d144SCharles Keepax static int cs42l43_power_down(struct cs42l43 *cs42l43) 984ace6d144SCharles Keepax { 985ace6d144SCharles Keepax int ret; 986ace6d144SCharles Keepax 987ace6d144SCharles Keepax ret = regulator_disable(cs42l43->vdd_d); 988ace6d144SCharles Keepax if (ret) { 989ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to disable vdd-d: %d\n", ret); 990ace6d144SCharles Keepax return ret; 991ace6d144SCharles Keepax } 992ace6d144SCharles Keepax 993ace6d144SCharles Keepax ret = regulator_bulk_disable(CS42L43_N_SUPPLIES, cs42l43->core_supplies); 994ace6d144SCharles Keepax if (ret) { 995ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to disable core supplies: %d\n", ret); 996ace6d144SCharles Keepax return ret; 997ace6d144SCharles Keepax } 998ace6d144SCharles Keepax 999ace6d144SCharles Keepax gpiod_set_value_cansleep(cs42l43->reset, 0); 1000ace6d144SCharles Keepax 1001ace6d144SCharles Keepax ret = regulator_disable(cs42l43->vdd_p); 1002ace6d144SCharles Keepax if (ret) { 1003ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to disable vdd-p: %d\n", ret); 1004ace6d144SCharles Keepax return ret; 1005ace6d144SCharles Keepax } 1006ace6d144SCharles Keepax 1007ace6d144SCharles Keepax return 0; 1008ace6d144SCharles Keepax } 1009ace6d144SCharles Keepax 1010ace6d144SCharles Keepax int cs42l43_dev_probe(struct cs42l43 *cs42l43) 1011ace6d144SCharles Keepax { 1012ace6d144SCharles Keepax int i, ret; 1013ace6d144SCharles Keepax 1014ace6d144SCharles Keepax dev_set_drvdata(cs42l43->dev, cs42l43); 1015ace6d144SCharles Keepax 1016ace6d144SCharles Keepax mutex_init(&cs42l43->pll_lock); 1017ace6d144SCharles Keepax init_completion(&cs42l43->device_attach); 1018ace6d144SCharles Keepax init_completion(&cs42l43->device_detach); 1019ace6d144SCharles Keepax init_completion(&cs42l43->firmware_download); 1020ace6d144SCharles Keepax INIT_WORK(&cs42l43->boot_work, cs42l43_boot_work); 1021ace6d144SCharles Keepax 1022ace6d144SCharles Keepax regcache_cache_only(cs42l43->regmap, true); 1023ace6d144SCharles Keepax 1024ace6d144SCharles Keepax cs42l43->reset = devm_gpiod_get_optional(cs42l43->dev, "reset", GPIOD_OUT_LOW); 1025ace6d144SCharles Keepax if (IS_ERR(cs42l43->reset)) 1026ace6d144SCharles Keepax return dev_err_probe(cs42l43->dev, PTR_ERR(cs42l43->reset), 1027ace6d144SCharles Keepax "Failed to get reset\n"); 1028ace6d144SCharles Keepax 1029ace6d144SCharles Keepax cs42l43->vdd_p = devm_regulator_get(cs42l43->dev, "vdd-p"); 1030ace6d144SCharles Keepax if (IS_ERR(cs42l43->vdd_p)) 1031ace6d144SCharles Keepax return dev_err_probe(cs42l43->dev, PTR_ERR(cs42l43->vdd_p), 1032ace6d144SCharles Keepax "Failed to get vdd-p\n"); 1033ace6d144SCharles Keepax 1034ace6d144SCharles Keepax cs42l43->vdd_d = devm_regulator_get(cs42l43->dev, "vdd-d"); 1035ace6d144SCharles Keepax if (IS_ERR(cs42l43->vdd_d)) 1036ace6d144SCharles Keepax return dev_err_probe(cs42l43->dev, PTR_ERR(cs42l43->vdd_d), 1037ace6d144SCharles Keepax "Failed to get vdd-d\n"); 1038ace6d144SCharles Keepax 1039ace6d144SCharles Keepax BUILD_BUG_ON(ARRAY_SIZE(cs42l43_core_supplies) != CS42L43_N_SUPPLIES); 1040ace6d144SCharles Keepax 1041ace6d144SCharles Keepax for (i = 0; i < CS42L43_N_SUPPLIES; i++) 1042ace6d144SCharles Keepax cs42l43->core_supplies[i].supply = cs42l43_core_supplies[i]; 1043ace6d144SCharles Keepax 1044ace6d144SCharles Keepax ret = devm_regulator_bulk_get(cs42l43->dev, CS42L43_N_SUPPLIES, 1045ace6d144SCharles Keepax cs42l43->core_supplies); 1046ace6d144SCharles Keepax if (ret) 1047ace6d144SCharles Keepax return dev_err_probe(cs42l43->dev, ret, 1048ace6d144SCharles Keepax "Failed to get core supplies\n"); 1049ace6d144SCharles Keepax 1050ace6d144SCharles Keepax ret = cs42l43_power_up(cs42l43); 1051ace6d144SCharles Keepax if (ret) 1052ace6d144SCharles Keepax return ret; 1053ace6d144SCharles Keepax 1054ace6d144SCharles Keepax pm_runtime_set_autosuspend_delay(cs42l43->dev, CS42L43_AUTOSUSPEND_TIME); 1055ace6d144SCharles Keepax pm_runtime_use_autosuspend(cs42l43->dev); 1056ace6d144SCharles Keepax pm_runtime_set_active(cs42l43->dev); 1057ace6d144SCharles Keepax /* 1058ace6d144SCharles Keepax * The device is already powered up, but keep it from suspending until 1059ace6d144SCharles Keepax * the boot work runs. 1060ace6d144SCharles Keepax */ 1061ace6d144SCharles Keepax pm_runtime_get_noresume(cs42l43->dev); 1062ace6d144SCharles Keepax devm_pm_runtime_enable(cs42l43->dev); 1063ace6d144SCharles Keepax 1064ace6d144SCharles Keepax queue_work(system_long_wq, &cs42l43->boot_work); 1065ace6d144SCharles Keepax 1066ace6d144SCharles Keepax return 0; 1067ace6d144SCharles Keepax } 1068ace6d144SCharles Keepax EXPORT_SYMBOL_NS_GPL(cs42l43_dev_probe, MFD_CS42L43); 1069ace6d144SCharles Keepax 1070ace6d144SCharles Keepax void cs42l43_dev_remove(struct cs42l43 *cs42l43) 1071ace6d144SCharles Keepax { 1072ace6d144SCharles Keepax cs42l43_power_down(cs42l43); 1073ace6d144SCharles Keepax } 1074ace6d144SCharles Keepax EXPORT_SYMBOL_NS_GPL(cs42l43_dev_remove, MFD_CS42L43); 1075ace6d144SCharles Keepax 1076ace6d144SCharles Keepax static int cs42l43_suspend(struct device *dev) 1077ace6d144SCharles Keepax { 1078ace6d144SCharles Keepax struct cs42l43 *cs42l43 = dev_get_drvdata(dev); 1079ace6d144SCharles Keepax int ret; 1080ace6d144SCharles Keepax 1081ace6d144SCharles Keepax /* 1082ace6d144SCharles Keepax * Don't care about being resumed here, but the driver does want 1083ace6d144SCharles Keepax * force_resume to always trigger an actual resume, so that register 1084ace6d144SCharles Keepax * state for the MCU/GPIOs is returned as soon as possible after system 1085ace6d144SCharles Keepax * resume. force_resume will resume if the reference count is resumed on 1086ace6d144SCharles Keepax * suspend hence the get_noresume. 1087ace6d144SCharles Keepax */ 1088ace6d144SCharles Keepax pm_runtime_get_noresume(dev); 1089ace6d144SCharles Keepax 1090ace6d144SCharles Keepax ret = pm_runtime_force_suspend(dev); 1091ace6d144SCharles Keepax if (ret) { 1092ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to force suspend: %d\n", ret); 1093ace6d144SCharles Keepax pm_runtime_put_noidle(dev); 1094ace6d144SCharles Keepax return ret; 1095ace6d144SCharles Keepax } 1096ace6d144SCharles Keepax 1097ace6d144SCharles Keepax pm_runtime_put_noidle(dev); 1098ace6d144SCharles Keepax 1099ace6d144SCharles Keepax ret = cs42l43_power_down(cs42l43); 1100ace6d144SCharles Keepax if (ret) 1101ace6d144SCharles Keepax return ret; 1102ace6d144SCharles Keepax 1103ace6d144SCharles Keepax return 0; 1104ace6d144SCharles Keepax } 1105ace6d144SCharles Keepax 1106ace6d144SCharles Keepax static int cs42l43_resume(struct device *dev) 1107ace6d144SCharles Keepax { 1108ace6d144SCharles Keepax struct cs42l43 *cs42l43 = dev_get_drvdata(dev); 1109ace6d144SCharles Keepax int ret; 1110ace6d144SCharles Keepax 1111ace6d144SCharles Keepax ret = cs42l43_power_up(cs42l43); 1112ace6d144SCharles Keepax if (ret) 1113ace6d144SCharles Keepax return ret; 1114ace6d144SCharles Keepax 1115ace6d144SCharles Keepax ret = pm_runtime_force_resume(dev); 1116ace6d144SCharles Keepax if (ret) { 1117ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to force resume: %d\n", ret); 1118ace6d144SCharles Keepax return ret; 1119ace6d144SCharles Keepax } 1120ace6d144SCharles Keepax 1121ace6d144SCharles Keepax return 0; 1122ace6d144SCharles Keepax } 1123ace6d144SCharles Keepax 1124ace6d144SCharles Keepax static int cs42l43_runtime_suspend(struct device *dev) 1125ace6d144SCharles Keepax { 1126ace6d144SCharles Keepax struct cs42l43 *cs42l43 = dev_get_drvdata(dev); 1127ace6d144SCharles Keepax 1128ace6d144SCharles Keepax /* 1129ace6d144SCharles Keepax * Whilst the driver doesn't power the chip down here, going into runtime 1130ace6d144SCharles Keepax * suspend lets the SoundWire bus power down, which means the driver 1131ace6d144SCharles Keepax * can't communicate with the device any more. 1132ace6d144SCharles Keepax */ 1133ace6d144SCharles Keepax regcache_cache_only(cs42l43->regmap, true); 1134ace6d144SCharles Keepax 1135ace6d144SCharles Keepax return 0; 1136ace6d144SCharles Keepax } 1137ace6d144SCharles Keepax 1138ace6d144SCharles Keepax static int cs42l43_runtime_resume(struct device *dev) 1139ace6d144SCharles Keepax { 1140ace6d144SCharles Keepax struct cs42l43 *cs42l43 = dev_get_drvdata(dev); 1141ace6d144SCharles Keepax unsigned int reset_canary; 1142ace6d144SCharles Keepax int ret; 1143ace6d144SCharles Keepax 1144ace6d144SCharles Keepax ret = cs42l43_wait_for_attach(cs42l43); 1145ace6d144SCharles Keepax if (ret) 1146ace6d144SCharles Keepax return ret; 1147ace6d144SCharles Keepax 1148ace6d144SCharles Keepax ret = regmap_read(cs42l43->regmap, CS42L43_RELID, &reset_canary); 1149ace6d144SCharles Keepax if (ret) { 1150ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to check reset canary: %d\n", ret); 1151ace6d144SCharles Keepax goto err; 1152ace6d144SCharles Keepax } 1153ace6d144SCharles Keepax 1154ace6d144SCharles Keepax if (!reset_canary) { 1155ace6d144SCharles Keepax /* 1156ace6d144SCharles Keepax * If the canary has cleared the chip has reset, re-handle the 1157ace6d144SCharles Keepax * MCU and mark the cache as dirty to indicate the chip reset. 1158ace6d144SCharles Keepax */ 1159ace6d144SCharles Keepax ret = cs42l43_mcu_update(cs42l43); 1160ace6d144SCharles Keepax if (ret) 1161ace6d144SCharles Keepax goto err; 1162ace6d144SCharles Keepax 1163ace6d144SCharles Keepax regcache_mark_dirty(cs42l43->regmap); 1164ace6d144SCharles Keepax } 1165ace6d144SCharles Keepax 1166ace6d144SCharles Keepax ret = regcache_sync(cs42l43->regmap); 1167ace6d144SCharles Keepax if (ret) { 1168ace6d144SCharles Keepax dev_err(cs42l43->dev, "Failed to restore register cache: %d\n", ret); 1169ace6d144SCharles Keepax goto err; 1170ace6d144SCharles Keepax } 1171ace6d144SCharles Keepax 1172ace6d144SCharles Keepax return 0; 1173ace6d144SCharles Keepax 1174ace6d144SCharles Keepax err: 1175ace6d144SCharles Keepax regcache_cache_only(cs42l43->regmap, true); 1176ace6d144SCharles Keepax 1177ace6d144SCharles Keepax return ret; 1178ace6d144SCharles Keepax } 1179ace6d144SCharles Keepax 1180ace6d144SCharles Keepax EXPORT_NS_GPL_DEV_PM_OPS(cs42l43_pm_ops, MFD_CS42L43) = { 1181eb72d520SCharles Keepax SYSTEM_SLEEP_PM_OPS(cs42l43_suspend, cs42l43_resume) 1182eb72d520SCharles Keepax RUNTIME_PM_OPS(cs42l43_runtime_suspend, cs42l43_runtime_resume, NULL) 1183ace6d144SCharles Keepax }; 1184ace6d144SCharles Keepax 1185ace6d144SCharles Keepax MODULE_DESCRIPTION("CS42L43 Core Driver"); 1186ace6d144SCharles Keepax MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>"); 1187ace6d144SCharles Keepax MODULE_LICENSE("GPL"); 1188ace6d144SCharles Keepax MODULE_FIRMWARE("cs42l43.bin"); 1189