xref: /openbmc/linux/drivers/mfd/wm831x-i2c.c (revision 4e57d142)
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