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