12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2e5b48684SMark Brown /* 3e5b48684SMark Brown * wm831x-i2c.c -- I2C access for Wolfson WM831x PMICs 4e5b48684SMark Brown * 5e5b48684SMark Brown * Copyright 2009,2010 Wolfson Microelectronics PLC. 6e5b48684SMark Brown * 7e5b48684SMark Brown * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 8e5b48684SMark Brown */ 9e5b48684SMark Brown 10e5b48684SMark Brown #include <linux/kernel.h> 11af5db808SPaul Gortmaker #include <linux/init.h> 12e5b48684SMark Brown #include <linux/i2c.h> 13e5b48684SMark Brown #include <linux/delay.h> 14e5b48684SMark Brown #include <linux/mfd/core.h> 15e5b48684SMark Brown #include <linux/slab.h> 161df5981bSMark Brown #include <linux/err.h> 17f6dd8449SCharles Keepax #include <linux/of.h> 18f6dd8449SCharles Keepax #include <linux/of_device.h> 191df5981bSMark Brown #include <linux/regmap.h> 20e5b48684SMark Brown 21e5b48684SMark Brown #include <linux/mfd/wm831x/core.h> 22e5b48684SMark Brown #include <linux/mfd/wm831x/pdata.h> 23e5b48684SMark Brown 24*5fb66be1SUwe Kleine-König static int wm831x_i2c_probe(struct i2c_client *i2c) 25e5b48684SMark Brown { 26*5fb66be1SUwe Kleine-König const struct i2c_device_id *id = i2c_client_get_device_id(i2c); 27f6dd8449SCharles Keepax struct wm831x_pdata *pdata = dev_get_platdata(&i2c->dev); 28f6dd8449SCharles Keepax const struct of_device_id *of_id; 29e5b48684SMark Brown struct wm831x *wm831x; 30f6dd8449SCharles Keepax enum wm831x_parent type; 311df5981bSMark Brown int ret; 32e5b48684SMark Brown 33f6dd8449SCharles Keepax if (i2c->dev.of_node) { 34f6dd8449SCharles Keepax of_id = of_match_device(wm831x_of_match, &i2c->dev); 35800e5455SGustavo A. R. Silva if (!of_id) { 36800e5455SGustavo A. R. Silva dev_err(&i2c->dev, "Failed to match device\n"); 37800e5455SGustavo A. R. Silva return -ENODEV; 38800e5455SGustavo A. R. Silva } 39f6dd8449SCharles Keepax type = (enum wm831x_parent)of_id->data; 40f6dd8449SCharles Keepax } else { 41f6dd8449SCharles Keepax type = (enum wm831x_parent)id->driver_data; 42f6dd8449SCharles Keepax } 43f6dd8449SCharles Keepax 44d48cbb74SMark Brown wm831x = devm_kzalloc(&i2c->dev, sizeof(struct wm831x), GFP_KERNEL); 45e5b48684SMark Brown if (wm831x == NULL) 46e5b48684SMark Brown return -ENOMEM; 47e5b48684SMark Brown 48e5b48684SMark Brown i2c_set_clientdata(i2c, wm831x); 49e5b48684SMark Brown wm831x->dev = &i2c->dev; 50f6dd8449SCharles Keepax wm831x->type = type; 511df5981bSMark Brown 52130a7032SMark Brown wm831x->regmap = devm_regmap_init_i2c(i2c, &wm831x_regmap_config); 531df5981bSMark Brown if (IS_ERR(wm831x->regmap)) { 541df5981bSMark Brown ret = PTR_ERR(wm831x->regmap); 551df5981bSMark Brown dev_err(wm831x->dev, "Failed to allocate register map: %d\n", 561df5981bSMark Brown ret); 571df5981bSMark Brown return ret; 581df5981bSMark Brown } 59e5b48684SMark Brown 60f6dd8449SCharles Keepax if (pdata) 61f6dd8449SCharles Keepax memcpy(&wm831x->pdata, pdata, sizeof(*pdata)); 62f6dd8449SCharles Keepax 63f6dd8449SCharles Keepax return wm831x_device_init(wm831x, i2c->irq); 64e5b48684SMark Brown } 65e5b48684SMark Brown 66c538ddbeSMark Brown static int wm831x_i2c_suspend(struct device *dev) 67e5b48684SMark Brown { 68c538ddbeSMark Brown struct wm831x *wm831x = dev_get_drvdata(dev); 69e5b48684SMark Brown 70e5b48684SMark Brown return wm831x_device_suspend(wm831x); 71e5b48684SMark Brown } 72e5b48684SMark Brown 73b9736a16SMark Brown static int wm831x_i2c_poweroff(struct device *dev) 74523d9cfbSMark Brown { 75b9736a16SMark Brown struct wm831x *wm831x = dev_get_drvdata(dev); 76523d9cfbSMark Brown 77523d9cfbSMark Brown wm831x_device_shutdown(wm831x); 78b9736a16SMark Brown 79b9736a16SMark Brown return 0; 80523d9cfbSMark Brown } 81523d9cfbSMark Brown 82e5b48684SMark Brown static const struct i2c_device_id wm831x_i2c_id[] = { 83e5b48684SMark Brown { "wm8310", WM8310 }, 84e5b48684SMark Brown { "wm8311", WM8311 }, 85e5b48684SMark Brown { "wm8312", WM8312 }, 86e5b48684SMark Brown { "wm8320", WM8320 }, 87e5b48684SMark Brown { "wm8321", WM8321 }, 88e5b48684SMark Brown { "wm8325", WM8325 }, 89412dc11dSMark Brown { "wm8326", WM8326 }, 90e5b48684SMark Brown { } 91e5b48684SMark Brown }; 92e5b48684SMark Brown 93c538ddbeSMark Brown static const struct dev_pm_ops wm831x_pm_ops = { 94c538ddbeSMark Brown .suspend = wm831x_i2c_suspend, 95b9736a16SMark Brown .poweroff = wm831x_i2c_poweroff, 96c538ddbeSMark Brown }; 97e5b48684SMark Brown 98e5b48684SMark Brown static struct i2c_driver wm831x_i2c_driver = { 99e5b48684SMark Brown .driver = { 100e5b48684SMark Brown .name = "wm831x", 101c538ddbeSMark Brown .pm = &wm831x_pm_ops, 102f6dd8449SCharles Keepax .of_match_table = of_match_ptr(wm831x_of_match), 103af5db808SPaul Gortmaker .suppress_bind_attrs = true, 104e5b48684SMark Brown }, 105*5fb66be1SUwe Kleine-König .probe_new = wm831x_i2c_probe, 106e5b48684SMark Brown .id_table = wm831x_i2c_id, 107e5b48684SMark Brown }; 108e5b48684SMark Brown 109e5b48684SMark Brown static int __init wm831x_i2c_init(void) 110e5b48684SMark Brown { 111e5b48684SMark Brown int ret; 112e5b48684SMark Brown 113e5b48684SMark Brown ret = i2c_add_driver(&wm831x_i2c_driver); 114e5b48684SMark Brown if (ret != 0) 115e5b48684SMark Brown pr_err("Failed to register wm831x I2C driver: %d\n", ret); 116e5b48684SMark Brown 117e5b48684SMark Brown return ret; 118e5b48684SMark Brown } 119e5b48684SMark Brown subsys_initcall(wm831x_i2c_init); 120