162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// cs35l41-lib.c -- CS35L41 Common functions for HDA and ASoC Audio drivers 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright 2017-2021 Cirrus Logic, Inc. 662306a36Sopenharmony_ci// 762306a36Sopenharmony_ci// Author: David Rhodes <david.rhodes@cirrus.com> 862306a36Sopenharmony_ci// Author: Lucas Tanure <lucas.tanure@cirrus.com> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/dev_printk.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/regmap.h> 1362306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1462306a36Sopenharmony_ci#include <linux/slab.h> 1562306a36Sopenharmony_ci#include <linux/firmware/cirrus/wmfw.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <sound/cs35l41.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic const struct reg_default cs35l41_reg[] = { 2062306a36Sopenharmony_ci { CS35L41_PWR_CTRL1, 0x00000000 }, 2162306a36Sopenharmony_ci { CS35L41_PWR_CTRL2, 0x00000000 }, 2262306a36Sopenharmony_ci { CS35L41_PWR_CTRL3, 0x01000010 }, 2362306a36Sopenharmony_ci { CS35L41_GPIO_PAD_CONTROL, 0x00000000 }, 2462306a36Sopenharmony_ci { CS35L41_GLOBAL_CLK_CTRL, 0x00000003 }, 2562306a36Sopenharmony_ci { CS35L41_TST_FS_MON0, 0x00020016 }, 2662306a36Sopenharmony_ci { CS35L41_BSTCVRT_COEFF, 0x00002424 }, 2762306a36Sopenharmony_ci { CS35L41_BSTCVRT_SLOPE_LBST, 0x00007500 }, 2862306a36Sopenharmony_ci { CS35L41_BSTCVRT_PEAK_CUR, 0x0000004A }, 2962306a36Sopenharmony_ci { CS35L41_SP_ENABLES, 0x00000000 }, 3062306a36Sopenharmony_ci { CS35L41_SP_RATE_CTRL, 0x00000028 }, 3162306a36Sopenharmony_ci { CS35L41_SP_FORMAT, 0x18180200 }, 3262306a36Sopenharmony_ci { CS35L41_SP_HIZ_CTRL, 0x00000002 }, 3362306a36Sopenharmony_ci { CS35L41_SP_FRAME_TX_SLOT, 0x03020100 }, 3462306a36Sopenharmony_ci { CS35L41_SP_FRAME_RX_SLOT, 0x00000100 }, 3562306a36Sopenharmony_ci { CS35L41_SP_TX_WL, 0x00000018 }, 3662306a36Sopenharmony_ci { CS35L41_SP_RX_WL, 0x00000018 }, 3762306a36Sopenharmony_ci { CS35L41_DAC_PCM1_SRC, 0x00000008 }, 3862306a36Sopenharmony_ci { CS35L41_ASP_TX1_SRC, 0x00000018 }, 3962306a36Sopenharmony_ci { CS35L41_ASP_TX2_SRC, 0x00000019 }, 4062306a36Sopenharmony_ci { CS35L41_ASP_TX3_SRC, 0x00000000 }, 4162306a36Sopenharmony_ci { CS35L41_ASP_TX4_SRC, 0x00000000 }, 4262306a36Sopenharmony_ci { CS35L41_DSP1_RX1_SRC, 0x00000008 }, 4362306a36Sopenharmony_ci { CS35L41_DSP1_RX2_SRC, 0x00000009 }, 4462306a36Sopenharmony_ci { CS35L41_DSP1_RX3_SRC, 0x00000018 }, 4562306a36Sopenharmony_ci { CS35L41_DSP1_RX4_SRC, 0x00000019 }, 4662306a36Sopenharmony_ci { CS35L41_DSP1_RX5_SRC, 0x00000020 }, 4762306a36Sopenharmony_ci { CS35L41_DSP1_RX6_SRC, 0x00000021 }, 4862306a36Sopenharmony_ci { CS35L41_DSP1_RX7_SRC, 0x0000003A }, 4962306a36Sopenharmony_ci { CS35L41_DSP1_RX8_SRC, 0x0000003B }, 5062306a36Sopenharmony_ci { CS35L41_NGATE1_SRC, 0x00000008 }, 5162306a36Sopenharmony_ci { CS35L41_NGATE2_SRC, 0x00000009 }, 5262306a36Sopenharmony_ci { CS35L41_AMP_DIG_VOL_CTRL, 0x00008000 }, 5362306a36Sopenharmony_ci { CS35L41_CLASSH_CFG, 0x000B0405 }, 5462306a36Sopenharmony_ci { CS35L41_WKFET_CFG, 0x00000111 }, 5562306a36Sopenharmony_ci { CS35L41_NG_CFG, 0x00000033 }, 5662306a36Sopenharmony_ci { CS35L41_AMP_GAIN_CTRL, 0x00000000 }, 5762306a36Sopenharmony_ci { CS35L41_IRQ1_MASK1, 0xFFFFFFFF }, 5862306a36Sopenharmony_ci { CS35L41_IRQ1_MASK2, 0xFFFFFFFF }, 5962306a36Sopenharmony_ci { CS35L41_IRQ1_MASK3, 0xFFFF87FF }, 6062306a36Sopenharmony_ci { CS35L41_IRQ1_MASK4, 0xFEFFFFFF }, 6162306a36Sopenharmony_ci { CS35L41_GPIO1_CTRL1, 0x81000001 }, 6262306a36Sopenharmony_ci { CS35L41_GPIO2_CTRL1, 0x81000001 }, 6362306a36Sopenharmony_ci { CS35L41_MIXER_NGATE_CFG, 0x00000000 }, 6462306a36Sopenharmony_ci { CS35L41_MIXER_NGATE_CH1_CFG, 0x00000303 }, 6562306a36Sopenharmony_ci { CS35L41_MIXER_NGATE_CH2_CFG, 0x00000303 }, 6662306a36Sopenharmony_ci { CS35L41_DSP1_CCM_CORE_CTRL, 0x00000101 }, 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic bool cs35l41_readable_reg(struct device *dev, unsigned int reg) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci switch (reg) { 7262306a36Sopenharmony_ci case CS35L41_DEVID: 7362306a36Sopenharmony_ci case CS35L41_REVID: 7462306a36Sopenharmony_ci case CS35L41_FABID: 7562306a36Sopenharmony_ci case CS35L41_RELID: 7662306a36Sopenharmony_ci case CS35L41_OTPID: 7762306a36Sopenharmony_ci case CS35L41_TEST_KEY_CTL: 7862306a36Sopenharmony_ci case CS35L41_USER_KEY_CTL: 7962306a36Sopenharmony_ci case CS35L41_OTP_CTRL0: 8062306a36Sopenharmony_ci case CS35L41_OTP_CTRL3: 8162306a36Sopenharmony_ci case CS35L41_OTP_CTRL4: 8262306a36Sopenharmony_ci case CS35L41_OTP_CTRL5: 8362306a36Sopenharmony_ci case CS35L41_OTP_CTRL6: 8462306a36Sopenharmony_ci case CS35L41_OTP_CTRL7: 8562306a36Sopenharmony_ci case CS35L41_OTP_CTRL8: 8662306a36Sopenharmony_ci case CS35L41_PWR_CTRL1: 8762306a36Sopenharmony_ci case CS35L41_PWR_CTRL2: 8862306a36Sopenharmony_ci case CS35L41_PWR_CTRL3: 8962306a36Sopenharmony_ci case CS35L41_CTRL_OVRRIDE: 9062306a36Sopenharmony_ci case CS35L41_AMP_OUT_MUTE: 9162306a36Sopenharmony_ci case CS35L41_PROTECT_REL_ERR_IGN: 9262306a36Sopenharmony_ci case CS35L41_GPIO_PAD_CONTROL: 9362306a36Sopenharmony_ci case CS35L41_JTAG_CONTROL: 9462306a36Sopenharmony_ci case CS35L41_PWRMGT_CTL: 9562306a36Sopenharmony_ci case CS35L41_WAKESRC_CTL: 9662306a36Sopenharmony_ci case CS35L41_PWRMGT_STS: 9762306a36Sopenharmony_ci case CS35L41_PLL_CLK_CTRL: 9862306a36Sopenharmony_ci case CS35L41_DSP_CLK_CTRL: 9962306a36Sopenharmony_ci case CS35L41_GLOBAL_CLK_CTRL: 10062306a36Sopenharmony_ci case CS35L41_DATA_FS_SEL: 10162306a36Sopenharmony_ci case CS35L41_TST_FS_MON0: 10262306a36Sopenharmony_ci case CS35L41_MDSYNC_EN: 10362306a36Sopenharmony_ci case CS35L41_MDSYNC_TX_ID: 10462306a36Sopenharmony_ci case CS35L41_MDSYNC_PWR_CTRL: 10562306a36Sopenharmony_ci case CS35L41_MDSYNC_DATA_TX: 10662306a36Sopenharmony_ci case CS35L41_MDSYNC_TX_STATUS: 10762306a36Sopenharmony_ci case CS35L41_MDSYNC_DATA_RX: 10862306a36Sopenharmony_ci case CS35L41_MDSYNC_RX_STATUS: 10962306a36Sopenharmony_ci case CS35L41_MDSYNC_ERR_STATUS: 11062306a36Sopenharmony_ci case CS35L41_MDSYNC_SYNC_PTE2: 11162306a36Sopenharmony_ci case CS35L41_MDSYNC_SYNC_PTE3: 11262306a36Sopenharmony_ci case CS35L41_MDSYNC_SYNC_MSM_STATUS: 11362306a36Sopenharmony_ci case CS35L41_BSTCVRT_VCTRL1: 11462306a36Sopenharmony_ci case CS35L41_BSTCVRT_VCTRL2: 11562306a36Sopenharmony_ci case CS35L41_BSTCVRT_PEAK_CUR: 11662306a36Sopenharmony_ci case CS35L41_BSTCVRT_SFT_RAMP: 11762306a36Sopenharmony_ci case CS35L41_BSTCVRT_COEFF: 11862306a36Sopenharmony_ci case CS35L41_BSTCVRT_SLOPE_LBST: 11962306a36Sopenharmony_ci case CS35L41_BSTCVRT_SW_FREQ: 12062306a36Sopenharmony_ci case CS35L41_BSTCVRT_DCM_CTRL: 12162306a36Sopenharmony_ci case CS35L41_BSTCVRT_DCM_MODE_FORCE: 12262306a36Sopenharmony_ci case CS35L41_BSTCVRT_OVERVOLT_CTRL: 12362306a36Sopenharmony_ci case CS35L41_VI_VOL_POL: 12462306a36Sopenharmony_ci case CS35L41_DTEMP_WARN_THLD: 12562306a36Sopenharmony_ci case CS35L41_DTEMP_CFG: 12662306a36Sopenharmony_ci case CS35L41_DTEMP_EN: 12762306a36Sopenharmony_ci case CS35L41_VPVBST_FS_SEL: 12862306a36Sopenharmony_ci case CS35L41_SP_ENABLES: 12962306a36Sopenharmony_ci case CS35L41_SP_RATE_CTRL: 13062306a36Sopenharmony_ci case CS35L41_SP_FORMAT: 13162306a36Sopenharmony_ci case CS35L41_SP_HIZ_CTRL: 13262306a36Sopenharmony_ci case CS35L41_SP_FRAME_TX_SLOT: 13362306a36Sopenharmony_ci case CS35L41_SP_FRAME_RX_SLOT: 13462306a36Sopenharmony_ci case CS35L41_SP_TX_WL: 13562306a36Sopenharmony_ci case CS35L41_SP_RX_WL: 13662306a36Sopenharmony_ci case CS35L41_DAC_PCM1_SRC: 13762306a36Sopenharmony_ci case CS35L41_ASP_TX1_SRC: 13862306a36Sopenharmony_ci case CS35L41_ASP_TX2_SRC: 13962306a36Sopenharmony_ci case CS35L41_ASP_TX3_SRC: 14062306a36Sopenharmony_ci case CS35L41_ASP_TX4_SRC: 14162306a36Sopenharmony_ci case CS35L41_DSP1_RX1_SRC: 14262306a36Sopenharmony_ci case CS35L41_DSP1_RX2_SRC: 14362306a36Sopenharmony_ci case CS35L41_DSP1_RX3_SRC: 14462306a36Sopenharmony_ci case CS35L41_DSP1_RX4_SRC: 14562306a36Sopenharmony_ci case CS35L41_DSP1_RX5_SRC: 14662306a36Sopenharmony_ci case CS35L41_DSP1_RX6_SRC: 14762306a36Sopenharmony_ci case CS35L41_DSP1_RX7_SRC: 14862306a36Sopenharmony_ci case CS35L41_DSP1_RX8_SRC: 14962306a36Sopenharmony_ci case CS35L41_NGATE1_SRC: 15062306a36Sopenharmony_ci case CS35L41_NGATE2_SRC: 15162306a36Sopenharmony_ci case CS35L41_AMP_DIG_VOL_CTRL: 15262306a36Sopenharmony_ci case CS35L41_VPBR_CFG: 15362306a36Sopenharmony_ci case CS35L41_VBBR_CFG: 15462306a36Sopenharmony_ci case CS35L41_VPBR_STATUS: 15562306a36Sopenharmony_ci case CS35L41_VBBR_STATUS: 15662306a36Sopenharmony_ci case CS35L41_OVERTEMP_CFG: 15762306a36Sopenharmony_ci case CS35L41_AMP_ERR_VOL: 15862306a36Sopenharmony_ci case CS35L41_VOL_STATUS_TO_DSP: 15962306a36Sopenharmony_ci case CS35L41_CLASSH_CFG: 16062306a36Sopenharmony_ci case CS35L41_WKFET_CFG: 16162306a36Sopenharmony_ci case CS35L41_NG_CFG: 16262306a36Sopenharmony_ci case CS35L41_AMP_GAIN_CTRL: 16362306a36Sopenharmony_ci case CS35L41_DAC_MSM_CFG: 16462306a36Sopenharmony_ci case CS35L41_IRQ1_CFG: 16562306a36Sopenharmony_ci case CS35L41_IRQ1_STATUS: 16662306a36Sopenharmony_ci case CS35L41_IRQ1_STATUS1: 16762306a36Sopenharmony_ci case CS35L41_IRQ1_STATUS2: 16862306a36Sopenharmony_ci case CS35L41_IRQ1_STATUS3: 16962306a36Sopenharmony_ci case CS35L41_IRQ1_STATUS4: 17062306a36Sopenharmony_ci case CS35L41_IRQ1_RAW_STATUS1: 17162306a36Sopenharmony_ci case CS35L41_IRQ1_RAW_STATUS2: 17262306a36Sopenharmony_ci case CS35L41_IRQ1_RAW_STATUS3: 17362306a36Sopenharmony_ci case CS35L41_IRQ1_RAW_STATUS4: 17462306a36Sopenharmony_ci case CS35L41_IRQ1_MASK1: 17562306a36Sopenharmony_ci case CS35L41_IRQ1_MASK2: 17662306a36Sopenharmony_ci case CS35L41_IRQ1_MASK3: 17762306a36Sopenharmony_ci case CS35L41_IRQ1_MASK4: 17862306a36Sopenharmony_ci case CS35L41_IRQ1_FRC1: 17962306a36Sopenharmony_ci case CS35L41_IRQ1_FRC2: 18062306a36Sopenharmony_ci case CS35L41_IRQ1_FRC3: 18162306a36Sopenharmony_ci case CS35L41_IRQ1_FRC4: 18262306a36Sopenharmony_ci case CS35L41_IRQ1_EDGE1: 18362306a36Sopenharmony_ci case CS35L41_IRQ1_EDGE4: 18462306a36Sopenharmony_ci case CS35L41_IRQ1_POL1: 18562306a36Sopenharmony_ci case CS35L41_IRQ1_POL2: 18662306a36Sopenharmony_ci case CS35L41_IRQ1_POL3: 18762306a36Sopenharmony_ci case CS35L41_IRQ1_POL4: 18862306a36Sopenharmony_ci case CS35L41_IRQ1_DB3: 18962306a36Sopenharmony_ci case CS35L41_IRQ2_CFG: 19062306a36Sopenharmony_ci case CS35L41_IRQ2_STATUS: 19162306a36Sopenharmony_ci case CS35L41_IRQ2_STATUS1: 19262306a36Sopenharmony_ci case CS35L41_IRQ2_STATUS2: 19362306a36Sopenharmony_ci case CS35L41_IRQ2_STATUS3: 19462306a36Sopenharmony_ci case CS35L41_IRQ2_STATUS4: 19562306a36Sopenharmony_ci case CS35L41_IRQ2_RAW_STATUS1: 19662306a36Sopenharmony_ci case CS35L41_IRQ2_RAW_STATUS2: 19762306a36Sopenharmony_ci case CS35L41_IRQ2_RAW_STATUS3: 19862306a36Sopenharmony_ci case CS35L41_IRQ2_RAW_STATUS4: 19962306a36Sopenharmony_ci case CS35L41_IRQ2_MASK1: 20062306a36Sopenharmony_ci case CS35L41_IRQ2_MASK2: 20162306a36Sopenharmony_ci case CS35L41_IRQ2_MASK3: 20262306a36Sopenharmony_ci case CS35L41_IRQ2_MASK4: 20362306a36Sopenharmony_ci case CS35L41_IRQ2_FRC1: 20462306a36Sopenharmony_ci case CS35L41_IRQ2_FRC2: 20562306a36Sopenharmony_ci case CS35L41_IRQ2_FRC3: 20662306a36Sopenharmony_ci case CS35L41_IRQ2_FRC4: 20762306a36Sopenharmony_ci case CS35L41_IRQ2_EDGE1: 20862306a36Sopenharmony_ci case CS35L41_IRQ2_EDGE4: 20962306a36Sopenharmony_ci case CS35L41_IRQ2_POL1: 21062306a36Sopenharmony_ci case CS35L41_IRQ2_POL2: 21162306a36Sopenharmony_ci case CS35L41_IRQ2_POL3: 21262306a36Sopenharmony_ci case CS35L41_IRQ2_POL4: 21362306a36Sopenharmony_ci case CS35L41_IRQ2_DB3: 21462306a36Sopenharmony_ci case CS35L41_GPIO_STATUS1: 21562306a36Sopenharmony_ci case CS35L41_GPIO1_CTRL1: 21662306a36Sopenharmony_ci case CS35L41_GPIO2_CTRL1: 21762306a36Sopenharmony_ci case CS35L41_MIXER_NGATE_CFG: 21862306a36Sopenharmony_ci case CS35L41_MIXER_NGATE_CH1_CFG: 21962306a36Sopenharmony_ci case CS35L41_MIXER_NGATE_CH2_CFG: 22062306a36Sopenharmony_ci case CS35L41_DSP_MBOX_1 ... CS35L41_DSP_VIRT2_MBOX_8: 22162306a36Sopenharmony_ci case CS35L41_CLOCK_DETECT_1: 22262306a36Sopenharmony_ci case CS35L41_DIE_STS1: 22362306a36Sopenharmony_ci case CS35L41_DIE_STS2: 22462306a36Sopenharmony_ci case CS35L41_TEMP_CAL1: 22562306a36Sopenharmony_ci case CS35L41_TEMP_CAL2: 22662306a36Sopenharmony_ci case CS35L41_DSP1_TIMESTAMP_COUNT: 22762306a36Sopenharmony_ci case CS35L41_DSP1_SYS_ID: 22862306a36Sopenharmony_ci case CS35L41_DSP1_SYS_VERSION: 22962306a36Sopenharmony_ci case CS35L41_DSP1_SYS_CORE_ID: 23062306a36Sopenharmony_ci case CS35L41_DSP1_SYS_AHB_ADDR: 23162306a36Sopenharmony_ci case CS35L41_DSP1_SYS_XSRAM_SIZE: 23262306a36Sopenharmony_ci case CS35L41_DSP1_SYS_YSRAM_SIZE: 23362306a36Sopenharmony_ci case CS35L41_DSP1_SYS_PSRAM_SIZE: 23462306a36Sopenharmony_ci case CS35L41_DSP1_SYS_PM_BOOT_SIZE: 23562306a36Sopenharmony_ci case CS35L41_DSP1_SYS_FEATURES: 23662306a36Sopenharmony_ci case CS35L41_DSP1_SYS_FIR_FILTERS: 23762306a36Sopenharmony_ci case CS35L41_DSP1_SYS_LMS_FILTERS: 23862306a36Sopenharmony_ci case CS35L41_DSP1_SYS_XM_BANK_SIZE: 23962306a36Sopenharmony_ci case CS35L41_DSP1_SYS_YM_BANK_SIZE: 24062306a36Sopenharmony_ci case CS35L41_DSP1_SYS_PM_BANK_SIZE: 24162306a36Sopenharmony_ci case CS35L41_DSP1_RX1_RATE: 24262306a36Sopenharmony_ci case CS35L41_DSP1_RX2_RATE: 24362306a36Sopenharmony_ci case CS35L41_DSP1_RX3_RATE: 24462306a36Sopenharmony_ci case CS35L41_DSP1_RX4_RATE: 24562306a36Sopenharmony_ci case CS35L41_DSP1_RX5_RATE: 24662306a36Sopenharmony_ci case CS35L41_DSP1_RX6_RATE: 24762306a36Sopenharmony_ci case CS35L41_DSP1_RX7_RATE: 24862306a36Sopenharmony_ci case CS35L41_DSP1_RX8_RATE: 24962306a36Sopenharmony_ci case CS35L41_DSP1_TX1_RATE: 25062306a36Sopenharmony_ci case CS35L41_DSP1_TX2_RATE: 25162306a36Sopenharmony_ci case CS35L41_DSP1_TX3_RATE: 25262306a36Sopenharmony_ci case CS35L41_DSP1_TX4_RATE: 25362306a36Sopenharmony_ci case CS35L41_DSP1_TX5_RATE: 25462306a36Sopenharmony_ci case CS35L41_DSP1_TX6_RATE: 25562306a36Sopenharmony_ci case CS35L41_DSP1_TX7_RATE: 25662306a36Sopenharmony_ci case CS35L41_DSP1_TX8_RATE: 25762306a36Sopenharmony_ci case CS35L41_DSP1_SCRATCH1: 25862306a36Sopenharmony_ci case CS35L41_DSP1_SCRATCH2: 25962306a36Sopenharmony_ci case CS35L41_DSP1_SCRATCH3: 26062306a36Sopenharmony_ci case CS35L41_DSP1_SCRATCH4: 26162306a36Sopenharmony_ci case CS35L41_DSP1_CCM_CORE_CTRL: 26262306a36Sopenharmony_ci case CS35L41_DSP1_CCM_CLK_OVERRIDE: 26362306a36Sopenharmony_ci case CS35L41_DSP1_XM_MSTR_EN: 26462306a36Sopenharmony_ci case CS35L41_DSP1_XM_CORE_PRI: 26562306a36Sopenharmony_ci case CS35L41_DSP1_XM_AHB_PACK_PL_PRI: 26662306a36Sopenharmony_ci case CS35L41_DSP1_XM_AHB_UP_PL_PRI: 26762306a36Sopenharmony_ci case CS35L41_DSP1_XM_ACCEL_PL0_PRI: 26862306a36Sopenharmony_ci case CS35L41_DSP1_XM_NPL0_PRI: 26962306a36Sopenharmony_ci case CS35L41_DSP1_YM_MSTR_EN: 27062306a36Sopenharmony_ci case CS35L41_DSP1_YM_CORE_PRI: 27162306a36Sopenharmony_ci case CS35L41_DSP1_YM_AHB_PACK_PL_PRI: 27262306a36Sopenharmony_ci case CS35L41_DSP1_YM_AHB_UP_PL_PRI: 27362306a36Sopenharmony_ci case CS35L41_DSP1_YM_ACCEL_PL0_PRI: 27462306a36Sopenharmony_ci case CS35L41_DSP1_YM_NPL0_PRI: 27562306a36Sopenharmony_ci case CS35L41_DSP1_MPU_XM_ACCESS0: 27662306a36Sopenharmony_ci case CS35L41_DSP1_MPU_YM_ACCESS0: 27762306a36Sopenharmony_ci case CS35L41_DSP1_MPU_WNDW_ACCESS0: 27862306a36Sopenharmony_ci case CS35L41_DSP1_MPU_XREG_ACCESS0: 27962306a36Sopenharmony_ci case CS35L41_DSP1_MPU_YREG_ACCESS0: 28062306a36Sopenharmony_ci case CS35L41_DSP1_MPU_XM_ACCESS1: 28162306a36Sopenharmony_ci case CS35L41_DSP1_MPU_YM_ACCESS1: 28262306a36Sopenharmony_ci case CS35L41_DSP1_MPU_WNDW_ACCESS1: 28362306a36Sopenharmony_ci case CS35L41_DSP1_MPU_XREG_ACCESS1: 28462306a36Sopenharmony_ci case CS35L41_DSP1_MPU_YREG_ACCESS1: 28562306a36Sopenharmony_ci case CS35L41_DSP1_MPU_XM_ACCESS2: 28662306a36Sopenharmony_ci case CS35L41_DSP1_MPU_YM_ACCESS2: 28762306a36Sopenharmony_ci case CS35L41_DSP1_MPU_WNDW_ACCESS2: 28862306a36Sopenharmony_ci case CS35L41_DSP1_MPU_XREG_ACCESS2: 28962306a36Sopenharmony_ci case CS35L41_DSP1_MPU_YREG_ACCESS2: 29062306a36Sopenharmony_ci case CS35L41_DSP1_MPU_XM_ACCESS3: 29162306a36Sopenharmony_ci case CS35L41_DSP1_MPU_YM_ACCESS3: 29262306a36Sopenharmony_ci case CS35L41_DSP1_MPU_WNDW_ACCESS3: 29362306a36Sopenharmony_ci case CS35L41_DSP1_MPU_XREG_ACCESS3: 29462306a36Sopenharmony_ci case CS35L41_DSP1_MPU_YREG_ACCESS3: 29562306a36Sopenharmony_ci case CS35L41_DSP1_MPU_XM_VIO_ADDR: 29662306a36Sopenharmony_ci case CS35L41_DSP1_MPU_XM_VIO_STATUS: 29762306a36Sopenharmony_ci case CS35L41_DSP1_MPU_YM_VIO_ADDR: 29862306a36Sopenharmony_ci case CS35L41_DSP1_MPU_YM_VIO_STATUS: 29962306a36Sopenharmony_ci case CS35L41_DSP1_MPU_PM_VIO_ADDR: 30062306a36Sopenharmony_ci case CS35L41_DSP1_MPU_PM_VIO_STATUS: 30162306a36Sopenharmony_ci case CS35L41_DSP1_MPU_LOCK_CONFIG: 30262306a36Sopenharmony_ci case CS35L41_DSP1_MPU_WDT_RST_CTRL: 30362306a36Sopenharmony_ci case CS35L41_OTP_TRIM_1: 30462306a36Sopenharmony_ci case CS35L41_OTP_TRIM_2: 30562306a36Sopenharmony_ci case CS35L41_OTP_TRIM_3: 30662306a36Sopenharmony_ci case CS35L41_OTP_TRIM_4: 30762306a36Sopenharmony_ci case CS35L41_OTP_TRIM_5: 30862306a36Sopenharmony_ci case CS35L41_OTP_TRIM_6: 30962306a36Sopenharmony_ci case CS35L41_OTP_TRIM_7: 31062306a36Sopenharmony_ci case CS35L41_OTP_TRIM_8: 31162306a36Sopenharmony_ci case CS35L41_OTP_TRIM_9: 31262306a36Sopenharmony_ci case CS35L41_OTP_TRIM_10: 31362306a36Sopenharmony_ci case CS35L41_OTP_TRIM_11: 31462306a36Sopenharmony_ci case CS35L41_OTP_TRIM_12: 31562306a36Sopenharmony_ci case CS35L41_OTP_TRIM_13: 31662306a36Sopenharmony_ci case CS35L41_OTP_TRIM_14: 31762306a36Sopenharmony_ci case CS35L41_OTP_TRIM_15: 31862306a36Sopenharmony_ci case CS35L41_OTP_TRIM_16: 31962306a36Sopenharmony_ci case CS35L41_OTP_TRIM_17: 32062306a36Sopenharmony_ci case CS35L41_OTP_TRIM_18: 32162306a36Sopenharmony_ci case CS35L41_OTP_TRIM_19: 32262306a36Sopenharmony_ci case CS35L41_OTP_TRIM_20: 32362306a36Sopenharmony_ci case CS35L41_OTP_TRIM_21: 32462306a36Sopenharmony_ci case CS35L41_OTP_TRIM_22: 32562306a36Sopenharmony_ci case CS35L41_OTP_TRIM_23: 32662306a36Sopenharmony_ci case CS35L41_OTP_TRIM_24: 32762306a36Sopenharmony_ci case CS35L41_OTP_TRIM_25: 32862306a36Sopenharmony_ci case CS35L41_OTP_TRIM_26: 32962306a36Sopenharmony_ci case CS35L41_OTP_TRIM_27: 33062306a36Sopenharmony_ci case CS35L41_OTP_TRIM_28: 33162306a36Sopenharmony_ci case CS35L41_OTP_TRIM_29: 33262306a36Sopenharmony_ci case CS35L41_OTP_TRIM_30: 33362306a36Sopenharmony_ci case CS35L41_OTP_TRIM_31: 33462306a36Sopenharmony_ci case CS35L41_OTP_TRIM_32: 33562306a36Sopenharmony_ci case CS35L41_OTP_TRIM_33: 33662306a36Sopenharmony_ci case CS35L41_OTP_TRIM_34: 33762306a36Sopenharmony_ci case CS35L41_OTP_TRIM_35: 33862306a36Sopenharmony_ci case CS35L41_OTP_TRIM_36: 33962306a36Sopenharmony_ci case CS35L41_OTP_MEM0 ... CS35L41_OTP_MEM31: 34062306a36Sopenharmony_ci case CS35L41_DSP1_XMEM_PACK_0 ... CS35L41_DSP1_XMEM_PACK_3068: 34162306a36Sopenharmony_ci case CS35L41_DSP1_XMEM_UNPACK32_0 ... CS35L41_DSP1_XMEM_UNPACK32_2046: 34262306a36Sopenharmony_ci case CS35L41_DSP1_XMEM_UNPACK24_0 ... CS35L41_DSP1_XMEM_UNPACK24_4093: 34362306a36Sopenharmony_ci case CS35L41_DSP1_YMEM_PACK_0 ... CS35L41_DSP1_YMEM_PACK_1532: 34462306a36Sopenharmony_ci case CS35L41_DSP1_YMEM_UNPACK32_0 ... CS35L41_DSP1_YMEM_UNPACK32_1022: 34562306a36Sopenharmony_ci case CS35L41_DSP1_YMEM_UNPACK24_0 ... CS35L41_DSP1_YMEM_UNPACK24_2045: 34662306a36Sopenharmony_ci case CS35L41_DSP1_PMEM_0 ... CS35L41_DSP1_PMEM_5114: 34762306a36Sopenharmony_ci /*test regs*/ 34862306a36Sopenharmony_ci case CS35L41_PLL_OVR: 34962306a36Sopenharmony_ci case CS35L41_BST_TEST_DUTY: 35062306a36Sopenharmony_ci case CS35L41_DIGPWM_IOCTRL: 35162306a36Sopenharmony_ci return true; 35262306a36Sopenharmony_ci default: 35362306a36Sopenharmony_ci return false; 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistatic bool cs35l41_precious_reg(struct device *dev, unsigned int reg) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci switch (reg) { 36062306a36Sopenharmony_ci case CS35L41_TEST_KEY_CTL: 36162306a36Sopenharmony_ci case CS35L41_USER_KEY_CTL: 36262306a36Sopenharmony_ci case CS35L41_OTP_MEM0 ... CS35L41_OTP_MEM31: 36362306a36Sopenharmony_ci case CS35L41_TST_FS_MON0: 36462306a36Sopenharmony_ci case CS35L41_DSP1_XMEM_PACK_0 ... CS35L41_DSP1_XMEM_PACK_3068: 36562306a36Sopenharmony_ci case CS35L41_DSP1_YMEM_PACK_0 ... CS35L41_DSP1_YMEM_PACK_1532: 36662306a36Sopenharmony_ci case CS35L41_DSP1_PMEM_0 ... CS35L41_DSP1_PMEM_5114: 36762306a36Sopenharmony_ci return true; 36862306a36Sopenharmony_ci default: 36962306a36Sopenharmony_ci return false; 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci} 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_cistatic bool cs35l41_volatile_reg(struct device *dev, unsigned int reg) 37462306a36Sopenharmony_ci{ 37562306a36Sopenharmony_ci switch (reg) { 37662306a36Sopenharmony_ci case CS35L41_DEVID: 37762306a36Sopenharmony_ci case CS35L41_SFT_RESET: 37862306a36Sopenharmony_ci case CS35L41_FABID: 37962306a36Sopenharmony_ci case CS35L41_REVID: 38062306a36Sopenharmony_ci case CS35L41_OTPID: 38162306a36Sopenharmony_ci case CS35L41_TEST_KEY_CTL: 38262306a36Sopenharmony_ci case CS35L41_USER_KEY_CTL: 38362306a36Sopenharmony_ci case CS35L41_PWRMGT_CTL: 38462306a36Sopenharmony_ci case CS35L41_WAKESRC_CTL: 38562306a36Sopenharmony_ci case CS35L41_PWRMGT_STS: 38662306a36Sopenharmony_ci case CS35L41_DTEMP_EN: 38762306a36Sopenharmony_ci case CS35L41_IRQ1_STATUS: 38862306a36Sopenharmony_ci case CS35L41_IRQ1_STATUS1: 38962306a36Sopenharmony_ci case CS35L41_IRQ1_STATUS2: 39062306a36Sopenharmony_ci case CS35L41_IRQ1_STATUS3: 39162306a36Sopenharmony_ci case CS35L41_IRQ1_STATUS4: 39262306a36Sopenharmony_ci case CS35L41_IRQ1_RAW_STATUS1: 39362306a36Sopenharmony_ci case CS35L41_IRQ1_RAW_STATUS2: 39462306a36Sopenharmony_ci case CS35L41_IRQ1_RAW_STATUS3: 39562306a36Sopenharmony_ci case CS35L41_IRQ1_RAW_STATUS4: 39662306a36Sopenharmony_ci case CS35L41_IRQ2_STATUS: 39762306a36Sopenharmony_ci case CS35L41_IRQ2_STATUS1: 39862306a36Sopenharmony_ci case CS35L41_IRQ2_STATUS2: 39962306a36Sopenharmony_ci case CS35L41_IRQ2_STATUS3: 40062306a36Sopenharmony_ci case CS35L41_IRQ2_STATUS4: 40162306a36Sopenharmony_ci case CS35L41_IRQ2_RAW_STATUS1: 40262306a36Sopenharmony_ci case CS35L41_IRQ2_RAW_STATUS2: 40362306a36Sopenharmony_ci case CS35L41_IRQ2_RAW_STATUS3: 40462306a36Sopenharmony_ci case CS35L41_IRQ2_RAW_STATUS4: 40562306a36Sopenharmony_ci case CS35L41_GPIO_STATUS1: 40662306a36Sopenharmony_ci case CS35L41_DSP_MBOX_1 ... CS35L41_DSP_VIRT2_MBOX_8: 40762306a36Sopenharmony_ci case CS35L41_DSP1_XMEM_PACK_0 ... CS35L41_DSP1_XMEM_PACK_3068: 40862306a36Sopenharmony_ci case CS35L41_DSP1_XMEM_UNPACK32_0 ... CS35L41_DSP1_XMEM_UNPACK32_2046: 40962306a36Sopenharmony_ci case CS35L41_DSP1_XMEM_UNPACK24_0 ... CS35L41_DSP1_XMEM_UNPACK24_4093: 41062306a36Sopenharmony_ci case CS35L41_DSP1_YMEM_PACK_0 ... CS35L41_DSP1_YMEM_PACK_1532: 41162306a36Sopenharmony_ci case CS35L41_DSP1_YMEM_UNPACK32_0 ... CS35L41_DSP1_YMEM_UNPACK32_1022: 41262306a36Sopenharmony_ci case CS35L41_DSP1_YMEM_UNPACK24_0 ... CS35L41_DSP1_YMEM_UNPACK24_2045: 41362306a36Sopenharmony_ci case CS35L41_DSP1_PMEM_0 ... CS35L41_DSP1_PMEM_5114: 41462306a36Sopenharmony_ci case CS35L41_DSP1_SCRATCH1: 41562306a36Sopenharmony_ci case CS35L41_DSP1_SCRATCH2: 41662306a36Sopenharmony_ci case CS35L41_DSP1_SCRATCH3: 41762306a36Sopenharmony_ci case CS35L41_DSP1_SCRATCH4: 41862306a36Sopenharmony_ci case CS35L41_DSP1_CCM_CLK_OVERRIDE ... CS35L41_DSP1_WDT_STATUS: 41962306a36Sopenharmony_ci case CS35L41_OTP_MEM0 ... CS35L41_OTP_MEM31: 42062306a36Sopenharmony_ci return true; 42162306a36Sopenharmony_ci default: 42262306a36Sopenharmony_ci return false; 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci} 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cistatic const struct cs35l41_otp_packed_element_t otp_map_1[] = { 42762306a36Sopenharmony_ci /* addr shift size */ 42862306a36Sopenharmony_ci { 0x00002030, 0, 4 }, /*TRIM_OSC_FREQ_TRIM*/ 42962306a36Sopenharmony_ci { 0x00002030, 7, 1 }, /*TRIM_OSC_TRIM_DONE*/ 43062306a36Sopenharmony_ci { 0x0000208c, 24, 6 }, /*TST_DIGREG_VREF_TRIM*/ 43162306a36Sopenharmony_ci { 0x00002090, 14, 4 }, /*TST_REF_TRIM*/ 43262306a36Sopenharmony_ci { 0x00002090, 10, 4 }, /*TST_REF_TEMPCO_TRIM*/ 43362306a36Sopenharmony_ci { 0x0000300C, 11, 4 }, /*PLL_LDOA_TST_VREF_TRIM*/ 43462306a36Sopenharmony_ci { 0x0000394C, 23, 2 }, /*BST_ATEST_CM_VOFF*/ 43562306a36Sopenharmony_ci { 0x00003950, 0, 7 }, /*BST_ATRIM_IADC_OFFSET*/ 43662306a36Sopenharmony_ci { 0x00003950, 8, 7 }, /*BST_ATRIM_IADC_GAIN1*/ 43762306a36Sopenharmony_ci { 0x00003950, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET1*/ 43862306a36Sopenharmony_ci { 0x00003950, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN1*/ 43962306a36Sopenharmony_ci { 0x00003954, 0, 7 }, /*BST_ATRIM_IADC_OFFSET2*/ 44062306a36Sopenharmony_ci { 0x00003954, 8, 7 }, /*BST_ATRIM_IADC_GAIN2*/ 44162306a36Sopenharmony_ci { 0x00003954, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET2*/ 44262306a36Sopenharmony_ci { 0x00003954, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN2*/ 44362306a36Sopenharmony_ci { 0x00003958, 0, 7 }, /*BST_ATRIM_IADC_OFFSET3*/ 44462306a36Sopenharmony_ci { 0x00003958, 8, 7 }, /*BST_ATRIM_IADC_GAIN3*/ 44562306a36Sopenharmony_ci { 0x00003958, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET3*/ 44662306a36Sopenharmony_ci { 0x00003958, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN3*/ 44762306a36Sopenharmony_ci { 0x0000395C, 0, 7 }, /*BST_ATRIM_IADC_OFFSET4*/ 44862306a36Sopenharmony_ci { 0x0000395C, 8, 7 }, /*BST_ATRIM_IADC_GAIN4*/ 44962306a36Sopenharmony_ci { 0x0000395C, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET4*/ 45062306a36Sopenharmony_ci { 0x0000395C, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN4*/ 45162306a36Sopenharmony_ci { 0x0000416C, 0, 8 }, /*VMON_GAIN_OTP_VAL*/ 45262306a36Sopenharmony_ci { 0x00004160, 0, 7 }, /*VMON_OFFSET_OTP_VAL*/ 45362306a36Sopenharmony_ci { 0x0000416C, 8, 8 }, /*IMON_GAIN_OTP_VAL*/ 45462306a36Sopenharmony_ci { 0x00004160, 16, 10 }, /*IMON_OFFSET_OTP_VAL*/ 45562306a36Sopenharmony_ci { 0x0000416C, 16, 12 }, /*VMON_CM_GAIN_OTP_VAL*/ 45662306a36Sopenharmony_ci { 0x0000416C, 28, 1 }, /*VMON_CM_GAIN_SIGN_OTP_VAL*/ 45762306a36Sopenharmony_ci { 0x00004170, 0, 6 }, /*IMON_CAL_TEMPCO_OTP_VAL*/ 45862306a36Sopenharmony_ci { 0x00004170, 6, 1 }, /*IMON_CAL_TEMPCO_SIGN_OTP*/ 45962306a36Sopenharmony_ci { 0x00004170, 8, 6 }, /*IMON_CAL_TEMPCO2_OTP_VAL*/ 46062306a36Sopenharmony_ci { 0x00004170, 14, 1 }, /*IMON_CAL_TEMPCO2_DN_UPB_OTP_VAL*/ 46162306a36Sopenharmony_ci { 0x00004170, 16, 9 }, /*IMON_CAL_TEMPCO_TBASE_OTP_VAL*/ 46262306a36Sopenharmony_ci { 0x00004360, 0, 5 }, /*TEMP_GAIN_OTP_VAL*/ 46362306a36Sopenharmony_ci { 0x00004360, 6, 9 }, /*TEMP_OFFSET_OTP_VAL*/ 46462306a36Sopenharmony_ci { 0x00004448, 0, 8 }, /*VP_SARADC_OFFSET*/ 46562306a36Sopenharmony_ci { 0x00004448, 8, 8 }, /*VP_GAIN_INDEX*/ 46662306a36Sopenharmony_ci { 0x00004448, 16, 8 }, /*VBST_SARADC_OFFSET*/ 46762306a36Sopenharmony_ci { 0x00004448, 24, 8 }, /*VBST_GAIN_INDEX*/ 46862306a36Sopenharmony_ci { 0x0000444C, 0, 3 }, /*ANA_SELINVREF*/ 46962306a36Sopenharmony_ci { 0x00006E30, 0, 5 }, /*GAIN_ERR_COEFF_0*/ 47062306a36Sopenharmony_ci { 0x00006E30, 8, 5 }, /*GAIN_ERR_COEFF_1*/ 47162306a36Sopenharmony_ci { 0x00006E30, 16, 5 }, /*GAIN_ERR_COEFF_2*/ 47262306a36Sopenharmony_ci { 0x00006E30, 24, 5 }, /*GAIN_ERR_COEFF_3*/ 47362306a36Sopenharmony_ci { 0x00006E34, 0, 5 }, /*GAIN_ERR_COEFF_4*/ 47462306a36Sopenharmony_ci { 0x00006E34, 8, 5 }, /*GAIN_ERR_COEFF_5*/ 47562306a36Sopenharmony_ci { 0x00006E34, 16, 5 }, /*GAIN_ERR_COEFF_6*/ 47662306a36Sopenharmony_ci { 0x00006E34, 24, 5 }, /*GAIN_ERR_COEFF_7*/ 47762306a36Sopenharmony_ci { 0x00006E38, 0, 5 }, /*GAIN_ERR_COEFF_8*/ 47862306a36Sopenharmony_ci { 0x00006E38, 8, 5 }, /*GAIN_ERR_COEFF_9*/ 47962306a36Sopenharmony_ci { 0x00006E38, 16, 5 }, /*GAIN_ERR_COEFF_10*/ 48062306a36Sopenharmony_ci { 0x00006E38, 24, 5 }, /*GAIN_ERR_COEFF_11*/ 48162306a36Sopenharmony_ci { 0x00006E3C, 0, 5 }, /*GAIN_ERR_COEFF_12*/ 48262306a36Sopenharmony_ci { 0x00006E3C, 8, 5 }, /*GAIN_ERR_COEFF_13*/ 48362306a36Sopenharmony_ci { 0x00006E3C, 16, 5 }, /*GAIN_ERR_COEFF_14*/ 48462306a36Sopenharmony_ci { 0x00006E3C, 24, 5 }, /*GAIN_ERR_COEFF_15*/ 48562306a36Sopenharmony_ci { 0x00006E40, 0, 5 }, /*GAIN_ERR_COEFF_16*/ 48662306a36Sopenharmony_ci { 0x00006E40, 8, 5 }, /*GAIN_ERR_COEFF_17*/ 48762306a36Sopenharmony_ci { 0x00006E40, 16, 5 }, /*GAIN_ERR_COEFF_18*/ 48862306a36Sopenharmony_ci { 0x00006E40, 24, 5 }, /*GAIN_ERR_COEFF_19*/ 48962306a36Sopenharmony_ci { 0x00006E44, 0, 5 }, /*GAIN_ERR_COEFF_20*/ 49062306a36Sopenharmony_ci { 0x00006E48, 0, 10 }, /*VOFF_GAIN_0*/ 49162306a36Sopenharmony_ci { 0x00006E48, 10, 10 }, /*VOFF_GAIN_1*/ 49262306a36Sopenharmony_ci { 0x00006E48, 20, 10 }, /*VOFF_GAIN_2*/ 49362306a36Sopenharmony_ci { 0x00006E4C, 0, 10 }, /*VOFF_GAIN_3*/ 49462306a36Sopenharmony_ci { 0x00006E4C, 10, 10 }, /*VOFF_GAIN_4*/ 49562306a36Sopenharmony_ci { 0x00006E4C, 20, 10 }, /*VOFF_GAIN_5*/ 49662306a36Sopenharmony_ci { 0x00006E50, 0, 10 }, /*VOFF_GAIN_6*/ 49762306a36Sopenharmony_ci { 0x00006E50, 10, 10 }, /*VOFF_GAIN_7*/ 49862306a36Sopenharmony_ci { 0x00006E50, 20, 10 }, /*VOFF_GAIN_8*/ 49962306a36Sopenharmony_ci { 0x00006E54, 0, 10 }, /*VOFF_GAIN_9*/ 50062306a36Sopenharmony_ci { 0x00006E54, 10, 10 }, /*VOFF_GAIN_10*/ 50162306a36Sopenharmony_ci { 0x00006E54, 20, 10 }, /*VOFF_GAIN_11*/ 50262306a36Sopenharmony_ci { 0x00006E58, 0, 10 }, /*VOFF_GAIN_12*/ 50362306a36Sopenharmony_ci { 0x00006E58, 10, 10 }, /*VOFF_GAIN_13*/ 50462306a36Sopenharmony_ci { 0x00006E58, 20, 10 }, /*VOFF_GAIN_14*/ 50562306a36Sopenharmony_ci { 0x00006E5C, 0, 10 }, /*VOFF_GAIN_15*/ 50662306a36Sopenharmony_ci { 0x00006E5C, 10, 10 }, /*VOFF_GAIN_16*/ 50762306a36Sopenharmony_ci { 0x00006E5C, 20, 10 }, /*VOFF_GAIN_17*/ 50862306a36Sopenharmony_ci { 0x00006E60, 0, 10 }, /*VOFF_GAIN_18*/ 50962306a36Sopenharmony_ci { 0x00006E60, 10, 10 }, /*VOFF_GAIN_19*/ 51062306a36Sopenharmony_ci { 0x00006E60, 20, 10 }, /*VOFF_GAIN_20*/ 51162306a36Sopenharmony_ci { 0x00006E64, 0, 10 }, /*VOFF_INT1*/ 51262306a36Sopenharmony_ci { 0x00007418, 7, 5 }, /*DS_SPK_INT1_CAP_TRIM*/ 51362306a36Sopenharmony_ci { 0x0000741C, 0, 5 }, /*DS_SPK_INT2_CAP_TRIM*/ 51462306a36Sopenharmony_ci { 0x0000741C, 11, 4 }, /*DS_SPK_LPF_CAP_TRIM*/ 51562306a36Sopenharmony_ci { 0x0000741C, 19, 4 }, /*DS_SPK_QUAN_CAP_TRIM*/ 51662306a36Sopenharmony_ci { 0x00007434, 17, 1 }, /*FORCE_CAL*/ 51762306a36Sopenharmony_ci { 0x00007434, 18, 7 }, /*CAL_OVERRIDE*/ 51862306a36Sopenharmony_ci { 0x00007068, 0, 9 }, /*MODIX*/ 51962306a36Sopenharmony_ci { 0x0000410C, 7, 1 }, /*VIMON_DLY_NOT_COMB*/ 52062306a36Sopenharmony_ci { 0x0000400C, 0, 7 }, /*VIMON_DLY*/ 52162306a36Sopenharmony_ci { 0x00000000, 0, 1 }, /*extra bit*/ 52262306a36Sopenharmony_ci { 0x00017040, 0, 8 }, /*X_COORDINATE*/ 52362306a36Sopenharmony_ci { 0x00017040, 8, 8 }, /*Y_COORDINATE*/ 52462306a36Sopenharmony_ci { 0x00017040, 16, 8 }, /*WAFER_ID*/ 52562306a36Sopenharmony_ci { 0x00017040, 24, 8 }, /*DVS*/ 52662306a36Sopenharmony_ci { 0x00017044, 0, 24 }, /*LOT_NUMBER*/ 52762306a36Sopenharmony_ci}; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cistatic const struct cs35l41_otp_packed_element_t otp_map_2[] = { 53062306a36Sopenharmony_ci /* addr shift size */ 53162306a36Sopenharmony_ci { 0x00002030, 0, 4 }, /*TRIM_OSC_FREQ_TRIM*/ 53262306a36Sopenharmony_ci { 0x00002030, 7, 1 }, /*TRIM_OSC_TRIM_DONE*/ 53362306a36Sopenharmony_ci { 0x0000208c, 24, 6 }, /*TST_DIGREG_VREF_TRIM*/ 53462306a36Sopenharmony_ci { 0x00002090, 14, 4 }, /*TST_REF_TRIM*/ 53562306a36Sopenharmony_ci { 0x00002090, 10, 4 }, /*TST_REF_TEMPCO_TRIM*/ 53662306a36Sopenharmony_ci { 0x0000300C, 11, 4 }, /*PLL_LDOA_TST_VREF_TRIM*/ 53762306a36Sopenharmony_ci { 0x0000394C, 23, 2 }, /*BST_ATEST_CM_VOFF*/ 53862306a36Sopenharmony_ci { 0x00003950, 0, 7 }, /*BST_ATRIM_IADC_OFFSET*/ 53962306a36Sopenharmony_ci { 0x00003950, 8, 7 }, /*BST_ATRIM_IADC_GAIN1*/ 54062306a36Sopenharmony_ci { 0x00003950, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET1*/ 54162306a36Sopenharmony_ci { 0x00003950, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN1*/ 54262306a36Sopenharmony_ci { 0x00003954, 0, 7 }, /*BST_ATRIM_IADC_OFFSET2*/ 54362306a36Sopenharmony_ci { 0x00003954, 8, 7 }, /*BST_ATRIM_IADC_GAIN2*/ 54462306a36Sopenharmony_ci { 0x00003954, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET2*/ 54562306a36Sopenharmony_ci { 0x00003954, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN2*/ 54662306a36Sopenharmony_ci { 0x00003958, 0, 7 }, /*BST_ATRIM_IADC_OFFSET3*/ 54762306a36Sopenharmony_ci { 0x00003958, 8, 7 }, /*BST_ATRIM_IADC_GAIN3*/ 54862306a36Sopenharmony_ci { 0x00003958, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET3*/ 54962306a36Sopenharmony_ci { 0x00003958, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN3*/ 55062306a36Sopenharmony_ci { 0x0000395C, 0, 7 }, /*BST_ATRIM_IADC_OFFSET4*/ 55162306a36Sopenharmony_ci { 0x0000395C, 8, 7 }, /*BST_ATRIM_IADC_GAIN4*/ 55262306a36Sopenharmony_ci { 0x0000395C, 16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET4*/ 55362306a36Sopenharmony_ci { 0x0000395C, 24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN4*/ 55462306a36Sopenharmony_ci { 0x0000416C, 0, 8 }, /*VMON_GAIN_OTP_VAL*/ 55562306a36Sopenharmony_ci { 0x00004160, 0, 7 }, /*VMON_OFFSET_OTP_VAL*/ 55662306a36Sopenharmony_ci { 0x0000416C, 8, 8 }, /*IMON_GAIN_OTP_VAL*/ 55762306a36Sopenharmony_ci { 0x00004160, 16, 10 }, /*IMON_OFFSET_OTP_VAL*/ 55862306a36Sopenharmony_ci { 0x0000416C, 16, 12 }, /*VMON_CM_GAIN_OTP_VAL*/ 55962306a36Sopenharmony_ci { 0x0000416C, 28, 1 }, /*VMON_CM_GAIN_SIGN_OTP_VAL*/ 56062306a36Sopenharmony_ci { 0x00004170, 0, 6 }, /*IMON_CAL_TEMPCO_OTP_VAL*/ 56162306a36Sopenharmony_ci { 0x00004170, 6, 1 }, /*IMON_CAL_TEMPCO_SIGN_OTP*/ 56262306a36Sopenharmony_ci { 0x00004170, 8, 6 }, /*IMON_CAL_TEMPCO2_OTP_VAL*/ 56362306a36Sopenharmony_ci { 0x00004170, 14, 1 }, /*IMON_CAL_TEMPCO2_DN_UPB_OTP_VAL*/ 56462306a36Sopenharmony_ci { 0x00004170, 16, 9 }, /*IMON_CAL_TEMPCO_TBASE_OTP_VAL*/ 56562306a36Sopenharmony_ci { 0x00004360, 0, 5 }, /*TEMP_GAIN_OTP_VAL*/ 56662306a36Sopenharmony_ci { 0x00004360, 6, 9 }, /*TEMP_OFFSET_OTP_VAL*/ 56762306a36Sopenharmony_ci { 0x00004448, 0, 8 }, /*VP_SARADC_OFFSET*/ 56862306a36Sopenharmony_ci { 0x00004448, 8, 8 }, /*VP_GAIN_INDEX*/ 56962306a36Sopenharmony_ci { 0x00004448, 16, 8 }, /*VBST_SARADC_OFFSET*/ 57062306a36Sopenharmony_ci { 0x00004448, 24, 8 }, /*VBST_GAIN_INDEX*/ 57162306a36Sopenharmony_ci { 0x0000444C, 0, 3 }, /*ANA_SELINVREF*/ 57262306a36Sopenharmony_ci { 0x00006E30, 0, 5 }, /*GAIN_ERR_COEFF_0*/ 57362306a36Sopenharmony_ci { 0x00006E30, 8, 5 }, /*GAIN_ERR_COEFF_1*/ 57462306a36Sopenharmony_ci { 0x00006E30, 16, 5 }, /*GAIN_ERR_COEFF_2*/ 57562306a36Sopenharmony_ci { 0x00006E30, 24, 5 }, /*GAIN_ERR_COEFF_3*/ 57662306a36Sopenharmony_ci { 0x00006E34, 0, 5 }, /*GAIN_ERR_COEFF_4*/ 57762306a36Sopenharmony_ci { 0x00006E34, 8, 5 }, /*GAIN_ERR_COEFF_5*/ 57862306a36Sopenharmony_ci { 0x00006E34, 16, 5 }, /*GAIN_ERR_COEFF_6*/ 57962306a36Sopenharmony_ci { 0x00006E34, 24, 5 }, /*GAIN_ERR_COEFF_7*/ 58062306a36Sopenharmony_ci { 0x00006E38, 0, 5 }, /*GAIN_ERR_COEFF_8*/ 58162306a36Sopenharmony_ci { 0x00006E38, 8, 5 }, /*GAIN_ERR_COEFF_9*/ 58262306a36Sopenharmony_ci { 0x00006E38, 16, 5 }, /*GAIN_ERR_COEFF_10*/ 58362306a36Sopenharmony_ci { 0x00006E38, 24, 5 }, /*GAIN_ERR_COEFF_11*/ 58462306a36Sopenharmony_ci { 0x00006E3C, 0, 5 }, /*GAIN_ERR_COEFF_12*/ 58562306a36Sopenharmony_ci { 0x00006E3C, 8, 5 }, /*GAIN_ERR_COEFF_13*/ 58662306a36Sopenharmony_ci { 0x00006E3C, 16, 5 }, /*GAIN_ERR_COEFF_14*/ 58762306a36Sopenharmony_ci { 0x00006E3C, 24, 5 }, /*GAIN_ERR_COEFF_15*/ 58862306a36Sopenharmony_ci { 0x00006E40, 0, 5 }, /*GAIN_ERR_COEFF_16*/ 58962306a36Sopenharmony_ci { 0x00006E40, 8, 5 }, /*GAIN_ERR_COEFF_17*/ 59062306a36Sopenharmony_ci { 0x00006E40, 16, 5 }, /*GAIN_ERR_COEFF_18*/ 59162306a36Sopenharmony_ci { 0x00006E40, 24, 5 }, /*GAIN_ERR_COEFF_19*/ 59262306a36Sopenharmony_ci { 0x00006E44, 0, 5 }, /*GAIN_ERR_COEFF_20*/ 59362306a36Sopenharmony_ci { 0x00006E48, 0, 10 }, /*VOFF_GAIN_0*/ 59462306a36Sopenharmony_ci { 0x00006E48, 10, 10 }, /*VOFF_GAIN_1*/ 59562306a36Sopenharmony_ci { 0x00006E48, 20, 10 }, /*VOFF_GAIN_2*/ 59662306a36Sopenharmony_ci { 0x00006E4C, 0, 10 }, /*VOFF_GAIN_3*/ 59762306a36Sopenharmony_ci { 0x00006E4C, 10, 10 }, /*VOFF_GAIN_4*/ 59862306a36Sopenharmony_ci { 0x00006E4C, 20, 10 }, /*VOFF_GAIN_5*/ 59962306a36Sopenharmony_ci { 0x00006E50, 0, 10 }, /*VOFF_GAIN_6*/ 60062306a36Sopenharmony_ci { 0x00006E50, 10, 10 }, /*VOFF_GAIN_7*/ 60162306a36Sopenharmony_ci { 0x00006E50, 20, 10 }, /*VOFF_GAIN_8*/ 60262306a36Sopenharmony_ci { 0x00006E54, 0, 10 }, /*VOFF_GAIN_9*/ 60362306a36Sopenharmony_ci { 0x00006E54, 10, 10 }, /*VOFF_GAIN_10*/ 60462306a36Sopenharmony_ci { 0x00006E54, 20, 10 }, /*VOFF_GAIN_11*/ 60562306a36Sopenharmony_ci { 0x00006E58, 0, 10 }, /*VOFF_GAIN_12*/ 60662306a36Sopenharmony_ci { 0x00006E58, 10, 10 }, /*VOFF_GAIN_13*/ 60762306a36Sopenharmony_ci { 0x00006E58, 20, 10 }, /*VOFF_GAIN_14*/ 60862306a36Sopenharmony_ci { 0x00006E5C, 0, 10 }, /*VOFF_GAIN_15*/ 60962306a36Sopenharmony_ci { 0x00006E5C, 10, 10 }, /*VOFF_GAIN_16*/ 61062306a36Sopenharmony_ci { 0x00006E5C, 20, 10 }, /*VOFF_GAIN_17*/ 61162306a36Sopenharmony_ci { 0x00006E60, 0, 10 }, /*VOFF_GAIN_18*/ 61262306a36Sopenharmony_ci { 0x00006E60, 10, 10 }, /*VOFF_GAIN_19*/ 61362306a36Sopenharmony_ci { 0x00006E60, 20, 10 }, /*VOFF_GAIN_20*/ 61462306a36Sopenharmony_ci { 0x00006E64, 0, 10 }, /*VOFF_INT1*/ 61562306a36Sopenharmony_ci { 0x00007418, 7, 5 }, /*DS_SPK_INT1_CAP_TRIM*/ 61662306a36Sopenharmony_ci { 0x0000741C, 0, 5 }, /*DS_SPK_INT2_CAP_TRIM*/ 61762306a36Sopenharmony_ci { 0x0000741C, 11, 4 }, /*DS_SPK_LPF_CAP_TRIM*/ 61862306a36Sopenharmony_ci { 0x0000741C, 19, 4 }, /*DS_SPK_QUAN_CAP_TRIM*/ 61962306a36Sopenharmony_ci { 0x00007434, 17, 1 }, /*FORCE_CAL*/ 62062306a36Sopenharmony_ci { 0x00007434, 18, 7 }, /*CAL_OVERRIDE*/ 62162306a36Sopenharmony_ci { 0x00007068, 0, 9 }, /*MODIX*/ 62262306a36Sopenharmony_ci { 0x0000410C, 7, 1 }, /*VIMON_DLY_NOT_COMB*/ 62362306a36Sopenharmony_ci { 0x0000400C, 0, 7 }, /*VIMON_DLY*/ 62462306a36Sopenharmony_ci { 0x00004000, 11, 1 }, /*VMON_POL*/ 62562306a36Sopenharmony_ci { 0x00017040, 0, 8 }, /*X_COORDINATE*/ 62662306a36Sopenharmony_ci { 0x00017040, 8, 8 }, /*Y_COORDINATE*/ 62762306a36Sopenharmony_ci { 0x00017040, 16, 8 }, /*WAFER_ID*/ 62862306a36Sopenharmony_ci { 0x00017040, 24, 8 }, /*DVS*/ 62962306a36Sopenharmony_ci { 0x00017044, 0, 24 }, /*LOT_NUMBER*/ 63062306a36Sopenharmony_ci}; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_cistatic const struct reg_sequence cs35l41_reva0_errata_patch[] = { 63362306a36Sopenharmony_ci { 0x00003854, 0x05180240 }, 63462306a36Sopenharmony_ci { CS35L41_VIMON_SPKMON_RESYNC, 0x00000000 }, 63562306a36Sopenharmony_ci { 0x00004310, 0x00000000 }, 63662306a36Sopenharmony_ci { CS35L41_VPVBST_FS_SEL, 0x00000000 }, 63762306a36Sopenharmony_ci { CS35L41_OTP_TRIM_30, 0x9091A1C8 }, 63862306a36Sopenharmony_ci { 0x00003014, 0x0200EE0E }, 63962306a36Sopenharmony_ci { CS35L41_BSTCVRT_DCM_CTRL, 0x00000051 }, 64062306a36Sopenharmony_ci { 0x00000054, 0x00000004 }, 64162306a36Sopenharmony_ci { CS35L41_IRQ1_DB3, 0x00000000 }, 64262306a36Sopenharmony_ci { CS35L41_IRQ2_DB3, 0x00000000 }, 64362306a36Sopenharmony_ci { CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 }, 64462306a36Sopenharmony_ci { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 }, 64562306a36Sopenharmony_ci { CS35L41_PWR_CTRL2, 0x00000000 }, 64662306a36Sopenharmony_ci { CS35L41_AMP_GAIN_CTRL, 0x00000000 }, 64762306a36Sopenharmony_ci { CS35L41_ASP_TX3_SRC, 0x00000000 }, 64862306a36Sopenharmony_ci { CS35L41_ASP_TX4_SRC, 0x00000000 }, 64962306a36Sopenharmony_ci}; 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_cistatic const struct reg_sequence cs35l41_revb0_errata_patch[] = { 65262306a36Sopenharmony_ci { CS35L41_VIMON_SPKMON_RESYNC, 0x00000000 }, 65362306a36Sopenharmony_ci { 0x00004310, 0x00000000 }, 65462306a36Sopenharmony_ci { CS35L41_VPVBST_FS_SEL, 0x00000000 }, 65562306a36Sopenharmony_ci { CS35L41_BSTCVRT_DCM_CTRL, 0x00000051 }, 65662306a36Sopenharmony_ci { CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 }, 65762306a36Sopenharmony_ci { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 }, 65862306a36Sopenharmony_ci { CS35L41_PWR_CTRL2, 0x00000000 }, 65962306a36Sopenharmony_ci { CS35L41_AMP_GAIN_CTRL, 0x00000000 }, 66062306a36Sopenharmony_ci { CS35L41_ASP_TX3_SRC, 0x00000000 }, 66162306a36Sopenharmony_ci { CS35L41_ASP_TX4_SRC, 0x00000000 }, 66262306a36Sopenharmony_ci}; 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_cistatic const struct reg_sequence cs35l41_revb2_errata_patch[] = { 66562306a36Sopenharmony_ci { CS35L41_VIMON_SPKMON_RESYNC, 0x00000000 }, 66662306a36Sopenharmony_ci { 0x00004310, 0x00000000 }, 66762306a36Sopenharmony_ci { CS35L41_VPVBST_FS_SEL, 0x00000000 }, 66862306a36Sopenharmony_ci { CS35L41_BSTCVRT_DCM_CTRL, 0x00000051 }, 66962306a36Sopenharmony_ci { CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 }, 67062306a36Sopenharmony_ci { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 }, 67162306a36Sopenharmony_ci { CS35L41_PWR_CTRL2, 0x00000000 }, 67262306a36Sopenharmony_ci { CS35L41_AMP_GAIN_CTRL, 0x00000000 }, 67362306a36Sopenharmony_ci { CS35L41_ASP_TX3_SRC, 0x00000000 }, 67462306a36Sopenharmony_ci { CS35L41_ASP_TX4_SRC, 0x00000000 }, 67562306a36Sopenharmony_ci}; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_cistatic const struct reg_sequence cs35l41_fs_errata_patch[] = { 67862306a36Sopenharmony_ci { CS35L41_DSP1_RX1_RATE, 0x00000001 }, 67962306a36Sopenharmony_ci { CS35L41_DSP1_RX2_RATE, 0x00000001 }, 68062306a36Sopenharmony_ci { CS35L41_DSP1_RX3_RATE, 0x00000001 }, 68162306a36Sopenharmony_ci { CS35L41_DSP1_RX4_RATE, 0x00000001 }, 68262306a36Sopenharmony_ci { CS35L41_DSP1_RX5_RATE, 0x00000001 }, 68362306a36Sopenharmony_ci { CS35L41_DSP1_RX6_RATE, 0x00000001 }, 68462306a36Sopenharmony_ci { CS35L41_DSP1_RX7_RATE, 0x00000001 }, 68562306a36Sopenharmony_ci { CS35L41_DSP1_RX8_RATE, 0x00000001 }, 68662306a36Sopenharmony_ci { CS35L41_DSP1_TX1_RATE, 0x00000001 }, 68762306a36Sopenharmony_ci { CS35L41_DSP1_TX2_RATE, 0x00000001 }, 68862306a36Sopenharmony_ci { CS35L41_DSP1_TX3_RATE, 0x00000001 }, 68962306a36Sopenharmony_ci { CS35L41_DSP1_TX4_RATE, 0x00000001 }, 69062306a36Sopenharmony_ci { CS35L41_DSP1_TX5_RATE, 0x00000001 }, 69162306a36Sopenharmony_ci { CS35L41_DSP1_TX6_RATE, 0x00000001 }, 69262306a36Sopenharmony_ci { CS35L41_DSP1_TX7_RATE, 0x00000001 }, 69362306a36Sopenharmony_ci { CS35L41_DSP1_TX8_RATE, 0x00000001 }, 69462306a36Sopenharmony_ci}; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_cistatic const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[] = { 69762306a36Sopenharmony_ci { 69862306a36Sopenharmony_ci .id = 0x01, 69962306a36Sopenharmony_ci .map = otp_map_1, 70062306a36Sopenharmony_ci .num_elements = ARRAY_SIZE(otp_map_1), 70162306a36Sopenharmony_ci .bit_offset = 16, 70262306a36Sopenharmony_ci .word_offset = 2, 70362306a36Sopenharmony_ci }, 70462306a36Sopenharmony_ci { 70562306a36Sopenharmony_ci .id = 0x02, 70662306a36Sopenharmony_ci .map = otp_map_2, 70762306a36Sopenharmony_ci .num_elements = ARRAY_SIZE(otp_map_2), 70862306a36Sopenharmony_ci .bit_offset = 16, 70962306a36Sopenharmony_ci .word_offset = 2, 71062306a36Sopenharmony_ci }, 71162306a36Sopenharmony_ci { 71262306a36Sopenharmony_ci .id = 0x03, 71362306a36Sopenharmony_ci .map = otp_map_2, 71462306a36Sopenharmony_ci .num_elements = ARRAY_SIZE(otp_map_2), 71562306a36Sopenharmony_ci .bit_offset = 16, 71662306a36Sopenharmony_ci .word_offset = 2, 71762306a36Sopenharmony_ci }, 71862306a36Sopenharmony_ci { 71962306a36Sopenharmony_ci .id = 0x06, 72062306a36Sopenharmony_ci .map = otp_map_2, 72162306a36Sopenharmony_ci .num_elements = ARRAY_SIZE(otp_map_2), 72262306a36Sopenharmony_ci .bit_offset = 16, 72362306a36Sopenharmony_ci .word_offset = 2, 72462306a36Sopenharmony_ci }, 72562306a36Sopenharmony_ci { 72662306a36Sopenharmony_ci .id = 0x08, 72762306a36Sopenharmony_ci .map = otp_map_1, 72862306a36Sopenharmony_ci .num_elements = ARRAY_SIZE(otp_map_1), 72962306a36Sopenharmony_ci .bit_offset = 16, 73062306a36Sopenharmony_ci .word_offset = 2, 73162306a36Sopenharmony_ci }, 73262306a36Sopenharmony_ci}; 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_cistruct regmap_config cs35l41_regmap_i2c = { 73562306a36Sopenharmony_ci .reg_bits = 32, 73662306a36Sopenharmony_ci .val_bits = 32, 73762306a36Sopenharmony_ci .reg_stride = CS35L41_REGSTRIDE, 73862306a36Sopenharmony_ci .reg_format_endian = REGMAP_ENDIAN_BIG, 73962306a36Sopenharmony_ci .val_format_endian = REGMAP_ENDIAN_BIG, 74062306a36Sopenharmony_ci .max_register = CS35L41_LASTREG, 74162306a36Sopenharmony_ci .reg_defaults = cs35l41_reg, 74262306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(cs35l41_reg), 74362306a36Sopenharmony_ci .volatile_reg = cs35l41_volatile_reg, 74462306a36Sopenharmony_ci .readable_reg = cs35l41_readable_reg, 74562306a36Sopenharmony_ci .precious_reg = cs35l41_precious_reg, 74662306a36Sopenharmony_ci .cache_type = REGCACHE_MAPLE, 74762306a36Sopenharmony_ci}; 74862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_regmap_i2c); 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_cistruct regmap_config cs35l41_regmap_spi = { 75162306a36Sopenharmony_ci .reg_bits = 32, 75262306a36Sopenharmony_ci .val_bits = 32, 75362306a36Sopenharmony_ci .pad_bits = 16, 75462306a36Sopenharmony_ci .reg_stride = CS35L41_REGSTRIDE, 75562306a36Sopenharmony_ci .reg_format_endian = REGMAP_ENDIAN_BIG, 75662306a36Sopenharmony_ci .val_format_endian = REGMAP_ENDIAN_BIG, 75762306a36Sopenharmony_ci .max_register = CS35L41_LASTREG, 75862306a36Sopenharmony_ci .reg_defaults = cs35l41_reg, 75962306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(cs35l41_reg), 76062306a36Sopenharmony_ci .volatile_reg = cs35l41_volatile_reg, 76162306a36Sopenharmony_ci .readable_reg = cs35l41_readable_reg, 76262306a36Sopenharmony_ci .precious_reg = cs35l41_precious_reg, 76362306a36Sopenharmony_ci .cache_type = REGCACHE_MAPLE, 76462306a36Sopenharmony_ci}; 76562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_regmap_spi); 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_cistatic const struct cs35l41_otp_map_element_t *cs35l41_find_otp_map(u32 otp_id) 76862306a36Sopenharmony_ci{ 76962306a36Sopenharmony_ci int i; 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(cs35l41_otp_map_map); i++) { 77262306a36Sopenharmony_ci if (cs35l41_otp_map_map[i].id == otp_id) 77362306a36Sopenharmony_ci return &cs35l41_otp_map_map[i]; 77462306a36Sopenharmony_ci } 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci return NULL; 77762306a36Sopenharmony_ci} 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ciint cs35l41_test_key_unlock(struct device *dev, struct regmap *regmap) 78062306a36Sopenharmony_ci{ 78162306a36Sopenharmony_ci static const struct reg_sequence unlock[] = { 78262306a36Sopenharmony_ci { CS35L41_TEST_KEY_CTL, 0x00000055 }, 78362306a36Sopenharmony_ci { CS35L41_TEST_KEY_CTL, 0x000000AA }, 78462306a36Sopenharmony_ci }; 78562306a36Sopenharmony_ci int ret; 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci ret = regmap_multi_reg_write(regmap, unlock, ARRAY_SIZE(unlock)); 78862306a36Sopenharmony_ci if (ret) 78962306a36Sopenharmony_ci dev_err(dev, "Failed to unlock test key: %d\n", ret); 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci return ret; 79262306a36Sopenharmony_ci} 79362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_test_key_unlock); 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ciint cs35l41_test_key_lock(struct device *dev, struct regmap *regmap) 79662306a36Sopenharmony_ci{ 79762306a36Sopenharmony_ci static const struct reg_sequence unlock[] = { 79862306a36Sopenharmony_ci { CS35L41_TEST_KEY_CTL, 0x000000CC }, 79962306a36Sopenharmony_ci { CS35L41_TEST_KEY_CTL, 0x00000033 }, 80062306a36Sopenharmony_ci }; 80162306a36Sopenharmony_ci int ret; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci ret = regmap_multi_reg_write(regmap, unlock, ARRAY_SIZE(unlock)); 80462306a36Sopenharmony_ci if (ret) 80562306a36Sopenharmony_ci dev_err(dev, "Failed to lock test key: %d\n", ret); 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci return ret; 80862306a36Sopenharmony_ci} 80962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_test_key_lock); 81062306a36Sopenharmony_ci 81162306a36Sopenharmony_ci/* Must be called with the TEST_KEY unlocked */ 81262306a36Sopenharmony_ciint cs35l41_otp_unpack(struct device *dev, struct regmap *regmap) 81362306a36Sopenharmony_ci{ 81462306a36Sopenharmony_ci const struct cs35l41_otp_map_element_t *otp_map_match; 81562306a36Sopenharmony_ci const struct cs35l41_otp_packed_element_t *otp_map; 81662306a36Sopenharmony_ci int bit_offset, word_offset, ret, i; 81762306a36Sopenharmony_ci unsigned int bit_sum = 8; 81862306a36Sopenharmony_ci u32 otp_val, otp_id_reg; 81962306a36Sopenharmony_ci u32 *otp_mem; 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci otp_mem = kmalloc_array(CS35L41_OTP_SIZE_WORDS, sizeof(*otp_mem), GFP_KERNEL); 82262306a36Sopenharmony_ci if (!otp_mem) 82362306a36Sopenharmony_ci return -ENOMEM; 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci ret = regmap_read(regmap, CS35L41_OTPID, &otp_id_reg); 82662306a36Sopenharmony_ci if (ret) { 82762306a36Sopenharmony_ci dev_err(dev, "Read OTP ID failed: %d\n", ret); 82862306a36Sopenharmony_ci goto err_otp_unpack; 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci otp_map_match = cs35l41_find_otp_map(otp_id_reg); 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci if (!otp_map_match) { 83462306a36Sopenharmony_ci dev_err(dev, "OTP Map matching ID %d not found\n", otp_id_reg); 83562306a36Sopenharmony_ci ret = -EINVAL; 83662306a36Sopenharmony_ci goto err_otp_unpack; 83762306a36Sopenharmony_ci } 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci ret = regmap_bulk_read(regmap, CS35L41_OTP_MEM0, otp_mem, CS35L41_OTP_SIZE_WORDS); 84062306a36Sopenharmony_ci if (ret) { 84162306a36Sopenharmony_ci dev_err(dev, "Read OTP Mem failed: %d\n", ret); 84262306a36Sopenharmony_ci goto err_otp_unpack; 84362306a36Sopenharmony_ci } 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci otp_map = otp_map_match->map; 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci bit_offset = otp_map_match->bit_offset; 84862306a36Sopenharmony_ci word_offset = otp_map_match->word_offset; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci for (i = 0; i < otp_map_match->num_elements; i++) { 85162306a36Sopenharmony_ci dev_dbg(dev, "bitoffset= %d, word_offset=%d, bit_sum mod 32=%d, otp_map[i].size = %u\n", 85262306a36Sopenharmony_ci bit_offset, word_offset, bit_sum % 32, otp_map[i].size); 85362306a36Sopenharmony_ci if (bit_offset + otp_map[i].size - 1 >= 32) { 85462306a36Sopenharmony_ci otp_val = (otp_mem[word_offset] & 85562306a36Sopenharmony_ci GENMASK(31, bit_offset)) >> bit_offset; 85662306a36Sopenharmony_ci otp_val |= (otp_mem[++word_offset] & 85762306a36Sopenharmony_ci GENMASK(bit_offset + otp_map[i].size - 33, 0)) << 85862306a36Sopenharmony_ci (32 - bit_offset); 85962306a36Sopenharmony_ci bit_offset += otp_map[i].size - 32; 86062306a36Sopenharmony_ci } else if (bit_offset + otp_map[i].size - 1 >= 0) { 86162306a36Sopenharmony_ci otp_val = (otp_mem[word_offset] & 86262306a36Sopenharmony_ci GENMASK(bit_offset + otp_map[i].size - 1, bit_offset) 86362306a36Sopenharmony_ci ) >> bit_offset; 86462306a36Sopenharmony_ci bit_offset += otp_map[i].size; 86562306a36Sopenharmony_ci } else /* both bit_offset and otp_map[i].size are 0 */ 86662306a36Sopenharmony_ci otp_val = 0; 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci bit_sum += otp_map[i].size; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci if (bit_offset == 32) { 87162306a36Sopenharmony_ci bit_offset = 0; 87262306a36Sopenharmony_ci word_offset++; 87362306a36Sopenharmony_ci } 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci if (otp_map[i].reg != 0) { 87662306a36Sopenharmony_ci ret = regmap_update_bits(regmap, otp_map[i].reg, 87762306a36Sopenharmony_ci GENMASK(otp_map[i].shift + otp_map[i].size - 1, 87862306a36Sopenharmony_ci otp_map[i].shift), 87962306a36Sopenharmony_ci otp_val << otp_map[i].shift); 88062306a36Sopenharmony_ci if (ret < 0) { 88162306a36Sopenharmony_ci dev_err(dev, "Write OTP val failed: %d\n", ret); 88262306a36Sopenharmony_ci goto err_otp_unpack; 88362306a36Sopenharmony_ci } 88462306a36Sopenharmony_ci } 88562306a36Sopenharmony_ci } 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci ret = 0; 88862306a36Sopenharmony_ci 88962306a36Sopenharmony_cierr_otp_unpack: 89062306a36Sopenharmony_ci kfree(otp_mem); 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci return ret; 89362306a36Sopenharmony_ci} 89462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_otp_unpack); 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci/* Must be called with the TEST_KEY unlocked */ 89762306a36Sopenharmony_ciint cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsigned int reg_revid) 89862306a36Sopenharmony_ci{ 89962306a36Sopenharmony_ci char *rev; 90062306a36Sopenharmony_ci int ret; 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci switch (reg_revid) { 90362306a36Sopenharmony_ci case CS35L41_REVID_A0: 90462306a36Sopenharmony_ci ret = regmap_register_patch(reg, cs35l41_reva0_errata_patch, 90562306a36Sopenharmony_ci ARRAY_SIZE(cs35l41_reva0_errata_patch)); 90662306a36Sopenharmony_ci rev = "A0"; 90762306a36Sopenharmony_ci break; 90862306a36Sopenharmony_ci case CS35L41_REVID_B0: 90962306a36Sopenharmony_ci ret = regmap_register_patch(reg, cs35l41_revb0_errata_patch, 91062306a36Sopenharmony_ci ARRAY_SIZE(cs35l41_revb0_errata_patch)); 91162306a36Sopenharmony_ci rev = "B0"; 91262306a36Sopenharmony_ci break; 91362306a36Sopenharmony_ci case CS35L41_REVID_B2: 91462306a36Sopenharmony_ci ret = regmap_register_patch(reg, cs35l41_revb2_errata_patch, 91562306a36Sopenharmony_ci ARRAY_SIZE(cs35l41_revb2_errata_patch)); 91662306a36Sopenharmony_ci rev = "B2"; 91762306a36Sopenharmony_ci break; 91862306a36Sopenharmony_ci default: 91962306a36Sopenharmony_ci ret = -EINVAL; 92062306a36Sopenharmony_ci rev = "XX"; 92162306a36Sopenharmony_ci break; 92262306a36Sopenharmony_ci } 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci if (ret) 92562306a36Sopenharmony_ci dev_err(dev, "Failed to apply %s errata patch: %d\n", rev, ret); 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci ret = regmap_write(reg, CS35L41_DSP1_CCM_CORE_CTRL, 0); 92862306a36Sopenharmony_ci if (ret < 0) 92962306a36Sopenharmony_ci dev_err(dev, "Write CCM_CORE_CTRL failed: %d\n", ret); 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci return ret; 93262306a36Sopenharmony_ci} 93362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_register_errata_patch); 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ciint cs35l41_set_channels(struct device *dev, struct regmap *reg, 93662306a36Sopenharmony_ci unsigned int tx_num, unsigned int *tx_slot, 93762306a36Sopenharmony_ci unsigned int rx_num, unsigned int *rx_slot) 93862306a36Sopenharmony_ci{ 93962306a36Sopenharmony_ci unsigned int val, mask; 94062306a36Sopenharmony_ci int i; 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci if (tx_num > 4 || rx_num > 2) 94362306a36Sopenharmony_ci return -EINVAL; 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci val = 0; 94662306a36Sopenharmony_ci mask = 0; 94762306a36Sopenharmony_ci for (i = 0; i < rx_num; i++) { 94862306a36Sopenharmony_ci dev_dbg(dev, "rx slot %d position = %d\n", i, rx_slot[i]); 94962306a36Sopenharmony_ci val |= rx_slot[i] << (i * 8); 95062306a36Sopenharmony_ci mask |= 0x3F << (i * 8); 95162306a36Sopenharmony_ci } 95262306a36Sopenharmony_ci regmap_update_bits(reg, CS35L41_SP_FRAME_RX_SLOT, mask, val); 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci val = 0; 95562306a36Sopenharmony_ci mask = 0; 95662306a36Sopenharmony_ci for (i = 0; i < tx_num; i++) { 95762306a36Sopenharmony_ci dev_dbg(dev, "tx slot %d position = %d\n", i, tx_slot[i]); 95862306a36Sopenharmony_ci val |= tx_slot[i] << (i * 8); 95962306a36Sopenharmony_ci mask |= 0x3F << (i * 8); 96062306a36Sopenharmony_ci } 96162306a36Sopenharmony_ci regmap_update_bits(reg, CS35L41_SP_FRAME_TX_SLOT, mask, val); 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci return 0; 96462306a36Sopenharmony_ci} 96562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_set_channels); 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_cistatic const unsigned char cs35l41_bst_k1_table[4][5] = { 96862306a36Sopenharmony_ci { 0x24, 0x32, 0x32, 0x4F, 0x57 }, 96962306a36Sopenharmony_ci { 0x24, 0x32, 0x32, 0x4F, 0x57 }, 97062306a36Sopenharmony_ci { 0x40, 0x32, 0x32, 0x4F, 0x57 }, 97162306a36Sopenharmony_ci { 0x40, 0x32, 0x32, 0x4F, 0x57 } 97262306a36Sopenharmony_ci}; 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_cistatic const unsigned char cs35l41_bst_k2_table[4][5] = { 97562306a36Sopenharmony_ci { 0x24, 0x49, 0x66, 0xA3, 0xEA }, 97662306a36Sopenharmony_ci { 0x24, 0x49, 0x66, 0xA3, 0xEA }, 97762306a36Sopenharmony_ci { 0x48, 0x49, 0x66, 0xA3, 0xEA }, 97862306a36Sopenharmony_ci { 0x48, 0x49, 0x66, 0xA3, 0xEA } 97962306a36Sopenharmony_ci}; 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_cistatic const unsigned char cs35l41_bst_slope_table[4] = { 98262306a36Sopenharmony_ci 0x75, 0x6B, 0x3B, 0x28 98362306a36Sopenharmony_ci}; 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_cistatic int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_ind, 98662306a36Sopenharmony_ci int boost_cap, int boost_ipk) 98762306a36Sopenharmony_ci{ 98862306a36Sopenharmony_ci unsigned char bst_lbst_val, bst_cbst_range, bst_ipk_scaled; 98962306a36Sopenharmony_ci int ret; 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci switch (boost_ind) { 99262306a36Sopenharmony_ci case 1000: /* 1.0 uH */ 99362306a36Sopenharmony_ci bst_lbst_val = 0; 99462306a36Sopenharmony_ci break; 99562306a36Sopenharmony_ci case 1200: /* 1.2 uH */ 99662306a36Sopenharmony_ci bst_lbst_val = 1; 99762306a36Sopenharmony_ci break; 99862306a36Sopenharmony_ci case 1500: /* 1.5 uH */ 99962306a36Sopenharmony_ci bst_lbst_val = 2; 100062306a36Sopenharmony_ci break; 100162306a36Sopenharmony_ci case 2200: /* 2.2 uH */ 100262306a36Sopenharmony_ci bst_lbst_val = 3; 100362306a36Sopenharmony_ci break; 100462306a36Sopenharmony_ci default: 100562306a36Sopenharmony_ci dev_err(dev, "Invalid boost inductor value: %d nH\n", boost_ind); 100662306a36Sopenharmony_ci return -EINVAL; 100762306a36Sopenharmony_ci } 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci switch (boost_cap) { 101062306a36Sopenharmony_ci case 0 ... 19: 101162306a36Sopenharmony_ci bst_cbst_range = 0; 101262306a36Sopenharmony_ci break; 101362306a36Sopenharmony_ci case 20 ... 50: 101462306a36Sopenharmony_ci bst_cbst_range = 1; 101562306a36Sopenharmony_ci break; 101662306a36Sopenharmony_ci case 51 ... 100: 101762306a36Sopenharmony_ci bst_cbst_range = 2; 101862306a36Sopenharmony_ci break; 101962306a36Sopenharmony_ci case 101 ... 200: 102062306a36Sopenharmony_ci bst_cbst_range = 3; 102162306a36Sopenharmony_ci break; 102262306a36Sopenharmony_ci default: 102362306a36Sopenharmony_ci if (boost_cap < 0) { 102462306a36Sopenharmony_ci dev_err(dev, "Invalid boost capacitor value: %d nH\n", boost_cap); 102562306a36Sopenharmony_ci return -EINVAL; 102662306a36Sopenharmony_ci } 102762306a36Sopenharmony_ci /* 201 uF and greater */ 102862306a36Sopenharmony_ci bst_cbst_range = 4; 102962306a36Sopenharmony_ci } 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci if (boost_ipk < 1600 || boost_ipk > 4500) { 103262306a36Sopenharmony_ci dev_err(dev, "Invalid boost inductor peak current: %d mA\n", boost_ipk); 103362306a36Sopenharmony_ci return -EINVAL; 103462306a36Sopenharmony_ci } 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_COEFF, 103762306a36Sopenharmony_ci CS35L41_BST_K1_MASK | CS35L41_BST_K2_MASK, 103862306a36Sopenharmony_ci cs35l41_bst_k1_table[bst_lbst_val][bst_cbst_range] 103962306a36Sopenharmony_ci << CS35L41_BST_K1_SHIFT | 104062306a36Sopenharmony_ci cs35l41_bst_k2_table[bst_lbst_val][bst_cbst_range] 104162306a36Sopenharmony_ci << CS35L41_BST_K2_SHIFT); 104262306a36Sopenharmony_ci if (ret) { 104362306a36Sopenharmony_ci dev_err(dev, "Failed to write boost coefficients: %d\n", ret); 104462306a36Sopenharmony_ci return ret; 104562306a36Sopenharmony_ci } 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_SLOPE_LBST, 104862306a36Sopenharmony_ci CS35L41_BST_SLOPE_MASK | CS35L41_BST_LBST_VAL_MASK, 104962306a36Sopenharmony_ci cs35l41_bst_slope_table[bst_lbst_val] 105062306a36Sopenharmony_ci << CS35L41_BST_SLOPE_SHIFT | 105162306a36Sopenharmony_ci bst_lbst_val << CS35L41_BST_LBST_VAL_SHIFT); 105262306a36Sopenharmony_ci if (ret) { 105362306a36Sopenharmony_ci dev_err(dev, "Failed to write boost slope/inductor value: %d\n", ret); 105462306a36Sopenharmony_ci return ret; 105562306a36Sopenharmony_ci } 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci bst_ipk_scaled = ((boost_ipk - 1600) / 50) + 0x10; 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_PEAK_CUR, CS35L41_BST_IPK_MASK, 106062306a36Sopenharmony_ci bst_ipk_scaled << CS35L41_BST_IPK_SHIFT); 106162306a36Sopenharmony_ci if (ret) { 106262306a36Sopenharmony_ci dev_err(dev, "Failed to write boost inductor peak current: %d\n", ret); 106362306a36Sopenharmony_ci return ret; 106462306a36Sopenharmony_ci } 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci regmap_update_bits(regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK, 106762306a36Sopenharmony_ci CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT); 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci return 0; 107062306a36Sopenharmony_ci} 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_cistatic const struct reg_sequence cs35l41_safe_to_reset[] = { 107362306a36Sopenharmony_ci { 0x00000040, 0x00000055 }, 107462306a36Sopenharmony_ci { 0x00000040, 0x000000AA }, 107562306a36Sopenharmony_ci { 0x0000393C, 0x000000C0, 6000}, 107662306a36Sopenharmony_ci { 0x0000393C, 0x00000000 }, 107762306a36Sopenharmony_ci { 0x00007414, 0x00C82222 }, 107862306a36Sopenharmony_ci { 0x0000742C, 0x00000000 }, 107962306a36Sopenharmony_ci { 0x00000040, 0x000000CC }, 108062306a36Sopenharmony_ci { 0x00000040, 0x00000033 }, 108162306a36Sopenharmony_ci}; 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_cistatic const struct reg_sequence cs35l41_active_to_safe_start[] = { 108462306a36Sopenharmony_ci { 0x00000040, 0x00000055 }, 108562306a36Sopenharmony_ci { 0x00000040, 0x000000AA }, 108662306a36Sopenharmony_ci { 0x00007438, 0x00585941 }, 108762306a36Sopenharmony_ci { CS35L41_PWR_CTRL1, 0x00000000 }, 108862306a36Sopenharmony_ci { 0x0000742C, 0x00000009 }, 108962306a36Sopenharmony_ci}; 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_cistatic const struct reg_sequence cs35l41_active_to_safe_end[] = { 109262306a36Sopenharmony_ci { 0x00007438, 0x00580941 }, 109362306a36Sopenharmony_ci { 0x00000040, 0x000000CC }, 109462306a36Sopenharmony_ci { 0x00000040, 0x00000033 }, 109562306a36Sopenharmony_ci}; 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_cistatic const struct reg_sequence cs35l41_safe_to_active_start[] = { 109862306a36Sopenharmony_ci { 0x00000040, 0x00000055 }, 109962306a36Sopenharmony_ci { 0x00000040, 0x000000AA }, 110062306a36Sopenharmony_ci { 0x0000742C, 0x0000000F }, 110162306a36Sopenharmony_ci { 0x0000742C, 0x00000079 }, 110262306a36Sopenharmony_ci { 0x00007438, 0x00585941 }, 110362306a36Sopenharmony_ci { CS35L41_PWR_CTRL1, 0x00000001 }, // GLOBAL_EN = 1 110462306a36Sopenharmony_ci}; 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_cistatic const struct reg_sequence cs35l41_safe_to_active_en_spk[] = { 110762306a36Sopenharmony_ci { 0x0000742C, 0x000000F9 }, 110862306a36Sopenharmony_ci { 0x00007438, 0x00580941 }, 110962306a36Sopenharmony_ci}; 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_cistatic const struct reg_sequence cs35l41_reset_to_safe[] = { 111262306a36Sopenharmony_ci { 0x00000040, 0x00000055 }, 111362306a36Sopenharmony_ci { 0x00000040, 0x000000AA }, 111462306a36Sopenharmony_ci { 0x00007438, 0x00585941 }, 111562306a36Sopenharmony_ci { 0x00007414, 0x08C82222 }, 111662306a36Sopenharmony_ci { 0x0000742C, 0x00000009 }, 111762306a36Sopenharmony_ci { 0x00000040, 0x000000CC }, 111862306a36Sopenharmony_ci { 0x00000040, 0x00000033 }, 111962306a36Sopenharmony_ci}; 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_cistatic const struct reg_sequence cs35l41_actv_seq[] = { 112262306a36Sopenharmony_ci /* SYNC_BST_CTL_RX_EN = 1; SYNC_BST_CTL_TX_EN = 1 */ 112362306a36Sopenharmony_ci {CS35L41_MDSYNC_EN, 0x00003000}, 112462306a36Sopenharmony_ci /* BST_CTL_SEL = MDSYNC */ 112562306a36Sopenharmony_ci {CS35L41_BSTCVRT_VCTRL2, 0x00000002}, 112662306a36Sopenharmony_ci}; 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_cistatic const struct reg_sequence cs35l41_pass_seq[] = { 112962306a36Sopenharmony_ci /* SYNC_BST_CTL_RX_EN = 0; SYNC_BST_CTL_TX_EN = 1 */ 113062306a36Sopenharmony_ci {CS35L41_MDSYNC_EN, 0x00001000}, 113162306a36Sopenharmony_ci /* BST_EN = 0 */ 113262306a36Sopenharmony_ci {CS35L41_PWR_CTRL2, 0x00003300}, 113362306a36Sopenharmony_ci /* BST_CTL_SEL = MDSYNC */ 113462306a36Sopenharmony_ci {CS35L41_BSTCVRT_VCTRL2, 0x00000002}, 113562306a36Sopenharmony_ci}; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ciint cs35l41_init_boost(struct device *dev, struct regmap *regmap, 113862306a36Sopenharmony_ci struct cs35l41_hw_cfg *hw_cfg) 113962306a36Sopenharmony_ci{ 114062306a36Sopenharmony_ci int ret; 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_ci switch (hw_cfg->bst_type) { 114362306a36Sopenharmony_ci case CS35L41_SHD_BOOST_ACTV: 114462306a36Sopenharmony_ci regmap_multi_reg_write(regmap, cs35l41_actv_seq, ARRAY_SIZE(cs35l41_actv_seq)); 114562306a36Sopenharmony_ci fallthrough; 114662306a36Sopenharmony_ci case CS35L41_INT_BOOST: 114762306a36Sopenharmony_ci ret = cs35l41_boost_config(dev, regmap, hw_cfg->bst_ind, 114862306a36Sopenharmony_ci hw_cfg->bst_cap, hw_cfg->bst_ipk); 114962306a36Sopenharmony_ci if (ret) 115062306a36Sopenharmony_ci dev_err(dev, "Error in Boost DT config: %d\n", ret); 115162306a36Sopenharmony_ci break; 115262306a36Sopenharmony_ci case CS35L41_EXT_BOOST: 115362306a36Sopenharmony_ci case CS35L41_EXT_BOOST_NO_VSPK_SWITCH: 115462306a36Sopenharmony_ci /* Only CLSA0100 doesn't use GPIO as VSPK switch, but even on that laptop we can 115562306a36Sopenharmony_ci * toggle GPIO1 as is not connected to anything. 115662306a36Sopenharmony_ci * There will be no other device without VSPK switch. 115762306a36Sopenharmony_ci */ 115862306a36Sopenharmony_ci regmap_write(regmap, CS35L41_GPIO1_CTRL1, 0x00000001); 115962306a36Sopenharmony_ci regmap_multi_reg_write(regmap, cs35l41_reset_to_safe, 116062306a36Sopenharmony_ci ARRAY_SIZE(cs35l41_reset_to_safe)); 116162306a36Sopenharmony_ci ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK, 116262306a36Sopenharmony_ci CS35L41_BST_DIS_FET_OFF << CS35L41_BST_EN_SHIFT); 116362306a36Sopenharmony_ci break; 116462306a36Sopenharmony_ci case CS35L41_SHD_BOOST_PASS: 116562306a36Sopenharmony_ci ret = regmap_multi_reg_write(regmap, cs35l41_pass_seq, 116662306a36Sopenharmony_ci ARRAY_SIZE(cs35l41_pass_seq)); 116762306a36Sopenharmony_ci break; 116862306a36Sopenharmony_ci default: 116962306a36Sopenharmony_ci dev_err(dev, "Boost type %d not supported\n", hw_cfg->bst_type); 117062306a36Sopenharmony_ci ret = -EINVAL; 117162306a36Sopenharmony_ci break; 117262306a36Sopenharmony_ci } 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci return ret; 117562306a36Sopenharmony_ci} 117662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_init_boost); 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_cibool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type) 117962306a36Sopenharmony_ci{ 118062306a36Sopenharmony_ci switch (b_type) { 118162306a36Sopenharmony_ci /* There is only one laptop that doesn't have VSPK switch. */ 118262306a36Sopenharmony_ci case CS35L41_EXT_BOOST_NO_VSPK_SWITCH: 118362306a36Sopenharmony_ci return false; 118462306a36Sopenharmony_ci case CS35L41_EXT_BOOST: 118562306a36Sopenharmony_ci regmap_write(regmap, CS35L41_GPIO1_CTRL1, 0x00000001); 118662306a36Sopenharmony_ci regmap_multi_reg_write(regmap, cs35l41_safe_to_reset, 118762306a36Sopenharmony_ci ARRAY_SIZE(cs35l41_safe_to_reset)); 118862306a36Sopenharmony_ci return true; 118962306a36Sopenharmony_ci default: 119062306a36Sopenharmony_ci return true; 119162306a36Sopenharmony_ci } 119262306a36Sopenharmony_ci} 119362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_safe_reset); 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci/* 119662306a36Sopenharmony_ci * Enabling the CS35L41_SHD_BOOST_ACTV and CS35L41_SHD_BOOST_PASS shared boosts 119762306a36Sopenharmony_ci * does also require a call to cs35l41_mdsync_up(), but not before getting the 119862306a36Sopenharmony_ci * PLL Lock signal. 119962306a36Sopenharmony_ci * 120062306a36Sopenharmony_ci * PLL Lock seems to be triggered soon after snd_pcm_start() is executed and 120162306a36Sopenharmony_ci * SNDRV_PCM_TRIGGER_START command is processed, which happens (long) after the 120262306a36Sopenharmony_ci * SND_SOC_DAPM_PRE_PMU event handler is invoked as part of snd_pcm_prepare(). 120362306a36Sopenharmony_ci * 120462306a36Sopenharmony_ci * This event handler is where cs35l41_global_enable() is normally called from, 120562306a36Sopenharmony_ci * but waiting for PLL Lock here will time out. Increasing the wait duration 120662306a36Sopenharmony_ci * will not help, as the only consequence of it would be to add an unnecessary 120762306a36Sopenharmony_ci * delay in the invocation of snd_pcm_start(). 120862306a36Sopenharmony_ci * 120962306a36Sopenharmony_ci * Trying to move the wait in the SNDRV_PCM_TRIGGER_START callback is not a 121062306a36Sopenharmony_ci * solution either, as the trigger is executed in an IRQ-off atomic context. 121162306a36Sopenharmony_ci * 121262306a36Sopenharmony_ci * The current approach is to invoke cs35l41_mdsync_up() right after receiving 121362306a36Sopenharmony_ci * the PLL Lock interrupt, in the IRQ handler. 121462306a36Sopenharmony_ci */ 121562306a36Sopenharmony_ciint cs35l41_global_enable(struct device *dev, struct regmap *regmap, enum cs35l41_boost_type b_type, 121662306a36Sopenharmony_ci int enable, bool firmware_running) 121762306a36Sopenharmony_ci{ 121862306a36Sopenharmony_ci int ret; 121962306a36Sopenharmony_ci unsigned int gpio1_func, pad_control, pwr_ctrl1, pwr_ctrl3, int_status, pup_pdn_mask; 122062306a36Sopenharmony_ci unsigned int pwr_ctl1_val; 122162306a36Sopenharmony_ci struct reg_sequence cs35l41_mdsync_down_seq[] = { 122262306a36Sopenharmony_ci {CS35L41_PWR_CTRL3, 0}, 122362306a36Sopenharmony_ci {CS35L41_GPIO_PAD_CONTROL, 0}, 122462306a36Sopenharmony_ci {CS35L41_PWR_CTRL1, 0, 3000}, 122562306a36Sopenharmony_ci }; 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci pup_pdn_mask = enable ? CS35L41_PUP_DONE_MASK : CS35L41_PDN_DONE_MASK; 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci ret = regmap_read(regmap, CS35L41_PWR_CTRL1, &pwr_ctl1_val); 123062306a36Sopenharmony_ci if (ret) 123162306a36Sopenharmony_ci return ret; 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci if ((pwr_ctl1_val & CS35L41_GLOBAL_EN_MASK) && enable) { 123462306a36Sopenharmony_ci dev_dbg(dev, "Cannot set Global Enable - already set.\n"); 123562306a36Sopenharmony_ci return 0; 123662306a36Sopenharmony_ci } else if (!(pwr_ctl1_val & CS35L41_GLOBAL_EN_MASK) && !enable) { 123762306a36Sopenharmony_ci dev_dbg(dev, "Cannot unset Global Enable - not set.\n"); 123862306a36Sopenharmony_ci return 0; 123962306a36Sopenharmony_ci } 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci switch (b_type) { 124262306a36Sopenharmony_ci case CS35L41_SHD_BOOST_ACTV: 124362306a36Sopenharmony_ci case CS35L41_SHD_BOOST_PASS: 124462306a36Sopenharmony_ci regmap_read(regmap, CS35L41_PWR_CTRL3, &pwr_ctrl3); 124562306a36Sopenharmony_ci regmap_read(regmap, CS35L41_GPIO_PAD_CONTROL, &pad_control); 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci pwr_ctrl3 &= ~CS35L41_SYNC_EN_MASK; 124862306a36Sopenharmony_ci pwr_ctrl1 = enable << CS35L41_GLOBAL_EN_SHIFT; 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci gpio1_func = enable ? CS35L41_GPIO1_MDSYNC : CS35L41_GPIO1_HIZ; 125162306a36Sopenharmony_ci gpio1_func <<= CS35L41_GPIO1_CTRL_SHIFT; 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci pad_control &= ~CS35L41_GPIO1_CTRL_MASK; 125462306a36Sopenharmony_ci pad_control |= gpio1_func & CS35L41_GPIO1_CTRL_MASK; 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci cs35l41_mdsync_down_seq[0].def = pwr_ctrl3; 125762306a36Sopenharmony_ci cs35l41_mdsync_down_seq[1].def = pad_control; 125862306a36Sopenharmony_ci cs35l41_mdsync_down_seq[2].def = pwr_ctrl1; 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci ret = regmap_multi_reg_write(regmap, cs35l41_mdsync_down_seq, 126162306a36Sopenharmony_ci ARRAY_SIZE(cs35l41_mdsync_down_seq)); 126262306a36Sopenharmony_ci /* Activation to be completed later via cs35l41_mdsync_up() */ 126362306a36Sopenharmony_ci if (ret || enable) 126462306a36Sopenharmony_ci return ret; 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1, 126762306a36Sopenharmony_ci int_status, int_status & pup_pdn_mask, 126862306a36Sopenharmony_ci 1000, 100000); 126962306a36Sopenharmony_ci if (ret) 127062306a36Sopenharmony_ci dev_err(dev, "Enable(%d) failed: %d\n", enable, ret); 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci /* Clear PUP/PDN status */ 127362306a36Sopenharmony_ci regmap_write(regmap, CS35L41_IRQ1_STATUS1, pup_pdn_mask); 127462306a36Sopenharmony_ci break; 127562306a36Sopenharmony_ci case CS35L41_INT_BOOST: 127662306a36Sopenharmony_ci ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL1, CS35L41_GLOBAL_EN_MASK, 127762306a36Sopenharmony_ci enable << CS35L41_GLOBAL_EN_SHIFT); 127862306a36Sopenharmony_ci if (ret) { 127962306a36Sopenharmony_ci dev_err(dev, "CS35L41_PWR_CTRL1 set failed: %d\n", ret); 128062306a36Sopenharmony_ci return ret; 128162306a36Sopenharmony_ci } 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1, 128462306a36Sopenharmony_ci int_status, int_status & pup_pdn_mask, 128562306a36Sopenharmony_ci 1000, 100000); 128662306a36Sopenharmony_ci if (ret) 128762306a36Sopenharmony_ci dev_err(dev, "Enable(%d) failed: %d\n", enable, ret); 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci /* Clear PUP/PDN status */ 129062306a36Sopenharmony_ci regmap_write(regmap, CS35L41_IRQ1_STATUS1, pup_pdn_mask); 129162306a36Sopenharmony_ci break; 129262306a36Sopenharmony_ci case CS35L41_EXT_BOOST: 129362306a36Sopenharmony_ci case CS35L41_EXT_BOOST_NO_VSPK_SWITCH: 129462306a36Sopenharmony_ci if (enable) { 129562306a36Sopenharmony_ci /* Test Key is unlocked here */ 129662306a36Sopenharmony_ci ret = regmap_multi_reg_write(regmap, cs35l41_safe_to_active_start, 129762306a36Sopenharmony_ci ARRAY_SIZE(cs35l41_safe_to_active_start)); 129862306a36Sopenharmony_ci if (ret) 129962306a36Sopenharmony_ci return ret; 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1, int_status, 130262306a36Sopenharmony_ci int_status & CS35L41_PUP_DONE_MASK, 1000, 100000); 130362306a36Sopenharmony_ci if (ret) { 130462306a36Sopenharmony_ci dev_err(dev, "Failed waiting for CS35L41_PUP_DONE_MASK: %d\n", ret); 130562306a36Sopenharmony_ci /* Lock the test key, it was unlocked during the multi_reg_write */ 130662306a36Sopenharmony_ci cs35l41_test_key_lock(dev, regmap); 130762306a36Sopenharmony_ci return ret; 130862306a36Sopenharmony_ci } 130962306a36Sopenharmony_ci regmap_write(regmap, CS35L41_IRQ1_STATUS1, CS35L41_PUP_DONE_MASK); 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci if (firmware_running) 131262306a36Sopenharmony_ci ret = cs35l41_set_cspl_mbox_cmd(dev, regmap, 131362306a36Sopenharmony_ci CSPL_MBOX_CMD_SPK_OUT_ENABLE); 131462306a36Sopenharmony_ci else 131562306a36Sopenharmony_ci ret = regmap_multi_reg_write(regmap, cs35l41_safe_to_active_en_spk, 131662306a36Sopenharmony_ci ARRAY_SIZE(cs35l41_safe_to_active_en_spk)); 131762306a36Sopenharmony_ci 131862306a36Sopenharmony_ci /* Lock the test key, it was unlocked during the multi_reg_write */ 131962306a36Sopenharmony_ci cs35l41_test_key_lock(dev, regmap); 132062306a36Sopenharmony_ci } else { 132162306a36Sopenharmony_ci /* Test Key is unlocked here */ 132262306a36Sopenharmony_ci ret = regmap_multi_reg_write(regmap, cs35l41_active_to_safe_start, 132362306a36Sopenharmony_ci ARRAY_SIZE(cs35l41_active_to_safe_start)); 132462306a36Sopenharmony_ci if (ret) { 132562306a36Sopenharmony_ci /* Lock the test key, it was unlocked during the multi_reg_write */ 132662306a36Sopenharmony_ci cs35l41_test_key_lock(dev, regmap); 132762306a36Sopenharmony_ci return ret; 132862306a36Sopenharmony_ci } 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ci ret = regmap_read_poll_timeout(regmap, CS35L41_IRQ1_STATUS1, int_status, 133162306a36Sopenharmony_ci int_status & CS35L41_PDN_DONE_MASK, 1000, 100000); 133262306a36Sopenharmony_ci if (ret) { 133362306a36Sopenharmony_ci dev_err(dev, "Failed waiting for CS35L41_PDN_DONE_MASK: %d\n", ret); 133462306a36Sopenharmony_ci /* Lock the test key, it was unlocked during the multi_reg_write */ 133562306a36Sopenharmony_ci cs35l41_test_key_lock(dev, regmap); 133662306a36Sopenharmony_ci return ret; 133762306a36Sopenharmony_ci } 133862306a36Sopenharmony_ci regmap_write(regmap, CS35L41_IRQ1_STATUS1, CS35L41_PDN_DONE_MASK); 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci /* Test Key is locked here */ 134162306a36Sopenharmony_ci ret = regmap_multi_reg_write(regmap, cs35l41_active_to_safe_end, 134262306a36Sopenharmony_ci ARRAY_SIZE(cs35l41_active_to_safe_end)); 134362306a36Sopenharmony_ci } 134462306a36Sopenharmony_ci break; 134562306a36Sopenharmony_ci default: 134662306a36Sopenharmony_ci ret = -EINVAL; 134762306a36Sopenharmony_ci break; 134862306a36Sopenharmony_ci } 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci return ret; 135162306a36Sopenharmony_ci} 135262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_global_enable); 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_ci/* 135562306a36Sopenharmony_ci * To be called after receiving the IRQ Lock interrupt, in order to complete 135662306a36Sopenharmony_ci * any shared boost activation initiated by cs35l41_global_enable(). 135762306a36Sopenharmony_ci */ 135862306a36Sopenharmony_ciint cs35l41_mdsync_up(struct regmap *regmap) 135962306a36Sopenharmony_ci{ 136062306a36Sopenharmony_ci return regmap_update_bits(regmap, CS35L41_PWR_CTRL3, 136162306a36Sopenharmony_ci CS35L41_SYNC_EN_MASK, CS35L41_SYNC_EN_MASK); 136262306a36Sopenharmony_ci} 136362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_mdsync_up); 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ciint cs35l41_gpio_config(struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg) 136662306a36Sopenharmony_ci{ 136762306a36Sopenharmony_ci struct cs35l41_gpio_cfg *gpio1 = &hw_cfg->gpio1; 136862306a36Sopenharmony_ci struct cs35l41_gpio_cfg *gpio2 = &hw_cfg->gpio2; 136962306a36Sopenharmony_ci int irq_pol = IRQF_TRIGGER_NONE; 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_ci regmap_update_bits(regmap, CS35L41_GPIO1_CTRL1, 137262306a36Sopenharmony_ci CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK, 137362306a36Sopenharmony_ci gpio1->pol_inv << CS35L41_GPIO_POL_SHIFT | 137462306a36Sopenharmony_ci !gpio1->out_en << CS35L41_GPIO_DIR_SHIFT); 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci regmap_update_bits(regmap, CS35L41_GPIO2_CTRL1, 137762306a36Sopenharmony_ci CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK, 137862306a36Sopenharmony_ci gpio2->pol_inv << CS35L41_GPIO_POL_SHIFT | 137962306a36Sopenharmony_ci !gpio2->out_en << CS35L41_GPIO_DIR_SHIFT); 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci if (gpio1->valid) 138262306a36Sopenharmony_ci regmap_update_bits(regmap, CS35L41_GPIO_PAD_CONTROL, CS35L41_GPIO1_CTRL_MASK, 138362306a36Sopenharmony_ci gpio1->func << CS35L41_GPIO1_CTRL_SHIFT); 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_ci if (gpio2->valid) { 138662306a36Sopenharmony_ci regmap_update_bits(regmap, CS35L41_GPIO_PAD_CONTROL, CS35L41_GPIO2_CTRL_MASK, 138762306a36Sopenharmony_ci gpio2->func << CS35L41_GPIO2_CTRL_SHIFT); 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci switch (gpio2->func) { 139062306a36Sopenharmony_ci case CS35L41_GPIO2_INT_PUSH_PULL_LOW: 139162306a36Sopenharmony_ci case CS35L41_GPIO2_INT_OPEN_DRAIN: 139262306a36Sopenharmony_ci irq_pol = IRQF_TRIGGER_LOW; 139362306a36Sopenharmony_ci break; 139462306a36Sopenharmony_ci case CS35L41_GPIO2_INT_PUSH_PULL_HIGH: 139562306a36Sopenharmony_ci irq_pol = IRQF_TRIGGER_HIGH; 139662306a36Sopenharmony_ci break; 139762306a36Sopenharmony_ci default: 139862306a36Sopenharmony_ci break; 139962306a36Sopenharmony_ci } 140062306a36Sopenharmony_ci } 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci return irq_pol; 140362306a36Sopenharmony_ci} 140462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_gpio_config); 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_cistatic const struct cs_dsp_region cs35l41_dsp1_regions[] = { 140762306a36Sopenharmony_ci { .type = WMFW_HALO_PM_PACKED, .base = CS35L41_DSP1_PMEM_0 }, 140862306a36Sopenharmony_ci { .type = WMFW_HALO_XM_PACKED, .base = CS35L41_DSP1_XMEM_PACK_0 }, 140962306a36Sopenharmony_ci { .type = WMFW_HALO_YM_PACKED, .base = CS35L41_DSP1_YMEM_PACK_0 }, 141062306a36Sopenharmony_ci {. type = WMFW_ADSP2_XM, .base = CS35L41_DSP1_XMEM_UNPACK24_0}, 141162306a36Sopenharmony_ci {. type = WMFW_ADSP2_YM, .base = CS35L41_DSP1_YMEM_UNPACK24_0}, 141262306a36Sopenharmony_ci}; 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_civoid cs35l41_configure_cs_dsp(struct device *dev, struct regmap *reg, struct cs_dsp *dsp) 141562306a36Sopenharmony_ci{ 141662306a36Sopenharmony_ci dsp->num = 1; 141762306a36Sopenharmony_ci dsp->type = WMFW_HALO; 141862306a36Sopenharmony_ci dsp->rev = 0; 141962306a36Sopenharmony_ci dsp->dev = dev; 142062306a36Sopenharmony_ci dsp->regmap = reg; 142162306a36Sopenharmony_ci dsp->base = CS35L41_DSP1_CTRL_BASE; 142262306a36Sopenharmony_ci dsp->base_sysinfo = CS35L41_DSP1_SYS_ID; 142362306a36Sopenharmony_ci dsp->mem = cs35l41_dsp1_regions; 142462306a36Sopenharmony_ci dsp->num_mems = ARRAY_SIZE(cs35l41_dsp1_regions); 142562306a36Sopenharmony_ci dsp->lock_regions = 0xFFFFFFFF; 142662306a36Sopenharmony_ci} 142762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_configure_cs_dsp); 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_cistatic bool cs35l41_check_cspl_mbox_sts(enum cs35l41_cspl_mbox_cmd cmd, 143062306a36Sopenharmony_ci enum cs35l41_cspl_mbox_status sts) 143162306a36Sopenharmony_ci{ 143262306a36Sopenharmony_ci switch (cmd) { 143362306a36Sopenharmony_ci case CSPL_MBOX_CMD_NONE: 143462306a36Sopenharmony_ci case CSPL_MBOX_CMD_UNKNOWN_CMD: 143562306a36Sopenharmony_ci return true; 143662306a36Sopenharmony_ci case CSPL_MBOX_CMD_PAUSE: 143762306a36Sopenharmony_ci case CSPL_MBOX_CMD_OUT_OF_HIBERNATE: 143862306a36Sopenharmony_ci return (sts == CSPL_MBOX_STS_PAUSED); 143962306a36Sopenharmony_ci case CSPL_MBOX_CMD_RESUME: 144062306a36Sopenharmony_ci return (sts == CSPL_MBOX_STS_RUNNING); 144162306a36Sopenharmony_ci case CSPL_MBOX_CMD_REINIT: 144262306a36Sopenharmony_ci return (sts == CSPL_MBOX_STS_RUNNING); 144362306a36Sopenharmony_ci case CSPL_MBOX_CMD_STOP_PRE_REINIT: 144462306a36Sopenharmony_ci return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT); 144562306a36Sopenharmony_ci case CSPL_MBOX_CMD_SPK_OUT_ENABLE: 144662306a36Sopenharmony_ci return (sts == CSPL_MBOX_STS_RUNNING); 144762306a36Sopenharmony_ci default: 144862306a36Sopenharmony_ci return false; 144962306a36Sopenharmony_ci } 145062306a36Sopenharmony_ci} 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ciint cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap, 145362306a36Sopenharmony_ci enum cs35l41_cspl_mbox_cmd cmd) 145462306a36Sopenharmony_ci{ 145562306a36Sopenharmony_ci unsigned int sts = 0, i; 145662306a36Sopenharmony_ci int ret; 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_ci // Set mailbox cmd 145962306a36Sopenharmony_ci ret = regmap_write(regmap, CS35L41_DSP_VIRT1_MBOX_1, cmd); 146062306a36Sopenharmony_ci if (ret < 0) { 146162306a36Sopenharmony_ci if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE) 146262306a36Sopenharmony_ci dev_err(dev, "Failed to write MBOX: %d\n", ret); 146362306a36Sopenharmony_ci return ret; 146462306a36Sopenharmony_ci } 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci // Read mailbox status and verify it is appropriate for the given cmd 146762306a36Sopenharmony_ci for (i = 0; i < 5; i++) { 146862306a36Sopenharmony_ci usleep_range(1000, 1100); 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci ret = regmap_read(regmap, CS35L41_DSP_MBOX_2, &sts); 147162306a36Sopenharmony_ci if (ret < 0) { 147262306a36Sopenharmony_ci dev_err(dev, "Failed to read MBOX STS: %d\n", ret); 147362306a36Sopenharmony_ci continue; 147462306a36Sopenharmony_ci } 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci if (!cs35l41_check_cspl_mbox_sts(cmd, sts)) 147762306a36Sopenharmony_ci dev_dbg(dev, "[%u] cmd %u returned invalid sts %u", i, cmd, sts); 147862306a36Sopenharmony_ci else 147962306a36Sopenharmony_ci return 0; 148062306a36Sopenharmony_ci } 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ci if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE) 148362306a36Sopenharmony_ci dev_err(dev, "Failed to set mailbox cmd %u (status %u)\n", cmd, sts); 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci return -ENOMSG; 148662306a36Sopenharmony_ci} 148762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_set_cspl_mbox_cmd); 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_ciint cs35l41_write_fs_errata(struct device *dev, struct regmap *regmap) 149062306a36Sopenharmony_ci{ 149162306a36Sopenharmony_ci int ret; 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci ret = regmap_multi_reg_write(regmap, cs35l41_fs_errata_patch, 149462306a36Sopenharmony_ci ARRAY_SIZE(cs35l41_fs_errata_patch)); 149562306a36Sopenharmony_ci if (ret < 0) 149662306a36Sopenharmony_ci dev_err(dev, "Failed to write fs errata: %d\n", ret); 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci return ret; 149962306a36Sopenharmony_ci} 150062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_write_fs_errata); 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_ciint cs35l41_enter_hibernate(struct device *dev, struct regmap *regmap, 150362306a36Sopenharmony_ci enum cs35l41_boost_type b_type) 150462306a36Sopenharmony_ci{ 150562306a36Sopenharmony_ci if (!cs35l41_safe_reset(regmap, b_type)) { 150662306a36Sopenharmony_ci dev_dbg(dev, "System does not support Suspend\n"); 150762306a36Sopenharmony_ci return -EINVAL; 150862306a36Sopenharmony_ci } 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci dev_dbg(dev, "Enter hibernate\n"); 151162306a36Sopenharmony_ci regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0088); 151262306a36Sopenharmony_ci regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0188); 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_ci // Don't wait for ACK since bus activity would wake the device 151562306a36Sopenharmony_ci regmap_write(regmap, CS35L41_DSP_VIRT1_MBOX_1, CSPL_MBOX_CMD_HIBERNATE); 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci return 0; 151862306a36Sopenharmony_ci} 151962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_enter_hibernate); 152062306a36Sopenharmony_ci 152162306a36Sopenharmony_cistatic void cs35l41_wait_for_pwrmgt_sts(struct device *dev, struct regmap *regmap) 152262306a36Sopenharmony_ci{ 152362306a36Sopenharmony_ci const int pwrmgt_retries = 10; 152462306a36Sopenharmony_ci unsigned int sts; 152562306a36Sopenharmony_ci int i, ret; 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci for (i = 0; i < pwrmgt_retries; i++) { 152862306a36Sopenharmony_ci ret = regmap_read(regmap, CS35L41_PWRMGT_STS, &sts); 152962306a36Sopenharmony_ci if (ret) 153062306a36Sopenharmony_ci dev_err(dev, "Failed to read PWRMGT_STS: %d\n", ret); 153162306a36Sopenharmony_ci else if (!(sts & CS35L41_WR_PEND_STS_MASK)) 153262306a36Sopenharmony_ci return; 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_ci udelay(20); 153562306a36Sopenharmony_ci } 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_ci dev_err(dev, "Timed out reading PWRMGT_STS\n"); 153862306a36Sopenharmony_ci} 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ciint cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap) 154162306a36Sopenharmony_ci{ 154262306a36Sopenharmony_ci const int wake_retries = 20; 154362306a36Sopenharmony_ci const int sleep_retries = 5; 154462306a36Sopenharmony_ci int ret, i, j; 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci for (i = 0; i < sleep_retries; i++) { 154762306a36Sopenharmony_ci dev_dbg(dev, "Exit hibernate\n"); 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_ci for (j = 0; j < wake_retries; j++) { 155062306a36Sopenharmony_ci ret = cs35l41_set_cspl_mbox_cmd(dev, regmap, 155162306a36Sopenharmony_ci CSPL_MBOX_CMD_OUT_OF_HIBERNATE); 155262306a36Sopenharmony_ci if (!ret) 155362306a36Sopenharmony_ci break; 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci usleep_range(100, 200); 155662306a36Sopenharmony_ci } 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ci if (j < wake_retries) { 155962306a36Sopenharmony_ci dev_dbg(dev, "Wake success at cycle: %d\n", j); 156062306a36Sopenharmony_ci return 0; 156162306a36Sopenharmony_ci } 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci dev_err(dev, "Wake failed, re-enter hibernate: %d\n", ret); 156462306a36Sopenharmony_ci 156562306a36Sopenharmony_ci cs35l41_wait_for_pwrmgt_sts(dev, regmap); 156662306a36Sopenharmony_ci regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0088); 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_ci cs35l41_wait_for_pwrmgt_sts(dev, regmap); 156962306a36Sopenharmony_ci regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0188); 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci cs35l41_wait_for_pwrmgt_sts(dev, regmap); 157262306a36Sopenharmony_ci regmap_write(regmap, CS35L41_PWRMGT_CTL, 0x3); 157362306a36Sopenharmony_ci } 157462306a36Sopenharmony_ci 157562306a36Sopenharmony_ci dev_err(dev, "Timed out waking device\n"); 157662306a36Sopenharmony_ci 157762306a36Sopenharmony_ci return -ETIMEDOUT; 157862306a36Sopenharmony_ci} 157962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cs35l41_exit_hibernate); 158062306a36Sopenharmony_ci 158162306a36Sopenharmony_ciMODULE_DESCRIPTION("CS35L41 library"); 158262306a36Sopenharmony_ciMODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>"); 158362306a36Sopenharmony_ciMODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>"); 158462306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1585