/* This driver handles a family of multipurpose chips, which incorporate * voltage regulators, lithium ion/polymer battery charging, GPIOs, LEDs, * and other features often needed in portable devices like cell phones * or digital cameras. * * The tps65011 and tps65013 have different voltage settings compared * to tps65010 and tps65012. The tps65013 has a NO_CHG status/irq. * All except tps65010 have "wait" mode, possibly defaulted so that * battery-insert != device-on. * * We could distinguish between some models by checking VDCDC1.UVLO or * other registers, unless they've been changed already after powerup * as part of board setup by a bootloader.
*/ enum tps_model {
TPS65010,
TPS65011,
TPS65012,
TPS65013,
};
/* handle IRQS in a task context, so we can use I2C calls */ staticvoid tps65010_interrupt(struct tps65010 *tps)
{
u8 tmp = 0, mask, poll;
/* IRQs won't trigger for certain events, but we can get * others by polling (normally, with external power applied).
*/
poll = 0;
/* regstatus irqs */ if (tps->nmask2) {
tmp = i2c_smbus_read_byte_data(tps->client, TPS_REGSTATUS);
mask = tmp ^ tps->regstatus;
tps->regstatus = tmp;
mask &= tps->nmask2;
} else
mask = 0; if (mask) {
tps->regstatus = tmp; /* may need to shut something down ... */
/* "off" usually means deep sleep */ if (tmp & TPS_REG_ONOFF) {
pr_info("%s: power off button\n", DRIVER_NAME); #if 0 /* REVISIT: this might need its own workqueue * plus tweaks including deadlock avoidance ... * also needs to get error handling and probably * an #ifdef CONFIG_HIBERNATION
*/
hibernate(); #endif
poll = 1;
}
}
show_chgstatus("chg/irq", tmp); if (tmp & (TPS_CHG_USB|TPS_CHG_AC))
show_chgconfig(tps->por, "conf", tps->chgconf);
/* Unless it was turned off or disabled, we charge any * battery whenever there's power available for it * and the charger hasn't been disabled.
*/ if (!(tps->chgstatus & ~(TPS_CHG_USB|TPS_CHG_AC))
&& (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC))
&& (tps->chgconf & TPS_CHARGE_ENABLE)
) { if (tps->chgstatus & TPS_CHG_USB) { /* VBUS options are readonly until reconnect */ if (mask & TPS_CHG_USB)
set_bit(FLAG_VBUS_CHANGED, &tps->flags);
charging = 1;
} elseif (tps->chgstatus & TPS_CHG_AC)
charging = 1;
} if (charging != tps->charging) {
tps->charging = charging;
pr_info("%s: battery %scharging\n",
DRIVER_NAME, charging ? "" :
((tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC))
? "NOT " : "dis"));
}
}
/* always poll to detect (a) power removal, without tps65013 * NO_CHG IRQ; or (b) restart of charging after stop.
*/ if ((tps->model != TPS65013 || !tps->charging)
&& (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC)))
poll = 1; if (poll)
queue_delayed_work(system_power_efficient_wq, &tps->work,
POWER_POLL_DELAY);
/* also potentially gpio-in rise or fall */
}
/* handle IRQs and polling using keventd for now */ staticvoid tps65010_work(struct work_struct *work)
{ struct tps65010 *tps;
/* the IRQ is active low, but many gpio lines can't support that * so this driver uses falling-edge triggers instead.
*/ if (client->irq > 0) {
status = request_irq(client->irq, tps65010_irq,
IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN,
DRIVER_NAME, tps); if (status < 0) {
dev_dbg(&client->dev, "can't get IRQ %d, err %d\n",
client->irq, status); return status;
}
set_bit(FLAG_IRQ_ENABLE, &tps->flags);
} else
dev_warn(&client->dev, "IRQ not configured!\n");
switch (tps->model) { case TPS65010: case TPS65012:
tps->por = 1; break; /* else CHGCONFIG.POR is replaced by AUA, enabling a WAIT mode */
}
tps->chgconf = i2c_smbus_read_byte_data(client, TPS_CHGCONFIG);
show_chgconfig(tps->por, "conf/init", tps->chgconf);
#ifdefined(CONFIG_USB_GADGET) && !defined(CONFIG_USB_OTG) /* USB hosts can't draw VBUS. OTG devices could, later * when OTG infrastructure enables it. USB peripherals * could be relying on VBUS while booting, though.
*/
tps->vbus = 100; #endif
/* unmask the "interesting" irqs, then poll once to * kickstart monitoring, initialize shadowed status * registers, and maybe disable VBUS draw.
*/
tps->nmask1 = ~0;
(void) i2c_smbus_write_byte_data(client, TPS_MASK1, ~tps->nmask1);
/* Draw from VBUS: * 0 mA -- DON'T DRAW (might supply power instead) * 100 mA -- usb unit load (slowest charge rate) * 500 mA -- usb high power (fast battery charge)
*/ int tps65010_set_vbus_draw(unsigned mA)
{ unsignedlong flags;
if (!the_tps) return -ENODEV;
/* assumes non-SMP */
local_irq_save(flags); if (mA >= 500)
mA = 500; elseif (mA >= 100)
mA = 100; else
mA = 0;
the_tps->vbus = mA; if ((the_tps->chgstatus & TPS_CHG_USB)
&& test_and_set_bit(
FLAG_VBUS_CHANGED, &the_tps->flags)) { /* gadget drivers call this in_irq() */
queue_delayed_work(system_power_efficient_wq, &the_tps->work,
0);
}
local_irq_restore(flags);
/*-------------------------------------------------------------------------*/ /* tps65010_set_led parameter: * led: LED1 or LED2 * mode: ON, OFF or BLINK
*/ int tps65010_set_led(unsigned led, unsigned mode)
{ int status; unsigned led_on, led_per, offs;
if (!the_tps) return -ENODEV;
if (led == LED1)
offs = 0; else {
offs = 2;
led = LED2;
}
/*-------------------------------------------------------------------------*/ /* tps65010_set_vib parameter: * value: ON or OFF
*/ int tps65010_set_vib(unsigned value)
{ int status; unsigned vdcdc2;
/*-------------------------------------------------------------------------*/ /* tps65010_set_low_pwr parameter: * mode: ON or OFF
*/ int tps65010_set_low_pwr(unsigned mode)
{ int status; unsigned vdcdc1;
/*-------------------------------------------------------------------------*/ /* tps65010_config_vregs1 parameter: * value to be written to VREGS1 register * Note: The complete register is written, set all bits you need
*/ int tps65010_config_vregs1(unsigned value)
{ int status;
staticint __init tps_init(void)
{ return i2c_add_driver(&tps65010_driver);
} /* NOTE: this MUST be initialized before the other parts of the system * that rely on it ... but after the i2c bus on which this relies. * That is, much earlier than on PC-type systems, which don't often use * I2C as a core system bus.
*/
subsys_initcall(tps_init);
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.15Bemerkung:
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-04-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.