1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (c) 2022 Svyatoslav Ryhel <clamor95@gmail.com> 4 */ 5 6#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}; 151