1 /* $OpenBSD: tps65090.c,v 1.6 2021/10/24 17:52:27 mpi Exp $ */ 2 /* 3 * Copyright (c) 2013 Patrick Wildt <patrick@blueri.se> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/device.h> 21 22 #include <dev/i2c/i2cvar.h> 23 24 #define REG_IRQ1 0x00 25 #define REG_IRQ2 0x01 26 #define REG_IRQ1MASK 0x02 27 #define REG_IRQ2MASK 0x03 28 #define REG_CG_CTRL0 0x04 29 #define REG_CG_CTRL0_ENC_MASK (1 << 0) 30 #define REG_CG_CTRL1 0x05 31 #define REG_CG_CTRL2 0x06 32 #define REG_CG_CTRL3 0x07 33 #define REG_CG_CTRL4 0x08 34 #define REG_CG_CTRL5 0x09 35 #define REG_CG_STATUS1 0x0a 36 #define REG_CG_STATUS2 0x0b 37 #define REG_DCDC1_CTRL 0x0c 38 #define REG_DCDC2_CTRL 0x0d 39 #define REG_DCDC3_CTRL 0x0e 40 #define REG_FET1_CTRL 0x0f 41 #define REG_FET2_CTRL 0x10 42 #define REG_FET3_CTRL 0x11 43 #define REG_FET4_CTRL 0x12 44 #define REG_FET5_CTRL 0x13 45 #define REG_FET6_CTRL 0x14 46 #define REG_FET7_CTRL 0x15 47 #define REG_FETx_CTRL(x) (0x0e + (x)) 48 #define REG_FETx_CTRL_ENFET (1 << 0) /* Enable FET */ 49 #define REG_FETx_CTRL_ADENFET (1 << 1) /* Enable output auto discharge */ 50 #define REG_FETx_CTRL_WAIT (3 << 2) /* Overcurrent timeout max */ 51 #define REG_FETx_CTRL_PGFET (1 << 4) /* Power good for FET status */ 52 #define REG_FETx_CTRL_TOFET (1 << 7) /* Timeout, startup, overload */ 53 #define REG_AD_CTRL 0x16 54 #define REG_AD_OUT1 0x17 55 #define REG_AD_OUT2 0x18 56 57 #define NFET 7 58 59 #ifdef DEBUG 60 #define DPRINTF(x) printf x 61 #else 62 #define DPRINTF(x) 63 #endif 64 65 struct tps65090_softc { 66 struct device sc_dev; 67 i2c_tag_t sc_tag; 68 i2c_addr_t sc_addr; 69 }; 70 71 struct tps65090_softc *tps65090_sc; 72 73 int tps65090_match(struct device *, void *, void *); 74 void tps65090_attach(struct device *, struct device *, void *); 75 76 int tps65090_read_reg(struct tps65090_softc *, uint8_t); 77 void tps65090_write_reg(struct tps65090_softc *, uint8_t, uint8_t); 78 int tps65090_fet_set(int, int); 79 int tps65090_fet_get(int); 80 void tps65090_fet_enable(int); 81 void tps65090_fet_disable(int); 82 int tps65090_get_charging(void); 83 void tps65090_set_charging(int); 84 85 const struct cfattach tpspmic_ca = { 86 sizeof(struct tps65090_softc), tps65090_match, tps65090_attach 87 }; 88 89 struct cfdriver tpspmic_cd = { 90 NULL, "tpspmic", DV_DULL 91 }; 92 93 int 94 tps65090_match(struct device *parent, void *match, void *aux) 95 { 96 struct i2c_attach_args *ia = aux; 97 98 if (strcmp(ia->ia_name, "ti,tps65090") == 0) 99 return (1); 100 return (0); 101 } 102 103 void 104 tps65090_attach(struct device *parent, struct device *self, void *aux) 105 { 106 struct tps65090_softc *sc = (struct tps65090_softc *)self; 107 struct i2c_attach_args *ia = aux; 108 109 sc->sc_tag = ia->ia_tag; 110 sc->sc_addr = ia->ia_addr; 111 tps65090_sc = sc; 112 113 printf("\n"); 114 } 115 116 /* 117 * FET1: Backlight on the Chromebook 118 * FET6: LCD panel on the Chromebook 119 */ 120 void 121 tps65090_fet_enable(int fet) 122 { 123 int i; 124 125 if (fet < 1 || fet > NFET) 126 return; 127 128 for (i = 0; i < 10; i++) { 129 if (!tps65090_fet_set(fet, 1)) 130 break; 131 132 if (i != 9) 133 tps65090_fet_set(fet, 0); 134 } 135 } 136 137 void 138 tps65090_fet_disable(int fet) 139 { 140 if (fet < 1 || fet > NFET) 141 return; 142 143 tps65090_fet_set(fet, 0); 144 } 145 146 int 147 tps65090_fet_set(int fet, int set) 148 { 149 struct tps65090_softc *sc = tps65090_sc; 150 int i; 151 uint8_t val, check; 152 153 val = REG_FETx_CTRL_ADENFET | REG_FETx_CTRL_WAIT; 154 if (set) 155 val |= REG_FETx_CTRL_ENFET; 156 157 tps65090_write_reg(sc, REG_FETx_CTRL(fet), val); 158 for (i = 0; i < 5; i++) { 159 check = tps65090_read_reg(sc, REG_FETx_CTRL(fet)); 160 161 /* FET state correct? */ 162 if (!!(check & REG_FETx_CTRL_PGFET) == set) 163 return 0; 164 165 /* Timeout, don't need to try again. */ 166 if (check & REG_FETx_CTRL_TOFET) 167 break; 168 169 delay(1000); 170 } 171 172 return -1; 173 } 174 175 int 176 tps65090_fet_get(int fet) 177 { 178 struct tps65090_softc *sc = tps65090_sc; 179 uint8_t val = tps65090_read_reg(sc, REG_FETx_CTRL(fet)); 180 return val & REG_FETx_CTRL_ENFET; 181 } 182 183 int 184 tps65090_get_charging(void) 185 { 186 struct tps65090_softc *sc = tps65090_sc; 187 uint8_t val = tps65090_read_reg(sc, REG_CG_CTRL0); 188 return val & REG_CG_CTRL0_ENC_MASK; 189 } 190 191 void 192 tps65090_set_charging(int set) 193 { 194 struct tps65090_softc *sc = tps65090_sc; 195 uint8_t val = tps65090_read_reg(sc, REG_CG_CTRL0); 196 if (set) 197 val |= REG_CG_CTRL0_ENC_MASK; 198 else 199 val &= REG_CG_CTRL0_ENC_MASK; 200 tps65090_write_reg(sc, REG_CG_CTRL0, val); 201 } 202 203 int 204 tps65090_read_reg(struct tps65090_softc *sc, uint8_t cmd) 205 { 206 uint8_t val; 207 208 iic_acquire_bus(sc->sc_tag, 0); 209 iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 210 sc->sc_addr, &cmd, 1, &val, 1, 0); 211 iic_release_bus(sc->sc_tag, 0); 212 213 return val; 214 } 215 216 void 217 tps65090_write_reg(struct tps65090_softc *sc, uint8_t cmd, uint8_t val) 218 { 219 iic_acquire_bus(sc->sc_tag, 0); 220 iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 221 sc->sc_addr, &cmd, 1, &val, 1, 0); 222 iic_release_bus(sc->sc_tag, 0); 223 } 224