From d0ffbf6bb103cae23f3ccf022fdc92f4b0e9930c Mon Sep 17 00:00:00 2001 From: Jeff LaBundy Date: Wed, 4 Apr 2018 16:49:20 -0500 Subject: [PATCH] misc: cs40l2x: Update DSP load procedure Separated DSP initialization into its own function and qualified the silicon revision to determine the appropriate firmware file and boot sequence. Change-Id: Ic2d50e8604d390877cf431811963d95be72d1ba6 Signed-off-by: Jeff LaBundy Signed-off-by: Ravi Vembu --- drivers/misc/cs40l2x.c | 86 +++++++++++++++++++++++++++++++----------- drivers/misc/cs40l2x.h | 6 +++ 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/drivers/misc/cs40l2x.c b/drivers/misc/cs40l2x.c index ba64dc7e93cf..5eed3d28c5d9 100644 --- a/drivers/misc/cs40l2x.c +++ b/drivers/misc/cs40l2x.c @@ -968,11 +968,34 @@ static void cs40l2x_dsp_start(struct cs40l2x_private *cs40l2x) unsigned int val; int dsp_timeout = CS40L2X_DSP_TIMEOUT_COUNT; - ret = regmap_update_bits(regmap, CS40L2X_DSP1_CCM_CORE_CTRL, - CS40L2X_DSP1_EN_MASK, 1 << CS40L2X_DSP1_EN_SHIFT); - if (ret) { - dev_err(dev, "Failed to enable DSP\n"); - return; + switch (cs40l2x->revid) { + case CS40L2X_REVID_A0: + ret = regmap_update_bits(regmap, CS40L2X_DSP1_CCM_CORE_CTRL, + CS40L2X_DSP1_RESET_MASK | + CS40L2X_DSP1_EN_MASK, + (1 << CS40L2X_DSP1_RESET_SHIFT) | + (1 << CS40L2X_DSP1_EN_SHIFT)); + if (ret) { + dev_err(dev, "Failed to start DSP\n"); + return; + } + break; + default: + ret = regmap_update_bits(regmap, CS40L2X_PWRMGT_CTL, + CS40L2X_MEM_RDY_MASK, + 1 << CS40L2X_MEM_RDY_SHIFT); + if (ret) { + dev_err(dev, "Failed to set memory ready flag\n"); + return; + } + + ret = regmap_update_bits(regmap, CS40L2X_DSP1_CCM_CORE_CTRL, + CS40L2X_DSP1_RESET_MASK, + 1 << CS40L2X_DSP1_RESET_SHIFT); + if (ret) { + dev_err(dev, "Failed to restart DSP\n"); + return; + } } while (dsp_timeout > 0) { @@ -1445,6 +1468,38 @@ static const struct reg_sequence cs40l2x_mpu_config[] = { {CS40L2X_DSP1_MPU_LOCK_CONFIG, 0x00000000} }; +static int cs40l2x_dsp_load(struct cs40l2x_private *cs40l2x) +{ + int ret; + unsigned int revid = cs40l2x->revid; + struct regmap *regmap = cs40l2x->regmap; + struct device *dev = cs40l2x->dev; + + switch (revid) { + case CS40L2X_REVID_A0: + case CS40L2X_REVID_B0: + ret = regmap_multi_reg_write(regmap, cs40l2x_mpu_config, + ARRAY_SIZE(cs40l2x_mpu_config)); + if (ret) { + dev_err(dev, "Failed to configure MPU\n"); + return ret; + } + + request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + CS40L2X_FW_NAME_A0, dev, GFP_KERNEL, cs40l2x, + cs40l2x_firmware_load); + return 0; + case CS40L2X_REVID_B1: + request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + CS40L2X_FW_NAME_B1, dev, GFP_KERNEL, cs40l2x, + cs40l2x_firmware_load); + return 0; + default: + dev_err(dev, "No firmware defined for revision %02X\n", revid); + return -EINVAL; + } +} + static int cs40l2x_init(struct cs40l2x_private *cs40l2x) { int ret; @@ -1516,25 +1571,8 @@ static int cs40l2x_init(struct cs40l2x_private *cs40l2x) return ret; } - ret = regmap_update_bits(regmap, CS40L2X_DSP1_CCM_CORE_CTRL, - CS40L2X_DSP1_RESET_MASK, 1 << CS40L2X_DSP1_RESET_SHIFT); - if (ret) { - dev_err(dev, "Failed to reset DSP\n"); - return ret; - } - - ret = regmap_multi_reg_write(regmap, cs40l2x_mpu_config, - ARRAY_SIZE(cs40l2x_mpu_config)); - if (ret) { - dev_err(dev, "Failed to configure MPU\n"); - return ret; - } - INIT_LIST_HEAD(&cs40l2x->coeff_desc_head); - request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, "cs40l20.wmfw", - dev, GFP_KERNEL, cs40l2x, cs40l2x_firmware_load); - return 0; } @@ -1889,6 +1927,10 @@ static int cs40l2x_i2c_probe(struct i2c_client *i2c_client, if (ret) goto err; + ret = cs40l2x_dsp_load(cs40l2x); + if (ret) + goto err; + return 0; err: gpiod_set_value_cansleep(cs40l2x->reset_gpio, 0); diff --git a/drivers/misc/cs40l2x.h b/drivers/misc/cs40l2x.h index 3593a2e9366a..7abf0aac3421 100644 --- a/drivers/misc/cs40l2x.h +++ b/drivers/misc/cs40l2x.h @@ -544,6 +544,9 @@ #define CS40L2X_GP2_CTRL_SHIFT 24 #define CS40L2X_GP2_CTRL_MCLK 0x3 +#define CS40L2X_MEM_RDY_MASK 0x00000002 +#define CS40L2X_MEM_RDY_SHIFT 1 + #define CS40L2X_PLL_REFCLK_SEL_MASK 0x00000007 #define CS40L2X_PLL_REFCLK_SEL_SHIFT 0 #define CS40L2X_PLL_REFCLK_SEL_MCLK 0x5 @@ -663,6 +666,9 @@ #define CS40L2X_DEVICE_NAME "vibrator" +#define CS40L2X_FW_NAME_A0 "cs40l20.wmfw" +#define CS40L2X_FW_NAME_B1 "cs40l25a.wmfw" + bool cs40l2x_readable_reg(struct device *dev, unsigned int reg); bool cs40l2x_precious_reg(struct device *dev, unsigned int reg);