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
wm831x_i2c_probe(struct i2c_client * i2c)245fb66be1SUwe Kleine-König static int wm831x_i2c_probe(struct i2c_client *i2c)
25e5b48684SMark Brown {
265fb66be1SUwe 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 }
39*4e57d142SKrzysztof Kozlowski type = (uintptr_t)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
wm831x_i2c_suspend(struct device * dev)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
wm831x_i2c_poweroff(struct device * dev)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 },
1059816d859SUwe Kleine-König .probe = wm831x_i2c_probe,
106e5b48684SMark Brown .id_table = wm831x_i2c_id,
107e5b48684SMark Brown };
108e5b48684SMark Brown
wm831x_i2c_init(void)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