brintos

brintos / linux-shallow public Read only

0
0
Text · 36.5 KiB · ae8fd37 Raw
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