#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <dev/i2c/i2cvar.h>
#define REG_IRQ1 0x00
#define REG_IRQ2 0x01
#define REG_IRQ1MASK 0x02
#define REG_IRQ2MASK 0x03
#define REG_CG_CTRL0 0x04
#define REG_CG_CTRL0_ENC_MASK (1 << 0)
#define REG_CG_CTRL1 0x05
#define REG_CG_CTRL2 0x06
#define REG_CG_CTRL3 0x07
#define REG_CG_CTRL4 0x08
#define REG_CG_CTRL5 0x09
#define REG_CG_STATUS1 0x0a
#define REG_CG_STATUS2 0x0b
#define REG_DCDC1_CTRL 0x0c
#define REG_DCDC2_CTRL 0x0d
#define REG_DCDC3_CTRL 0x0e
#define REG_FET1_CTRL 0x0f
#define REG_FET2_CTRL 0x10
#define REG_FET3_CTRL 0x11
#define REG_FET4_CTRL 0x12
#define REG_FET5_CTRL 0x13
#define REG_FET6_CTRL 0x14
#define REG_FET7_CTRL 0x15
#define REG_FETx_CTRL(x) (0x0e + (x))
#define REG_FETx_CTRL_ENFET (1 << 0)
#define REG_FETx_CTRL_ADENFET (1 << 1)
#define REG_FETx_CTRL_WAIT (3 << 2)
#define REG_FETx_CTRL_PGFET (1 << 4)
#define REG_FETx_CTRL_TOFET (1 << 7)
#define REG_AD_CTRL 0x16
#define REG_AD_OUT1 0x17
#define REG_AD_OUT2 0x18
#define NFET 7
#ifdef DEBUG
#define DPRINTF(x) printf x
#else
#define DPRINTF(x)
#endif
struct tps65090_softc {
struct device sc_dev;
i2c_tag_t sc_tag;
i2c_addr_t sc_addr;
};
struct tps65090_softc *tps65090_sc;
int tps65090_match(struct device *, void *, void *);
void tps65090_attach(struct device *, struct device *, void *);
int tps65090_read_reg(struct tps65090_softc *, uint8_t);
void tps65090_write_reg(struct tps65090_softc *, uint8_t, uint8_t);
int tps65090_fet_set(int, int);
int tps65090_fet_get(int);
void tps65090_fet_enable(int);
void tps65090_fet_disable(int);
int tps65090_get_charging(void);
void tps65090_set_charging(int);
const struct cfattach tpspmic_ca = {
sizeof(struct tps65090_softc), tps65090_match, tps65090_attach
};
struct cfdriver tpspmic_cd = {
NULL, "tpspmic", DV_DULL
};
int
tps65090_match(struct device *parent, void *match, void *aux)
{
struct i2c_attach_args *ia = aux;
if (strcmp(ia->ia_name, "ti,tps65090") == 0)
return (1);
return (0);
}
void
tps65090_attach(struct device *parent, struct device *self, void *aux)
{
struct tps65090_softc *sc = (struct tps65090_softc *)self;
struct i2c_attach_args *ia = aux;
sc->sc_tag = ia->ia_tag;
sc->sc_addr = ia->ia_addr;
tps65090_sc = sc;
printf("\n");
}
void
tps65090_fet_enable(int fet)
{
int i;
if (fet < 1 || fet > NFET)
return;
for (i = 0; i < 10; i++) {
if (!tps65090_fet_set(fet, 1))
break;
if (i != 9)
tps65090_fet_set(fet, 0);
}
}
void
tps65090_fet_disable(int fet)
{
if (fet < 1 || fet > NFET)
return;
tps65090_fet_set(fet, 0);
}
int
tps65090_fet_set(int fet, int set)
{
struct tps65090_softc *sc = tps65090_sc;
int i;
uint8_t val, check;
val = REG_FETx_CTRL_ADENFET | REG_FETx_CTRL_WAIT;
if (set)
val |= REG_FETx_CTRL_ENFET;
tps65090_write_reg(sc, REG_FETx_CTRL(fet), val);
for (i = 0; i < 5; i++) {
check = tps65090_read_reg(sc, REG_FETx_CTRL(fet));
if (!!(check & REG_FETx_CTRL_PGFET) == set)
return 0;
if (check & REG_FETx_CTRL_TOFET)
break;
delay(1000);
}
return -1;
}
int
tps65090_fet_get(int fet)
{
struct tps65090_softc *sc = tps65090_sc;
uint8_t val = tps65090_read_reg(sc, REG_FETx_CTRL(fet));
return val & REG_FETx_CTRL_ENFET;
}
int
tps65090_get_charging(void)
{
struct tps65090_softc *sc = tps65090_sc;
uint8_t val = tps65090_read_reg(sc, REG_CG_CTRL0);
return val & REG_CG_CTRL0_ENC_MASK;
}
void
tps65090_set_charging(int set)
{
struct tps65090_softc *sc = tps65090_sc;
uint8_t val = tps65090_read_reg(sc, REG_CG_CTRL0);
if (set)
val |= REG_CG_CTRL0_ENC_MASK;
else
val &= REG_CG_CTRL0_ENC_MASK;
tps65090_write_reg(sc, REG_CG_CTRL0, val);
}
int
tps65090_read_reg(struct tps65090_softc *sc, uint8_t cmd)
{
uint8_t val;
iic_acquire_bus(sc->sc_tag, 0);
iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
sc->sc_addr, &cmd, 1, &val, 1, 0);
iic_release_bus(sc->sc_tag, 0);
return val;
}
void
tps65090_write_reg(struct tps65090_softc *sc, uint8_t cmd, uint8_t val)
{
iic_acquire_bus(sc->sc_tag, 0);
iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
sc->sc_addr, &cmd, 1, &val, 1, 0);
iic_release_bus(sc->sc_tag, 0);
}