1 /* 2 * (C) Copyright 2022 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <i2c.h> 10 #include <irq-generic.h> 11 #include <power/fuel_gauge.h> 12 #include <power/power_delivery/power_delivery.h> 13 #include <linux/usb/phy-rockchip-usb2.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 static int dbg_enable; 18 19 #define SC8551_DBG(args...) \ 20 do { \ 21 if (dbg_enable) { \ 22 printf(args); \ 23 } \ 24 } while (0) 25 26 struct sc8551 { 27 struct udevice *dev; 28 struct udevice *pd; 29 bool pd_online; 30 u32 init_count; 31 u32 ichg; 32 u32 vchg; 33 int irq; 34 }; 35 36 enum charger_type { 37 CHARGER_TYPE_NO = 0, 38 CHARGER_TYPE_USB, 39 CHARGER_TYPE_AC, 40 CHARGER_TYPE_DC, 41 CHARGER_TYPE_UNDEF, 42 }; 43 44 /* Register 05h */ 45 #define SC8551_REG_05 0x05 46 #define SC8551_AC_OVP_STAT_MASK 0x80 47 #define SC8551_AC_OVP_STAT_SHIFT 7 48 49 #define SC8551_AC_OVP_MASK 0x07 50 #define SC8551_AC_OVP_SHIFT 0 51 #define SC8551_AC_OVP_BASE 11 52 #define SC8551_AC_OVP_LSB 1 53 #define SC8551_AC_OVP_6P5V 65 54 55 /* Register 0Bh */ 56 #define SC8551_REG_0B 0x0B 57 #define SC8551_REG_RST_MASK 0x80 58 #define SC8551_REG_RST_SHIFT 7 59 #define SC8551_REG_RST_ENABLE 1 60 #define SC8551_REG_RST_DISABLE 0 61 #define SC8551_AC_OVP_VOLTAGE 13 62 63 static int sc8551_read(struct sc8551 *charger, uint reg, u8 *buffer) 64 { 65 u16 val; 66 int ret; 67 68 ret = dm_i2c_read(charger->dev, reg, (u8 *)&val, 1); 69 if (ret) { 70 printf("sc8551: read %#x error, ret=%d", reg, ret); 71 return ret; 72 } 73 74 *buffer = val; 75 return 0; 76 } 77 78 static int sc8551_write(struct sc8551 *charger, uint reg, u16 val) 79 { 80 int ret; 81 82 ret = dm_i2c_write(charger->dev, reg, (u8 *)&val, 1); 83 if (ret) 84 printf("sc8551: write %#x error, ret=%d", reg, ret); 85 86 return ret; 87 } 88 89 static int sc8551_update_bits(struct sc8551 *charger, 90 uint offset, 91 uint mask, 92 uint val) 93 { 94 u8 reg; 95 int ret; 96 97 ret = sc8551_read(charger, offset, ®); 98 if (ret) 99 return ret; 100 101 reg &= ~mask; 102 103 return sc8551_write(charger, offset, reg | val); 104 } 105 106 static int sc8551_charger_capability(struct udevice *dev) 107 { 108 return 0; 109 } 110 111 static int sc8551_dwc_otg_check_dpdm(void) 112 { 113 #if defined(CONFIG_PHY_ROCKCHIP_INNO_USB2) && !defined(CONFIG_SPL_BUILD) 114 return rockchip_chg_get_type(); 115 #else 116 debug("rockchip_chg_get_type() is not implement\n"); 117 return CHARGER_TYPE_NO; 118 #endif 119 } 120 121 static int sc8551_get_usb_state(struct sc8551 *sc8551) 122 { 123 int charger_type; 124 125 switch (sc8551_dwc_otg_check_dpdm()) { 126 case 0: 127 charger_type = CHARGER_TYPE_NO; 128 break; 129 case 1: 130 case 3: 131 charger_type = CHARGER_TYPE_USB; 132 break; 133 case 2: 134 charger_type = CHARGER_TYPE_AC; 135 break; 136 default: 137 charger_type = CHARGER_TYPE_NO; 138 break; 139 } 140 141 return charger_type; 142 } 143 144 static bool sc8551_check_charge(struct sc8551 *sc8551) 145 { 146 if (sc8551_get_usb_state(sc8551) != CHARGER_TYPE_NO) 147 return true; 148 149 return false; 150 } 151 152 static bool sc8551_update_get_chrg_online(struct udevice *dev) 153 { 154 struct sc8551 *sc8551 = dev_get_priv(dev); 155 156 return sc8551_check_charge(sc8551); 157 } 158 159 static int sc8551_ofdata_to_platdata(struct udevice *dev) 160 { 161 return 0; 162 } 163 164 static int sc8551_set_acovp_th(struct sc8551 *sc, int threshold) 165 { 166 int ret; 167 u8 val; 168 169 if (threshold < SC8551_AC_OVP_BASE) 170 threshold = SC8551_AC_OVP_BASE; 171 172 if (threshold == SC8551_AC_OVP_6P5V) 173 val = 0x07; 174 else 175 val = (threshold - SC8551_AC_OVP_BASE) / SC8551_AC_OVP_LSB; 176 177 val <<= SC8551_AC_OVP_SHIFT; 178 179 ret = sc8551_update_bits(sc, SC8551_REG_05, 180 SC8551_AC_OVP_MASK, val); 181 182 return ret; 183 } 184 185 static int sc8551_probe(struct udevice *dev) 186 { 187 struct sc8551 *charger = dev_get_priv(dev); 188 189 SC8551_DBG("sc8551: driver version-20220903\n"); 190 191 charger->dev = dev; 192 193 SC8551_DBG("sc8551: not reset\n"); 194 195 sc8551_set_acovp_th(charger, SC8551_AC_OVP_VOLTAGE); 196 197 return 0; 198 } 199 200 static const struct udevice_id charger_ids[] = { 201 { .compatible = "sc,sc8551-standalone" }, 202 { }, 203 }; 204 205 static struct dm_fuel_gauge_ops charger_ops = { 206 .get_chrg_online = sc8551_update_get_chrg_online, 207 .capability = sc8551_charger_capability, 208 }; 209 210 U_BOOT_DRIVER(sc8551_charger) = { 211 .name = "sc8551_charger", 212 .id = UCLASS_FG, 213 .probe = sc8551_probe, 214 .of_match = charger_ids, 215 .ops = &charger_ops, 216 .ofdata_to_platdata = sc8551_ofdata_to_platdata, 217 .priv_auto_alloc_size = sizeof(struct sc8551), 218 }; 219