~funderscore blog cgit wiki get in touch
aboutsummaryrefslogtreecommitdiff
blob: a33b5ef919cc2dd1291ce6ed06709c5073bc92f3 (plain)
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),
};