Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Core driver for WM8400.
0004  *
0005  * Copyright 2008 Wolfson Microelectronics PLC.
0006  *
0007  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
0008  */
0009 
0010 #include <linux/init.h>
0011 #include <linux/bug.h>
0012 #include <linux/err.h>
0013 #include <linux/i2c.h>
0014 #include <linux/kernel.h>
0015 #include <linux/mfd/core.h>
0016 #include <linux/mfd/wm8400-private.h>
0017 #include <linux/mfd/wm8400-audio.h>
0018 #include <linux/regmap.h>
0019 #include <linux/slab.h>
0020 
0021 static bool wm8400_volatile(struct device *dev, unsigned int reg)
0022 {
0023     switch (reg) {
0024     case WM8400_INTERRUPT_STATUS_1:
0025     case WM8400_INTERRUPT_LEVELS:
0026     case WM8400_SHUTDOWN_REASON:
0027         return true;
0028     default:
0029         return false;
0030     }
0031 }
0032 
0033 static int wm8400_register_codec(struct wm8400 *wm8400)
0034 {
0035     const struct mfd_cell cell = {
0036         .name = "wm8400-codec",
0037         .platform_data = wm8400,
0038         .pdata_size = sizeof(*wm8400),
0039     };
0040 
0041     return devm_mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0, NULL);
0042 }
0043 
0044 /*
0045  * wm8400_init - Generic initialisation
0046  *
0047  * The WM8400 can be configured as either an I2C or SPI device.  Probe
0048  * functions for each bus set up the accessors then call into this to
0049  * set up the device itself.
0050  */
0051 static int wm8400_init(struct wm8400 *wm8400,
0052                struct wm8400_platform_data *pdata)
0053 {
0054     unsigned int reg;
0055     int ret;
0056 
0057     dev_set_drvdata(wm8400->dev, wm8400);
0058 
0059     /* Check that this is actually a WM8400 */
0060     ret = regmap_read(wm8400->regmap, WM8400_RESET_ID, &reg);
0061     if (ret != 0) {
0062         dev_err(wm8400->dev, "Chip ID register read failed\n");
0063         return -EIO;
0064     }
0065     if (reg != 0x6172) {
0066         dev_err(wm8400->dev, "Device is not a WM8400, ID is %x\n",
0067             reg);
0068         return -ENODEV;
0069     }
0070 
0071     ret = regmap_read(wm8400->regmap, WM8400_ID, &reg);
0072     if (ret != 0) {
0073         dev_err(wm8400->dev, "ID register read failed: %d\n", ret);
0074         return ret;
0075     }
0076     reg = (reg & WM8400_CHIP_REV_MASK) >> WM8400_CHIP_REV_SHIFT;
0077     dev_info(wm8400->dev, "WM8400 revision %x\n", reg);
0078 
0079     ret = wm8400_register_codec(wm8400);
0080     if (ret != 0) {
0081         dev_err(wm8400->dev, "Failed to register codec\n");
0082         return ret;
0083     }
0084 
0085     if (pdata && pdata->platform_init) {
0086         ret = pdata->platform_init(wm8400->dev);
0087         if (ret != 0) {
0088             dev_err(wm8400->dev, "Platform init failed: %d\n",
0089                 ret);
0090             return ret;
0091         }
0092     } else
0093         dev_warn(wm8400->dev, "No platform initialisation supplied\n");
0094 
0095     return 0;
0096 }
0097 
0098 static const struct regmap_config wm8400_regmap_config = {
0099     .reg_bits = 8,
0100     .val_bits = 16,
0101     .max_register = WM8400_REGISTER_COUNT - 1,
0102 
0103     .volatile_reg = wm8400_volatile,
0104 
0105     .cache_type = REGCACHE_RBTREE,
0106 };
0107 
0108 /**
0109  * wm8400_reset_codec_reg_cache - Reset cached codec registers to
0110  * their default values.
0111  *
0112  * @wm8400: pointer to local driver data structure
0113  */
0114 void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400)
0115 {
0116     regmap_reinit_cache(wm8400->regmap, &wm8400_regmap_config);
0117 }
0118 EXPORT_SYMBOL_GPL(wm8400_reset_codec_reg_cache);
0119 
0120 #if IS_ENABLED(CONFIG_I2C)
0121 static int wm8400_i2c_probe(struct i2c_client *i2c,
0122                 const struct i2c_device_id *id)
0123 {
0124     struct wm8400 *wm8400;
0125 
0126     wm8400 = devm_kzalloc(&i2c->dev, sizeof(struct wm8400), GFP_KERNEL);
0127     if (!wm8400)
0128         return -ENOMEM;
0129 
0130     wm8400->regmap = devm_regmap_init_i2c(i2c, &wm8400_regmap_config);
0131     if (IS_ERR(wm8400->regmap))
0132         return PTR_ERR(wm8400->regmap);
0133 
0134     wm8400->dev = &i2c->dev;
0135     i2c_set_clientdata(i2c, wm8400);
0136 
0137     return wm8400_init(wm8400, dev_get_platdata(&i2c->dev));
0138 }
0139 
0140 static const struct i2c_device_id wm8400_i2c_id[] = {
0141        { "wm8400", 0 },
0142        { }
0143 };
0144 
0145 static struct i2c_driver wm8400_i2c_driver = {
0146     .driver = {
0147         .name = "WM8400",
0148     },
0149     .probe    = wm8400_i2c_probe,
0150     .id_table = wm8400_i2c_id,
0151 };
0152 #endif
0153 
0154 static int __init wm8400_driver_init(void)
0155 {
0156     int ret = -ENODEV;
0157 
0158 #if IS_ENABLED(CONFIG_I2C)
0159     ret = i2c_add_driver(&wm8400_i2c_driver);
0160     if (ret != 0)
0161         pr_err("Failed to register I2C driver: %d\n", ret);
0162 #endif
0163 
0164     return ret;
0165 }
0166 subsys_initcall(wm8400_driver_init);