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
tps65090_match(struct device * parent,void * match,void * aux)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
tps65090_attach(struct device * parent,struct device * self,void * aux)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
tps65090_fet_enable(int fet)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
tps65090_fet_disable(int fet)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
tps65090_fet_set(int fet,int set)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
tps65090_fet_get(int fet)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
tps65090_get_charging(void)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
tps65090_set_charging(int set)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
tps65090_read_reg(struct tps65090_softc * sc,uint8_t cmd)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
tps65090_write_reg(struct tps65090_softc * sc,uint8_t cmd,uint8_t val)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