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