1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2022 Svyatoslav Ryhel <clamor95@gmail.com>
*/
#include <common.h>
#include <dm.h>
#include <i2c.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <log.h>
#include <extcon.h>
#include <asm/gpio.h>
#define CONTROL_1 0x01
#define SW_CONTROL 0x03
#define ID_200 0x10
#define ADC_EN 0x02
#define CP_EN 0x01
#define DP_USB 0x00
#define DP_UART 0x08
#define DP_AUDIO 0x10
#define DP_OPEN 0x38
#define DM_USB 0x00
#define DM_UART 0x01
#define DM_AUDIO 0x02
#define DM_OPEN 0x07
#define AP_USB BIT(0)
#define CP_USB BIT(1)
#define CP_UART BIT(2)
struct max14526_priv {
struct gpio_desc usif_gpio;
struct gpio_desc dp2t_gpio;
struct gpio_desc ifx_usb_vbus_gpio;
};
static void max14526_set_mode(struct udevice *dev, int mode)
{
struct max14526_priv *priv = dev_get_priv(dev);
int ret;
if ((mode & AP_USB) || (mode & CP_USB)) {
/* Connect CP UART signals to AP */
ret = dm_gpio_set_value(&priv->usif_gpio, 0);
if (ret)
log_debug("cp-uart > ap failed (%d)\n", ret);
}
if (mode & CP_UART) {
/* Connect CP UART signals to DP2T */
ret = dm_gpio_set_value(&priv->usif_gpio, 1);
if (ret)
log_debug("cp-uart > dp2t failed (%d)\n", ret);
}
if (mode & CP_USB) {
/* Connect CP USB to MUIC UART */
ret = dm_gpio_set_value(&priv->ifx_usb_vbus_gpio, 1);
if (ret)
log_debug("usb-vbus-gpio enable failed (%d)\n", ret);
ret = dm_gpio_set_value(&priv->dp2t_gpio, 1);
if (ret)
log_debug("cp-usb > muic-uart failed (%d)\n", ret);
}
if ((mode & AP_USB) || (mode & CP_UART)) {
/* Connect CP UART to MUIC UART */
ret = dm_gpio_set_value(&priv->dp2t_gpio, 0);
if (ret)
log_debug("cp-uart > muic-uart failed (%d)\n", ret);
}
if (mode & AP_USB) {
/* Enables USB Path */
ret = dm_i2c_reg_write(dev, SW_CONTROL, DP_USB | DM_USB);
if (ret)
log_debug("USB path set failed: %d\n", ret);
}
if ((mode & CP_USB) || (mode & CP_UART)) {
/* Enables UART Path */
ret = dm_i2c_reg_write(dev, SW_CONTROL, DP_UART | DM_UART);
if (ret)
log_debug("UART path set failed: %d\n", ret);
}
/* Enables 200K, Charger Pump, and ADC */
ret = dm_i2c_reg_write(dev, CONTROL_1, ID_200 | ADC_EN | CP_EN);
if (ret)
log_debug("200K, Charger Pump, and ADC set failed: %d\n", ret);
}
static int max14526_probe(struct udevice *dev)
{
struct max14526_priv *priv = dev_get_priv(dev);
int ret, mode = 0;
ret = gpio_request_by_name(dev, "usif-gpios", 0,
&priv->usif_gpio, GPIOD_IS_OUT);
if (ret) {
log_err("could not decode usif-gpios (%d)\n", ret);
return ret;
}
ret = gpio_request_by_name(dev, "dp2t-gpios", 0,
&priv->dp2t_gpio, GPIOD_IS_OUT);
if (ret) {
log_err("could not decode dp2t-gpios (%d)\n", ret);
return ret;
}
if (dev_read_bool(dev, "maxim,ap-usb"))
mode |= AP_USB;
if (dev_read_bool(dev, "maxim,cp-usb")) {
mode |= CP_USB;
ret = gpio_request_by_name(dev, "usb-vbus-gpios", 0,
&priv->ifx_usb_vbus_gpio, GPIOD_IS_OUT);
if (ret) {
log_err("could not decode usb-vbus-gpios (%d)\n", ret);
return ret;
}
}
if (dev_read_bool(dev, "maxim,cp-uart"))
mode |= CP_UART;
max14526_set_mode(dev, mode);
return 0;
}
static const struct udevice_id max14526_ids[] = {
{ .compatible = "maxim,max14526-muic" },
{ }
};
U_BOOT_DRIVER(extcon_max14526) = {
.name = "extcon_max14526",
.id = UCLASS_EXTCON,
.of_match = max14526_ids,
.probe = max14526_probe,
.priv_auto = sizeof(struct max14526_priv),
};
|