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