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