1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2c6f75622SMark Brown /*
3c6f75622SMark Brown * Arizona-i2c.c -- Arizona I2C bus interface
4c6f75622SMark Brown *
5c6f75622SMark Brown * Copyright 2012 Wolfson Microelectronics plc
6c6f75622SMark Brown *
7c6f75622SMark Brown * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8c6f75622SMark Brown */
9c6f75622SMark Brown
10c6f75622SMark Brown #include <linux/err.h>
11c6f75622SMark Brown #include <linux/i2c.h>
12c6f75622SMark Brown #include <linux/module.h>
13c6f75622SMark Brown #include <linux/pm_runtime.h>
14c6f75622SMark Brown #include <linux/regmap.h>
15c6f75622SMark Brown #include <linux/regulator/consumer.h>
16c6f75622SMark Brown #include <linux/slab.h>
173d6d1d1cSSachin Kamat #include <linux/of.h>
18c6f75622SMark Brown
19c6f75622SMark Brown #include <linux/mfd/arizona/core.h>
20c6f75622SMark Brown
21c6f75622SMark Brown #include "arizona.h"
22c6f75622SMark Brown
arizona_i2c_probe(struct i2c_client * i2c)236cb7ac1cSUwe Kleine-König static int arizona_i2c_probe(struct i2c_client *i2c)
24c6f75622SMark Brown {
256cb7ac1cSUwe Kleine-König const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
26039da225SHans de Goede const void *match_data;
27c6f75622SMark Brown struct arizona *arizona;
28b61c1ec0SRichard Fitzgerald const struct regmap_config *regmap_config = NULL;
29039da225SHans de Goede unsigned long type = 0;
30942786e6SLee Jones int ret;
31c6f75622SMark Brown
32039da225SHans de Goede match_data = device_get_match_data(&i2c->dev);
33039da225SHans de Goede if (match_data)
34039da225SHans de Goede type = (unsigned long)match_data;
35039da225SHans de Goede else if (id)
36d781009cSMark Brown type = id->driver_data;
37d781009cSMark Brown
38d781009cSMark Brown switch (type) {
39c6f75622SMark Brown case WM5102:
40b61c1ec0SRichard Fitzgerald if (IS_ENABLED(CONFIG_MFD_WM5102))
41c6f75622SMark Brown regmap_config = &wm5102_i2c_regmap;
42c6f75622SMark Brown break;
43e102befeSMark Brown case WM5110:
44e5d4ef0dSRichard Fitzgerald case WM8280:
45b61c1ec0SRichard Fitzgerald if (IS_ENABLED(CONFIG_MFD_WM5110))
46e102befeSMark Brown regmap_config = &wm5110_i2c_regmap;
47e102befeSMark Brown break;
48dc7d4863SCharles Keepax case WM8997:
49b61c1ec0SRichard Fitzgerald if (IS_ENABLED(CONFIG_MFD_WM8997))
50dc7d4863SCharles Keepax regmap_config = &wm8997_i2c_regmap;
51dc7d4863SCharles Keepax break;
526887b042SRichard Fitzgerald case WM8998:
536887b042SRichard Fitzgerald case WM1814:
54b61c1ec0SRichard Fitzgerald if (IS_ENABLED(CONFIG_MFD_WM8998))
556887b042SRichard Fitzgerald regmap_config = &wm8998_i2c_regmap;
566887b042SRichard Fitzgerald break;
57c6f75622SMark Brown default:
582e44e28aSRichard Fitzgerald dev_err(&i2c->dev, "Unknown device type %ld\n", type);
59c6f75622SMark Brown return -EINVAL;
60c6f75622SMark Brown }
61c6f75622SMark Brown
62b61c1ec0SRichard Fitzgerald if (!regmap_config) {
63b61c1ec0SRichard Fitzgerald dev_err(&i2c->dev,
64b61c1ec0SRichard Fitzgerald "No kernel support for device type %ld\n", type);
65b61c1ec0SRichard Fitzgerald return -EINVAL;
66b61c1ec0SRichard Fitzgerald }
67b61c1ec0SRichard Fitzgerald
68c6f75622SMark Brown arizona = devm_kzalloc(&i2c->dev, sizeof(*arizona), GFP_KERNEL);
69c6f75622SMark Brown if (arizona == NULL)
70c6f75622SMark Brown return -ENOMEM;
71c6f75622SMark Brown
72c6f75622SMark Brown arizona->regmap = devm_regmap_init_i2c(i2c, regmap_config);
73c6f75622SMark Brown if (IS_ERR(arizona->regmap)) {
74c6f75622SMark Brown ret = PTR_ERR(arizona->regmap);
75c6f75622SMark Brown dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
76c6f75622SMark Brown ret);
77c6f75622SMark Brown return ret;
78c6f75622SMark Brown }
79c6f75622SMark Brown
802e44e28aSRichard Fitzgerald arizona->type = type;
81c6f75622SMark Brown arizona->dev = &i2c->dev;
82c6f75622SMark Brown arizona->irq = i2c->irq;
83c6f75622SMark Brown
84c6f75622SMark Brown return arizona_dev_init(arizona);
85c6f75622SMark Brown }
86c6f75622SMark Brown
arizona_i2c_remove(struct i2c_client * i2c)87ed5c2f5fSUwe Kleine-König static void arizona_i2c_remove(struct i2c_client *i2c)
88c6f75622SMark Brown {
89c6f75622SMark Brown struct arizona *arizona = dev_get_drvdata(&i2c->dev);
909f6e872aSLee Jones
91c6f75622SMark Brown arizona_dev_exit(arizona);
92c6f75622SMark Brown }
93c6f75622SMark Brown
94c6f75622SMark Brown static const struct i2c_device_id arizona_i2c_id[] = {
95c6f75622SMark Brown { "wm5102", WM5102 },
96e102befeSMark Brown { "wm5110", WM5110 },
97e5d4ef0dSRichard Fitzgerald { "wm8280", WM8280 },
98dc7d4863SCharles Keepax { "wm8997", WM8997 },
996887b042SRichard Fitzgerald { "wm8998", WM8998 },
1006887b042SRichard Fitzgerald { "wm1814", WM1814 },
101c6f75622SMark Brown { }
102c6f75622SMark Brown };
103c6f75622SMark Brown MODULE_DEVICE_TABLE(i2c, arizona_i2c_id);
104c6f75622SMark Brown
1053f65555cSCharles Keepax #ifdef CONFIG_OF
10610377bb2SCharles Keepax static const struct of_device_id arizona_i2c_of_match[] = {
1073f65555cSCharles Keepax { .compatible = "wlf,wm5102", .data = (void *)WM5102 },
1083f65555cSCharles Keepax { .compatible = "wlf,wm5110", .data = (void *)WM5110 },
1093f65555cSCharles Keepax { .compatible = "wlf,wm8280", .data = (void *)WM8280 },
1103f65555cSCharles Keepax { .compatible = "wlf,wm8997", .data = (void *)WM8997 },
1113f65555cSCharles Keepax { .compatible = "wlf,wm8998", .data = (void *)WM8998 },
1123f65555cSCharles Keepax { .compatible = "wlf,wm1814", .data = (void *)WM1814 },
1133f65555cSCharles Keepax {},
1143f65555cSCharles Keepax };
11588165679SAndré Apitzsch MODULE_DEVICE_TABLE(of, arizona_i2c_of_match);
1163f65555cSCharles Keepax #endif
1173f65555cSCharles Keepax
118c6f75622SMark Brown static struct i2c_driver arizona_i2c_driver = {
119c6f75622SMark Brown .driver = {
120c6f75622SMark Brown .name = "arizona",
12150d3ac7dSPaul Cercueil .pm = pm_ptr(&arizona_pm_ops),
1223f65555cSCharles Keepax .of_match_table = of_match_ptr(arizona_i2c_of_match),
123c6f75622SMark Brown },
124*9816d859SUwe Kleine-König .probe = arizona_i2c_probe,
12584449216SBill Pemberton .remove = arizona_i2c_remove,
126c6f75622SMark Brown .id_table = arizona_i2c_id,
127c6f75622SMark Brown };
128c6f75622SMark Brown
129c6f75622SMark Brown module_i2c_driver(arizona_i2c_driver);
130c6f75622SMark Brown
13106e577b4SHans de Goede MODULE_SOFTDEP("pre: arizona_ldo1");
132c6f75622SMark Brown MODULE_DESCRIPTION("Arizona I2C bus interface");
133c6f75622SMark Brown MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
134c6f75622SMark Brown MODULE_LICENSE("GPL");
135