cs48l32
int cs48l32_apply_patch(struct cs48l32 *cs48l32)
ret = regmap_register_patch(cs48l32->regmap, cs48l32_reva_patch,
return dev_err_probe(cs48l32->dev, ret, "Failed to apply patch\n");
int cs48l32_create_regmap(struct spi_device *spi, struct cs48l32 *cs48l32)
cs48l32->regmap = devm_regmap_init_spi(spi, &cs48l32_regmap);
return PTR_ERR_OR_ZERO(cs48l32->regmap);
struct cs48l32 *cs48l32 = &fll->codec->core;
regmap_set_bits(cs48l32->regmap,
regmap_clear_bits(cs48l32->regmap,
regmap_set_bits(cs48l32->regmap,
regmap_update_bits_check(cs48l32->regmap,
regmap_clear_bits(cs48l32->regmap,
pm_runtime_put_autosuspend(cs48l32->dev);
struct cs48l32 *cs48l32 = &fll->codec->core;
pm_runtime_get_sync(cs48l32->dev);
regmap_set_bits(cs48l32->regmap,
regmap_update_bits(cs48l32->regmap,
regmap_set_bits(cs48l32->regmap,
regmap_set_bits(cs48l32->regmap,
regmap_set_bits(cs48l32->regmap,
regmap_clear_bits(cs48l32->regmap,
struct cs48l32 *cs48l32 = &cs48l32_codec->core;
if (pm_runtime_suspended(cs48l32->dev))
ret = regmap_read(cs48l32->regmap, CS48L32_DEVID, &val);
struct cs48l32 *cs48l32 = &cs48l32_codec->core;
ret = device_property_read_u32_array(cs48l32->dev, propname, dest, n_max);
return dev_err_probe(cs48l32->dev, ret, "%s malformed\n", propname);
static int cs48l32_wait_for_boot(struct cs48l32 *cs48l32)
ret = regmap_read_poll_timeout(cs48l32->regmap, CS48L32_IRQ1_EINT_2, val,
dev_err(cs48l32->dev, "BOOT_DONE timed out\n");
ret = regmap_read(cs48l32->regmap, CS48L32_MCU_CTRL1, &val);
dev_err(cs48l32->dev, "Failed to read MCU_CTRL1: %d\n", ret);
dev_err(cs48l32->dev, "MCU boot failed\n");
pm_runtime_mark_last_busy(cs48l32->dev);
static int cs48l32_soft_reset(struct cs48l32 *cs48l32)
ret = regmap_write(cs48l32->regmap, CS48L32_SFT_RESET, CS48L32_SFT_RESET_MAGIC);
dev_err(cs48l32->dev, "Failed to write soft reset: %d\n", ret);
static void cs48l32_enable_hard_reset(struct cs48l32 *cs48l32)
if (cs48l32->reset_gpio)
gpiod_set_raw_value_cansleep(cs48l32->reset_gpio, 0);
static void cs48l32_disable_hard_reset(struct cs48l32 *cs48l32)
if (cs48l32->reset_gpio) {
gpiod_set_raw_value_cansleep(cs48l32->reset_gpio, 1);
struct cs48l32 *cs48l32 = &cs48l32_codec->core;
ret = regulator_enable(cs48l32->vdd_d);
dev_err(cs48l32->dev, "Failed to enable VDD_D: %d\n", ret);
regcache_cache_only(cs48l32->regmap, false);
ret = cs48l32_wait_for_boot(cs48l32);
regmap_read(cs48l32->regmap, CS48L32_CTRL_IF_DEBUG3, &val);
regcache_mark_dirty(cs48l32->regmap);
dev_dbg(cs48l32->dev, "Did not reset during suspend\n");
ret = regcache_sync(cs48l32->regmap);
dev_err(cs48l32->dev, "Failed to restore register cache\n");
regcache_cache_only(cs48l32->regmap, true);
regulator_disable(cs48l32->vdd_d);
struct cs48l32 *cs48l32 = &cs48l32_codec->core;
regmap_write(cs48l32->regmap, CS48L32_CTRL_IF_DEBUG3, 1);
regcache_cache_only(cs48l32->regmap, true);
regulator_disable(cs48l32->vdd_d);
static int cs48l32_configure_clk32k(struct cs48l32 *cs48l32)
ret = clk_prepare_enable(cs48l32->mclk1);
return dev_err_probe(cs48l32->dev, ret, "Failed to enable 32k clock\n");
ret = regmap_update_bits(cs48l32->regmap, CS48L32_CLOCK32K,
clk_disable_unprepare(cs48l32->mclk1);
return dev_err_probe(cs48l32->dev, ret, "Failed to init 32k clock\n");
static int cs48l32_get_clocks(struct cs48l32 *cs48l32)
cs48l32->mclk1 = devm_clk_get_optional(cs48l32->dev, "mclk1");
if (IS_ERR(cs48l32->mclk1))
return dev_err_probe(cs48l32->dev, PTR_ERR(cs48l32->mclk1),
static int cs48l32_get_reset_gpio(struct cs48l32 *cs48l32)
reset = devm_gpiod_get_optional(cs48l32->dev, "reset", GPIOD_OUT_LOW);
return dev_err_probe(cs48l32->dev, PTR_ERR(reset), "Failed to request /RESET\n");
cs48l32->reset_gpio = reset;
struct cs48l32 *cs48l32;
cs48l32 = &cs48l32_codec->core;
cs48l32->dev = dev;
cs48l32->irq = spi->irq;
dev_set_drvdata(cs48l32->dev, cs48l32_codec);
ret = cs48l32_create_regmap(spi, cs48l32);
regcache_cache_only(cs48l32->regmap, true);
ret = cs48l32_get_reset_gpio(cs48l32);
ret = cs48l32_get_clocks(cs48l32);
static_assert(ARRAY_SIZE(cs48l32_core_supplies) == ARRAY_SIZE(cs48l32->core_supplies));
for (i = 0; i < ARRAY_SIZE(cs48l32->core_supplies); i++)
cs48l32->core_supplies[i].supply = cs48l32_core_supplies[i];
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(cs48l32->core_supplies),
cs48l32->core_supplies);
cs48l32->vdd_d = devm_regulator_get(cs48l32->dev, "vdd-d");
if (IS_ERR(cs48l32->vdd_d))
return dev_err_probe(dev, PTR_ERR(cs48l32->vdd_d), "Failed to request vdd-d\n");
ret = regulator_bulk_enable(ARRAY_SIZE(cs48l32->core_supplies), cs48l32->core_supplies);
ret = regulator_enable(cs48l32->vdd_d);
cs48l32_disable_hard_reset(cs48l32);
regcache_cache_only(cs48l32->regmap, false);
if (!cs48l32->reset_gpio) {
ret = cs48l32_soft_reset(cs48l32);
ret = cs48l32_wait_for_boot(cs48l32);
dev_err(cs48l32->dev, "Device failed initial boot: %d\n", ret);
ret = regmap_read(cs48l32->regmap, CS48L32_DEVID, &hwid);
dev_err_probe(cs48l32->dev, ret, "Unknown device ID: %#x\n", hwid);
ret = regmap_read(cs48l32->regmap, CS48L32_REVID, &rev);
ret = regmap_read(cs48l32->regmap, CS48L32_OTPID, &otp_rev);
ret = cs48l32_apply_patch(cs48l32);
dev_err(cs48l32->dev, "Failed to apply patch %d\n", ret);
ret = regmap_set_bits(cs48l32->regmap, CS48L32_IRQ1_MASK_2, CS48L32_BOOT_DONE_EINT1_MASK);
ret = cs48l32_configure_clk32k(cs48l32);
pm_runtime_set_active(cs48l32->dev);
pm_runtime_set_autosuspend_delay(cs48l32->dev, 100);
pm_runtime_use_autosuspend(cs48l32->dev);
pm_runtime_enable(cs48l32->dev);
clk_disable_unprepare(cs48l32->mclk1);
cs48l32_enable_hard_reset(cs48l32);
regulator_disable(cs48l32->vdd_d);
regulator_bulk_disable(ARRAY_SIZE(cs48l32->core_supplies), cs48l32->core_supplies);
struct cs48l32 *cs48l32 = &cs48l32_codec->core;
if (cs48l32->irq >= 1)
free_irq(cs48l32->irq, cs48l32_codec);
pm_runtime_disable(cs48l32->dev);
regulator_disable(cs48l32->vdd_d);
clk_disable_unprepare(cs48l32->mclk1);
cs48l32_enable_hard_reset(cs48l32);
regulator_bulk_disable(ARRAY_SIZE(cs48l32->core_supplies), cs48l32->core_supplies);
struct cs48l32;
struct cs48l32 core;
int cs48l32_apply_patch(struct cs48l32 *cs48l32);
int cs48l32_create_regmap(struct spi_device *spi, struct cs48l32 *cs48l32);