162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * CS42L43 I2C driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2022-2023 Cirrus Logic, Inc. and 662306a36Sopenharmony_ci * Cirrus Logic International Semiconductor Ltd. 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/err.h> 1062306a36Sopenharmony_ci#include <linux/errno.h> 1162306a36Sopenharmony_ci#include <linux/i2c.h> 1262306a36Sopenharmony_ci#include <linux/mfd/cs42l43-regs.h> 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "cs42l43.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic const struct regmap_config cs42l43_i2c_regmap = { 1862306a36Sopenharmony_ci .reg_bits = 32, 1962306a36Sopenharmony_ci .reg_stride = 4, 2062306a36Sopenharmony_ci .val_bits = 32, 2162306a36Sopenharmony_ci .reg_format_endian = REGMAP_ENDIAN_BIG, 2262306a36Sopenharmony_ci .val_format_endian = REGMAP_ENDIAN_BIG, 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci .max_register = CS42L43_MCU_RAM_MAX, 2562306a36Sopenharmony_ci .readable_reg = cs42l43_readable_register, 2662306a36Sopenharmony_ci .volatile_reg = cs42l43_volatile_register, 2762306a36Sopenharmony_ci .precious_reg = cs42l43_precious_register, 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci .cache_type = REGCACHE_MAPLE, 3062306a36Sopenharmony_ci .reg_defaults = cs42l43_reg_default, 3162306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(cs42l43_reg_default), 3262306a36Sopenharmony_ci}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic int cs42l43_i2c_probe(struct i2c_client *i2c) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci struct cs42l43 *cs42l43; 3762306a36Sopenharmony_ci int ret; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci cs42l43 = devm_kzalloc(&i2c->dev, sizeof(*cs42l43), GFP_KERNEL); 4062306a36Sopenharmony_ci if (!cs42l43) 4162306a36Sopenharmony_ci return -ENOMEM; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci cs42l43->dev = &i2c->dev; 4462306a36Sopenharmony_ci cs42l43->irq = i2c->irq; 4562306a36Sopenharmony_ci /* A device on an I2C is always attached by definition. */ 4662306a36Sopenharmony_ci cs42l43->attached = true; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci cs42l43->regmap = devm_regmap_init_i2c(i2c, &cs42l43_i2c_regmap); 4962306a36Sopenharmony_ci if (IS_ERR(cs42l43->regmap)) { 5062306a36Sopenharmony_ci ret = PTR_ERR(cs42l43->regmap); 5162306a36Sopenharmony_ci dev_err(cs42l43->dev, "Failed to allocate regmap: %d\n", ret); 5262306a36Sopenharmony_ci return ret; 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci return cs42l43_dev_probe(cs42l43); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic void cs42l43_i2c_remove(struct i2c_client *i2c) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci struct cs42l43 *cs42l43 = dev_get_drvdata(&i2c->dev); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci cs42l43_dev_remove(cs42l43); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_OF) 6662306a36Sopenharmony_cistatic const struct of_device_id cs42l43_of_match[] = { 6762306a36Sopenharmony_ci { .compatible = "cirrus,cs42l43", }, 6862306a36Sopenharmony_ci {} 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, cs42l43_of_match); 7162306a36Sopenharmony_ci#endif 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_ACPI) 7462306a36Sopenharmony_cistatic const struct acpi_device_id cs42l43_acpi_match[] = { 7562306a36Sopenharmony_ci { "CSC4243", 0 }, 7662306a36Sopenharmony_ci {} 7762306a36Sopenharmony_ci}; 7862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, cs42l43_acpi_match); 7962306a36Sopenharmony_ci#endif 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic struct i2c_driver cs42l43_i2c_driver = { 8262306a36Sopenharmony_ci .driver = { 8362306a36Sopenharmony_ci .name = "cs42l43", 8462306a36Sopenharmony_ci .pm = pm_ptr(&cs42l43_pm_ops), 8562306a36Sopenharmony_ci .of_match_table = of_match_ptr(cs42l43_of_match), 8662306a36Sopenharmony_ci .acpi_match_table = ACPI_PTR(cs42l43_acpi_match), 8762306a36Sopenharmony_ci }, 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci .probe = cs42l43_i2c_probe, 9062306a36Sopenharmony_ci .remove = cs42l43_i2c_remove, 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_cimodule_i2c_driver(cs42l43_i2c_driver); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ciMODULE_IMPORT_NS(MFD_CS42L43); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ciMODULE_DESCRIPTION("CS42L43 I2C Driver"); 9762306a36Sopenharmony_ciMODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>"); 9862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 99