blob: 3ed810e81f631b0ade6bfbbdd8f30fa74ae4088c [file] [log] [blame]
Thomas Gleixnerd2912cb2019-06-04 10:11:33 +02001// SPDX-License-Identifier: GPL-2.0-only
Mark Brownc6f75622012-06-19 16:35:49 +01002/*
3 * Arizona-i2c.c -- Arizona I2C bus interface
4 *
5 * Copyright 2012 Wolfson Microelectronics plc
6 *
7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
Mark Brownc6f75622012-06-19 16:35:49 +01008 */
9
10#include <linux/err.h>
11#include <linux/i2c.h>
12#include <linux/module.h>
13#include <linux/pm_runtime.h>
14#include <linux/regmap.h>
15#include <linux/regulator/consumer.h>
16#include <linux/slab.h>
Sachin Kamat3d6d1d12013-10-16 14:26:56 +053017#include <linux/of.h>
Mark Brownc6f75622012-06-19 16:35:49 +010018
19#include <linux/mfd/arizona/core.h>
20
21#include "arizona.h"
22
Bill Pembertonf791be42012-11-19 13:23:04 -050023static int arizona_i2c_probe(struct i2c_client *i2c,
Lee Jones942786e2014-07-02 14:28:46 +010024 const struct i2c_device_id *id)
Mark Brownc6f75622012-06-19 16:35:49 +010025{
Hans de Goede039da222021-01-20 22:49:54 +010026 const void *match_data;
Mark Brownc6f75622012-06-19 16:35:49 +010027 struct arizona *arizona;
Richard Fitzgeraldb61c1ec2015-10-02 13:29:14 +010028 const struct regmap_config *regmap_config = NULL;
Hans de Goede039da222021-01-20 22:49:54 +010029 unsigned long type = 0;
Lee Jones942786e2014-07-02 14:28:46 +010030 int ret;
Mark Brownc6f75622012-06-19 16:35:49 +010031
Hans de Goede039da222021-01-20 22:49:54 +010032 match_data = device_get_match_data(&i2c->dev);
33 if (match_data)
34 type = (unsigned long)match_data;
35 else if (id)
Mark Brownd7810092013-03-25 00:11:27 +000036 type = id->driver_data;
37
38 switch (type) {
Mark Brownc6f75622012-06-19 16:35:49 +010039 case WM5102:
Richard Fitzgeraldb61c1ec2015-10-02 13:29:14 +010040 if (IS_ENABLED(CONFIG_MFD_WM5102))
41 regmap_config = &wm5102_i2c_regmap;
Mark Brownc6f75622012-06-19 16:35:49 +010042 break;
Mark Browne102bef2012-07-10 12:37:58 +010043 case WM5110:
Richard Fitzgeralde5d4ef02015-01-17 15:21:22 +000044 case WM8280:
Richard Fitzgeraldb61c1ec2015-10-02 13:29:14 +010045 if (IS_ENABLED(CONFIG_MFD_WM5110))
46 regmap_config = &wm5110_i2c_regmap;
Mark Browne102bef2012-07-10 12:37:58 +010047 break;
Charles Keepaxdc7d4862013-06-13 09:43:29 +010048 case WM8997:
Richard Fitzgeraldb61c1ec2015-10-02 13:29:14 +010049 if (IS_ENABLED(CONFIG_MFD_WM8997))
50 regmap_config = &wm8997_i2c_regmap;
Charles Keepaxdc7d4862013-06-13 09:43:29 +010051 break;
Richard Fitzgerald6887b042015-07-03 16:16:35 +010052 case WM8998:
53 case WM1814:
Richard Fitzgeraldb61c1ec2015-10-02 13:29:14 +010054 if (IS_ENABLED(CONFIG_MFD_WM8998))
55 regmap_config = &wm8998_i2c_regmap;
Richard Fitzgerald6887b042015-07-03 16:16:35 +010056 break;
Mark Brownc6f75622012-06-19 16:35:49 +010057 default:
Richard Fitzgerald2e44e282015-10-02 13:29:15 +010058 dev_err(&i2c->dev, "Unknown device type %ld\n", type);
Mark Brownc6f75622012-06-19 16:35:49 +010059 return -EINVAL;
60 }
61
Richard Fitzgeraldb61c1ec2015-10-02 13:29:14 +010062 if (!regmap_config) {
63 dev_err(&i2c->dev,
64 "No kernel support for device type %ld\n", type);
65 return -EINVAL;
66 }
67
Mark Brownc6f75622012-06-19 16:35:49 +010068 arizona = devm_kzalloc(&i2c->dev, sizeof(*arizona), GFP_KERNEL);
69 if (arizona == NULL)
70 return -ENOMEM;
71
72 arizona->regmap = devm_regmap_init_i2c(i2c, regmap_config);
73 if (IS_ERR(arizona->regmap)) {
74 ret = PTR_ERR(arizona->regmap);
75 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
76 ret);
77 return ret;
78 }
79
Richard Fitzgerald2e44e282015-10-02 13:29:15 +010080 arizona->type = type;
Mark Brownc6f75622012-06-19 16:35:49 +010081 arizona->dev = &i2c->dev;
82 arizona->irq = i2c->irq;
83
84 return arizona_dev_init(arizona);
85}
86
Bill Pemberton4740f732012-11-19 13:26:01 -050087static int arizona_i2c_remove(struct i2c_client *i2c)
Mark Brownc6f75622012-06-19 16:35:49 +010088{
89 struct arizona *arizona = dev_get_drvdata(&i2c->dev);
Lee Jones9f6e8722015-10-28 13:54:07 +000090
Mark Brownc6f75622012-06-19 16:35:49 +010091 arizona_dev_exit(arizona);
Lee Jones9f6e8722015-10-28 13:54:07 +000092
Mark Brownc6f75622012-06-19 16:35:49 +010093 return 0;
94}
95
96static const struct i2c_device_id arizona_i2c_id[] = {
97 { "wm5102", WM5102 },
Mark Browne102bef2012-07-10 12:37:58 +010098 { "wm5110", WM5110 },
Richard Fitzgeralde5d4ef02015-01-17 15:21:22 +000099 { "wm8280", WM8280 },
Charles Keepaxdc7d4862013-06-13 09:43:29 +0100100 { "wm8997", WM8997 },
Richard Fitzgerald6887b042015-07-03 16:16:35 +0100101 { "wm8998", WM8998 },
102 { "wm1814", WM1814 },
Mark Brownc6f75622012-06-19 16:35:49 +0100103 { }
104};
105MODULE_DEVICE_TABLE(i2c, arizona_i2c_id);
106
Charles Keepax3f655552021-09-28 17:30:35 +0100107#ifdef CONFIG_OF
108const struct of_device_id arizona_i2c_of_match[] = {
109 { .compatible = "wlf,wm5102", .data = (void *)WM5102 },
110 { .compatible = "wlf,wm5110", .data = (void *)WM5110 },
111 { .compatible = "wlf,wm8280", .data = (void *)WM8280 },
112 { .compatible = "wlf,wm8997", .data = (void *)WM8997 },
113 { .compatible = "wlf,wm8998", .data = (void *)WM8998 },
114 { .compatible = "wlf,wm1814", .data = (void *)WM1814 },
115 {},
116};
117#endif
118
Mark Brownc6f75622012-06-19 16:35:49 +0100119static struct i2c_driver arizona_i2c_driver = {
120 .driver = {
121 .name = "arizona",
Mark Brownc6f75622012-06-19 16:35:49 +0100122 .pm = &arizona_pm_ops,
Charles Keepax3f655552021-09-28 17:30:35 +0100123 .of_match_table = of_match_ptr(arizona_i2c_of_match),
Mark Brownc6f75622012-06-19 16:35:49 +0100124 },
125 .probe = arizona_i2c_probe,
Bill Pemberton84449212012-11-19 13:20:24 -0500126 .remove = arizona_i2c_remove,
Mark Brownc6f75622012-06-19 16:35:49 +0100127 .id_table = arizona_i2c_id,
128};
129
130module_i2c_driver(arizona_i2c_driver);
131
Hans de Goede06e577b2021-01-20 22:49:53 +0100132MODULE_SOFTDEP("pre: arizona_ldo1");
Mark Brownc6f75622012-06-19 16:35:49 +0100133MODULE_DESCRIPTION("Arizona I2C bus interface");
134MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
135MODULE_LICENSE("GPL");