Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/extcon/extcon-max14526.c
29509 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
3
#include <linux/device.h>
4
#include <linux/devm-helpers.h>
5
#include <linux/delay.h>
6
#include <linux/err.h>
7
#include <linux/extcon-provider.h>
8
#include <linux/i2c.h>
9
#include <linux/mod_devicetable.h>
10
#include <linux/interrupt.h>
11
#include <linux/module.h>
12
#include <linux/pm.h>
13
#include <linux/regmap.h>
14
15
/* I2C addresses of MUIC internal registers */
16
#define MAX14526_DEVICE_ID 0x00
17
#define MAX14526_ID 0x02
18
19
/* CONTROL_1 register masks */
20
#define MAX14526_CONTROL_1 0x01
21
#define ID_2P2 BIT(6)
22
#define ID_620 BIT(5)
23
#define ID_200 BIT(4)
24
#define VLDO BIT(3)
25
#define SEMREN BIT(2)
26
#define ADC_EN BIT(1)
27
#define CP_EN BIT(0)
28
29
/* CONTROL_2 register masks */
30
#define MAX14526_CONTROL_2 0x02
31
#define INTPOL BIT(7)
32
#define INT_EN BIT(6)
33
#define MIC_LP BIT(5)
34
#define CP_AUD BIT(4)
35
#define CHG_TYPE BIT(1)
36
#define USB_DET_DIS BIT(0)
37
38
/* SW_CONTROL register masks */
39
#define MAX14526_SW_CONTROL 0x03
40
#define SW_DATA 0x00
41
#define SW_UART 0x01
42
#define SW_AUDIO 0x02
43
#define SW_OPEN 0x07
44
45
/* INT_STATUS register masks */
46
#define MAX14526_INT_STAT 0x04
47
#define CHGDET BIT(7)
48
#define MR_COMP BIT(6)
49
#define SENDEND BIT(5)
50
#define V_VBUS BIT(4)
51
52
/* STATUS register masks */
53
#define MAX14526_STATUS 0x05
54
#define CPORT BIT(7)
55
#define CHPORT BIT(6)
56
#define C1COMP BIT(0)
57
58
enum max14526_idno_resistance {
59
MAX14526_GND,
60
MAX14526_24KOHM,
61
MAX14526_56KOHM,
62
MAX14526_100KOHM,
63
MAX14526_130KOHM,
64
MAX14526_180KOHM,
65
MAX14526_240KOHM,
66
MAX14526_330KOHM,
67
MAX14526_430KOHM,
68
MAX14526_620KOHM,
69
MAX14526_910KOHM,
70
MAX14526_OPEN
71
};
72
73
enum max14526_field_idx {
74
VENDOR_ID, CHIP_REV, /* DEVID */
75
DM, DP, /* SW_CONTROL */
76
MAX14526_N_REGMAP_FIELDS
77
};
78
79
static const struct reg_field max14526_reg_field[MAX14526_N_REGMAP_FIELDS] = {
80
[VENDOR_ID] = REG_FIELD(MAX14526_DEVICE_ID, 4, 7),
81
[CHIP_REV] = REG_FIELD(MAX14526_DEVICE_ID, 0, 3),
82
[DM] = REG_FIELD(MAX14526_SW_CONTROL, 0, 2),
83
[DP] = REG_FIELD(MAX14526_SW_CONTROL, 3, 5),
84
};
85
86
struct max14526_data {
87
struct i2c_client *client;
88
struct extcon_dev *edev;
89
90
struct regmap *regmap;
91
struct regmap_field *rfield[MAX14526_N_REGMAP_FIELDS];
92
93
int last_state;
94
int cable;
95
};
96
97
enum max14526_muic_modes {
98
MAX14526_OTG = MAX14526_GND, /* no power */
99
MAX14526_MHL = MAX14526_56KOHM, /* no power */
100
MAX14526_OTG_Y = MAX14526_GND | V_VBUS,
101
MAX14526_MHL_CHG = MAX14526_GND | V_VBUS | CHGDET,
102
MAX14526_NONE = MAX14526_OPEN,
103
MAX14526_USB = MAX14526_OPEN | V_VBUS,
104
MAX14526_CHG = MAX14526_OPEN | V_VBUS | CHGDET,
105
};
106
107
static const unsigned int max14526_extcon_cable[] = {
108
EXTCON_USB,
109
EXTCON_USB_HOST,
110
EXTCON_CHG_USB_FAST,
111
EXTCON_DISP_MHL,
112
EXTCON_NONE,
113
};
114
115
static int max14526_ap_usb_mode(struct max14526_data *priv)
116
{
117
struct device *dev = &priv->client->dev;
118
int ret;
119
120
/* Enable USB Path */
121
ret = regmap_field_write(priv->rfield[DM], SW_DATA);
122
if (ret)
123
return ret;
124
125
ret = regmap_field_write(priv->rfield[DP], SW_DATA);
126
if (ret)
127
return ret;
128
129
/* Enable 200K, Charger Pump and ADC */
130
ret = regmap_write(priv->regmap, MAX14526_CONTROL_1,
131
ID_200 | ADC_EN | CP_EN);
132
if (ret)
133
return ret;
134
135
dev_dbg(dev, "AP USB mode set\n");
136
137
return 0;
138
}
139
140
static irqreturn_t max14526_interrupt(int irq, void *dev_id)
141
{
142
struct max14526_data *priv = dev_id;
143
struct device *dev = &priv->client->dev;
144
int state, ret;
145
146
/*
147
* Upon an MUIC IRQ (MUIC_INT_N falls), wait at least 70ms
148
* before reading INT_STAT and STATUS. After the reads,
149
* MUIC_INT_N returns to high (but the INT_STAT and STATUS
150
* contents will be held).
151
*/
152
msleep(100);
153
154
ret = regmap_read(priv->regmap, MAX14526_INT_STAT, &state);
155
if (ret)
156
dev_err(dev, "failed to read MUIC state %d\n", ret);
157
158
if (state == priv->last_state)
159
return IRQ_HANDLED;
160
161
/* Detach previous device */
162
extcon_set_state_sync(priv->edev, priv->cable, false);
163
164
switch (state) {
165
case MAX14526_USB:
166
priv->cable = EXTCON_USB;
167
break;
168
169
case MAX14526_CHG:
170
priv->cable = EXTCON_CHG_USB_FAST;
171
break;
172
173
case MAX14526_OTG:
174
case MAX14526_OTG_Y:
175
priv->cable = EXTCON_USB_HOST;
176
break;
177
178
case MAX14526_MHL:
179
case MAX14526_MHL_CHG:
180
priv->cable = EXTCON_DISP_MHL;
181
break;
182
183
case MAX14526_NONE:
184
default:
185
priv->cable = EXTCON_NONE;
186
break;
187
}
188
189
extcon_set_state_sync(priv->edev, priv->cable, true);
190
191
priv->last_state = state;
192
193
return IRQ_HANDLED;
194
}
195
196
static const struct regmap_config max14526_regmap_config = {
197
.reg_bits = 8,
198
.val_bits = 8,
199
.max_register = MAX14526_STATUS,
200
};
201
202
static int max14526_probe(struct i2c_client *client)
203
{
204
struct device *dev = &client->dev;
205
struct max14526_data *priv;
206
int ret, dev_id, rev, i;
207
208
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
209
if (!priv)
210
return -ENOMEM;
211
212
priv->client = client;
213
i2c_set_clientdata(client, priv);
214
215
priv->regmap = devm_regmap_init_i2c(client, &max14526_regmap_config);
216
if (IS_ERR(priv->regmap))
217
return dev_err_probe(dev, PTR_ERR(priv->regmap), "cannot allocate regmap\n");
218
219
for (i = 0; i < MAX14526_N_REGMAP_FIELDS; i++) {
220
priv->rfield[i] = devm_regmap_field_alloc(dev, priv->regmap,
221
max14526_reg_field[i]);
222
if (IS_ERR(priv->rfield[i]))
223
return dev_err_probe(dev, PTR_ERR(priv->rfield[i]),
224
"cannot allocate regmap field\n");
225
}
226
227
/* Detect if MUIC version is supported */
228
ret = regmap_field_read(priv->rfield[VENDOR_ID], &dev_id);
229
if (ret)
230
return dev_err_probe(dev, ret, "failed to read MUIC ID\n");
231
232
regmap_field_read(priv->rfield[CHIP_REV], &rev);
233
234
if (dev_id == MAX14526_ID)
235
dev_info(dev, "detected MAX14526 MUIC with id 0x%x, rev 0x%x\n", dev_id, rev);
236
else
237
dev_err_probe(dev, -EINVAL, "MUIC vendor id 0x%X is not recognized\n", dev_id);
238
239
priv->edev = devm_extcon_dev_allocate(dev, max14526_extcon_cable);
240
if (IS_ERR(priv->edev))
241
return dev_err_probe(dev, (IS_ERR(priv->edev)),
242
"failed to allocate extcon device\n");
243
244
ret = devm_extcon_dev_register(dev, priv->edev);
245
if (ret < 0)
246
return dev_err_probe(dev, ret, "failed to register extcon device\n");
247
248
ret = max14526_ap_usb_mode(priv);
249
if (ret < 0)
250
return dev_err_probe(dev, ret, "failed to set AP USB mode\n");
251
252
regmap_write_bits(priv->regmap, MAX14526_CONTROL_2, INT_EN, INT_EN);
253
regmap_write_bits(priv->regmap, MAX14526_CONTROL_2, USB_DET_DIS, (u32)~USB_DET_DIS);
254
255
ret = devm_request_threaded_irq(dev, client->irq, NULL, &max14526_interrupt,
256
IRQF_ONESHOT | IRQF_SHARED, client->name, priv);
257
if (ret)
258
return dev_err_probe(dev, ret, "failed to register IRQ\n");
259
260
irq_wake_thread(client->irq, priv);
261
262
return 0;
263
}
264
265
static int max14526_resume(struct device *dev)
266
{
267
struct i2c_client *client = to_i2c_client(dev);
268
struct max14526_data *priv = i2c_get_clientdata(client);
269
270
irq_wake_thread(client->irq, priv);
271
272
return 0;
273
}
274
275
static DEFINE_SIMPLE_DEV_PM_OPS(max14526_pm_ops, NULL, max14526_resume);
276
277
static const struct of_device_id max14526_match[] = {
278
{ .compatible = "maxim,max14526" },
279
{ /* sentinel */ }
280
};
281
MODULE_DEVICE_TABLE(of, max14526_match);
282
283
static const struct i2c_device_id max14526_id[] = {
284
{ "max14526" },
285
{ }
286
};
287
MODULE_DEVICE_TABLE(i2c, max14526_id);
288
289
static struct i2c_driver max14526_driver = {
290
.driver = {
291
.name = "max14526",
292
.of_match_table = max14526_match,
293
.pm = &max14526_pm_ops,
294
},
295
.probe = max14526_probe,
296
.id_table = max14526_id,
297
};
298
module_i2c_driver(max14526_driver);
299
300
MODULE_AUTHOR("Svyatoslav Ryhel <[email protected]>");
301
MODULE_DESCRIPTION("MAX14526 extcon driver to support MUIC");
302
MODULE_LICENSE("GPL");
303
304