10SN/A/*- 211442Sserb * SPDX-License-Identifier: BSD-2-Clause 30SN/A * 40SN/A * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org> 50SN/A * All rights reserved. 60SN/A * 72362SN/A * Redistribution and use in source and binary forms, with or without 80SN/A * modification, are permitted provided that the following conditions 92362SN/A * are met: 100SN/A * 1. Redistributions of source code must retain the above copyright 110SN/A * notice, this list of conditions and the following disclaimer. 120SN/A * 2. Redistributions in binary form must reproduce the above copyright 130SN/A * notice, this list of conditions and the following disclaimer in the 140SN/A * documentation and/or other materials provided with the distribution. 150SN/A * 160SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 170SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 180SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 190SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 200SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 212362SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 222362SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 232362SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 240SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 250SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 260SN/A * SUCH DAMAGE. 270SN/A */ 280SN/A 290SN/A#include <sys/cdefs.h> 300SN/A/* 310SN/A* TI TPS65217 PMIC companion chip for AM335x SoC sitting on I2C bus 320SN/A*/ 3315954Salexsch#include <sys/param.h> 3415040Salexsch#include <sys/systm.h> 3515786Salexsch#include <sys/eventhandler.h> 3616331Salexsch#include <sys/kernel.h> 3715786Salexsch#include <sys/module.h> 380SN/A#include <sys/clock.h> 3911442Sserb#include <sys/time.h> 408099SN/A#include <sys/bus.h> 410SN/A#include <sys/proc.h> 420SN/A#include <sys/reboot.h> 430SN/A#include <sys/resource.h> 440SN/A#include <sys/rman.h> 457342SN/A 460SN/A#include <dev/iicbus/iicbus.h> 470SN/A#include <dev/iicbus/iiconf.h> 480SN/A 490SN/A#include <dev/ofw/openfirm.h> 500SN/A#include <dev/ofw/ofw_bus.h> 512381SN/A#include <dev/ofw/ofw_bus_subr.h> 527342SN/A 537342SN/A#include <arm/ti/am335x/am335x_rtcvar.h> 542381SN/A#include <arm/ti/am335x/tps65217x.h> 550SN/A 560SN/A#include "iicbus_if.h" 570SN/A 5810418SN/Astruct am335x_pmic_softc { 5910418SN/A device_t sc_dev; 600SN/A uint32_t sc_addr; 610SN/A struct resource *sc_irq_res; 621686SN/A void *sc_intrhand; 63760SN/A}; 640SN/A 650SN/Astatic const char *tps65217_voreg_c[4] = {"4.10V", "4.15V", "4.20V", "4.25V"}; 660SN/A 670SN/Astatic int am335x_pmic_bootverbose = 0; 680SN/ATUNABLE_INT("hw.am335x_pmic.bootverbose", &am335x_pmic_bootverbose); 690SN/Astatic char am335x_pmic_vo[6]; 700SN/ATUNABLE_STR("hw.am335x_pmic.vo", am335x_pmic_vo, sizeof(am335x_pmic_vo)); 710SN/A 720SN/Astatic void am335x_pmic_shutdown(void *, int); 730SN/A 740SN/Astatic int 750SN/Aam335x_pmic_read(device_t dev, uint8_t addr, uint8_t *data, uint8_t size) 760SN/A{ 770SN/A return (iicdev_readfrom(dev, addr, data, size, IIC_INTRWAIT)); 780SN/A} 790SN/A 8012631Savstepanstatic int 810SN/Aam335x_pmic_write(device_t dev, uint8_t address, uint8_t *data, uint8_t size) 820SN/A{ 830SN/A return (iicdev_writeto(dev, address, data, size, IIC_INTRWAIT)); 840SN/A} 850SN/A 869450SN/Astatic void 879450SN/Aam335x_pmic_intr(void *arg) 889450SN/A{ 891637SN/A struct am335x_pmic_softc *sc = (struct am335x_pmic_softc *)arg; 901637SN/A struct tps65217_status_reg status_reg; 911637SN/A struct tps65217_int_reg int_reg; 921637SN/A int rv; 931637SN/A char notify_buf[16]; 941637SN/A 951637SN/A THREAD_SLEEPING_OK(); 961637SN/A rv = am335x_pmic_read(sc->sc_dev, TPS65217_INT_REG, (uint8_t *)&int_reg, 1); 971637SN/A if (rv != 0) { 981637SN/A device_printf(sc->sc_dev, "Cannot read interrupt register\n"); 991637SN/A THREAD_NO_SLEEPING(); 1001637SN/A return; 1011637SN/A } 1021637SN/A rv = am335x_pmic_read(sc->sc_dev, TPS65217_STATUS_REG, (uint8_t *)&status_reg, 1); 1031637SN/A if (rv != 0) { 1041637SN/A device_printf(sc->sc_dev, "Cannot read status register\n"); 1051637SN/A THREAD_NO_SLEEPING(); 1060SN/A return; 1070SN/A } 1080SN/A THREAD_NO_SLEEPING(); 1090SN/A 1100SN/A if (int_reg.pbi && status_reg.pb) 1112450SN/A shutdown_nice(RB_POWEROFF); 1122450SN/A if (int_reg.aci) { 1132450SN/A snprintf(notify_buf, sizeof(notify_buf), "notify=0x%02x", 1142450SN/A status_reg.acpwr); 1152450SN/A devctl_notify("ACPI", "ACAD", "power", notify_buf); 1162450SN/A } 1170SN/A} 1180SN/A 1190SN/Astatic int 1200SN/Aam335x_pmic_probe(device_t dev) 1210SN/A{ 1220SN/A struct am335x_pmic_softc *sc; 12312694Salexsch 12412694Salexsch if (!ofw_bus_is_compatible(dev, "ti,tps65217")) 12512694Salexsch return (ENXIO); 12612694Salexsch 12712694Salexsch sc = device_get_softc(dev); 12812694Salexsch sc->sc_dev = dev; 1290SN/A /* Convert to 8-bit addressing */ 13012694Salexsch sc->sc_addr = iicbus_get_addr(dev); 13112694Salexsch 13212694Salexsch device_set_desc(dev, "TI TPS65217 Power Management IC"); 13312694Salexsch 13412694Salexsch return (0); 13512694Salexsch} 13612694Salexsch 1370SN/Astatic void 13812694Salexscham335x_pmic_dump_chgconfig(device_t dev) 13912694Salexsch{ 1400SN/A struct tps65217_chgconfig0_reg reg0; 1410SN/A struct tps65217_chgconfig1_reg reg1; 1420SN/A struct tps65217_chgconfig2_reg reg2; 1430SN/A struct tps65217_chgconfig3_reg reg3; 1440SN/A const char *e_d[] = {"enabled", "disabled"}; 1450SN/A const char *d_e[] = {"disabled", "enabled"}; 1460SN/A const char *i_a[] = {"inactive", "active"}; 1470SN/A const char *f_t[] = {"false", "true"}; 1480SN/A const char *timer_c[] = {"4h", "5h", "6h", "8h"}; 1490SN/A const char *ntc_type_c[] = {"100k", "10k"}; 1500SN/A const char *vprechg_c[] = {"2.9V", "2.5V"}; 1510SN/A const char *trange_c[] = {"0-45 C", "0-60 C"}; 1520SN/A const char *termif_c[] = {"2.5%", "7.5%", "15%", "18%"}; 1530SN/A const char *pchrgt_c[] = {"30 min", "60 min"}; 1540SN/A const char *dppmth_c[] = {"3.50V", "3.75V", "4.00V", "4.25V"}; 1550SN/A const char *ichrg_c[] = {"300mA", "400mA", "500mA", "700mA"}; 1561637SN/A 1571637SN/A am335x_pmic_read(dev, TPS65217_CHGCONFIG0_REG, (uint8_t *)®0, 1); 1581637SN/A device_printf(dev, " BAT TEMP/NTC ERROR: %s\n", f_t[reg0.battemp]); 1591637SN/A device_printf(dev, " Pre-charge timer time-out: %s\n", f_t[reg0.pchgtout]); 1600SN/A device_printf(dev, " Charge timer time-out: %s\n", f_t[reg0.chgtout]); 1611734SN/A device_printf(dev, " Charger active: %s\n", f_t[reg0.active]); 1621734SN/A device_printf(dev, " Termination current detected: %s\n", f_t[reg0.termi]); 1631734SN/A device_printf(dev, " Thermal suspend: %s\n", f_t[reg0.tsusp]); 1641734SN/A device_printf(dev, " DPPM active: %s\n", f_t[reg0.dppm]); 1651734SN/A device_printf(dev, " Thermal regulation: %s\n", i_a[reg0.treg]); 1661734SN/A 1671734SN/A am335x_pmic_read(dev, TPS65217_CHGCONFIG1_REG, (uint8_t *)®1, 1); 1681734SN/A device_printf(dev, " Charger: %s\n", d_e[reg1.chg_en]); 1691734SN/A device_printf(dev, " Suspend charge: %s\n", i_a[reg1.susp]); 1701734SN/A device_printf(dev, " Charge termination: %s\n", e_d[reg1.term]); 1711734SN/A device_printf(dev, " Charger reset: %s\n", i_a[reg1.reset]); 1721734SN/A device_printf(dev, " NTC TYPE: %s\n", ntc_type_c[reg1.ntc_type]); 1731734SN/A device_printf(dev, " Safety timer: %s\n", d_e[reg1.tmr_en]); 1740SN/A device_printf(dev, " Charge safety timer: %s\n", timer_c[reg1.timer]); 1750SN/A 1760SN/A am335x_pmic_read(dev, TPS65217_CHGCONFIG2_REG, (uint8_t *)®2, 1); 1770SN/A device_printf(dev, " Charge voltage: %s\n", tps65217_voreg_c[reg2.voreg]); 1780SN/A device_printf(dev, " Pre-charge to fast charge transition voltage: %s\n", 17912631Savstepan vprechg_c[reg2.vprechg]); 18012631Savstepan device_printf(dev, " Dynamic timer function: %s\n", d_e[reg2.dyntmr]); 1810SN/A 1820SN/A am335x_pmic_read(dev, TPS65217_CHGCONFIG3_REG, (uint8_t *)®3, 1); 1831686SN/A device_printf(dev, " Temperature range for charging: %s\n", trange_c[reg3.trange]); 1840SN/A device_printf(dev, " Termination current factor: %s\n", termif_c[reg3.termif]); 1850SN/A device_printf(dev, " Pre-charge time: %s\n", pchrgt_c[reg3.pchrgt]); 1860SN/A device_printf(dev, " Power path DPPM threshold: %s\n", dppmth_c[reg3.dppmth]); 1870SN/A device_printf(dev, " Charge current: %s\n", ichrg_c[reg3.ichrg]); 1880SN/A} 1890SN/A 1900SN/Astatic void 1910SN/Aam335x_pmic_setvo(device_t dev, uint8_t vo) 1920SN/A{ 1930SN/A struct tps65217_chgconfig2_reg reg2; 1940SN/A 1950SN/A am335x_pmic_read(dev, TPS65217_CHGCONFIG2_REG, (uint8_t *)®2, 1); 1960SN/A reg2.voreg = vo; 1970SN/A am335x_pmic_write(dev, TPS65217_CHGCONFIG2_REG, (uint8_t *)®2, 1); 1980SN/A} 1990SN/A 2001637SN/Astatic void 2011637SN/Aam335x_pmic_start(struct am335x_pmic_softc *sc) 2021738SN/A{ 2030SN/A device_t dev; 2040SN/A struct tps65217_status_reg status_reg; 2050SN/A struct tps65217_chipid_reg chipid_reg; 2060SN/A uint8_t reg, vo; 2071738SN/A char name[20]; 2081738SN/A char pwr[4][11] = {"Battery", "USB", "AC", "USB and AC"}; 2091738SN/A int rv; 2101738SN/A phandle_t node; 2110SN/A 2120SN/A dev = sc->sc_dev; 2130SN/A am335x_pmic_read(dev, TPS65217_CHIPID_REG, (uint8_t *)&chipid_reg, 1); 2143973SN/A switch (chipid_reg.chip) { 2153973SN/A case TPS65217A: 2161738SN/A sprintf(name, "TPS65217A ver 1.%u", chipid_reg.rev); 2173973SN/A break; 2180SN/A case TPS65217B: 2190SN/A sprintf(name, "TPS65217B ver 1.%u", chipid_reg.rev); 2200SN/A break; 2211637SN/A case TPS65217C: 2220SN/A sprintf(name, "TPS65217C ver 1.%u", chipid_reg.rev); 2230SN/A break; 2240SN/A case TPS65217D: 2250SN/A sprintf(name, "TPS65217D ver 1.%u", chipid_reg.rev); 2260SN/A break; 2270SN/A default: 2280SN/A sprintf(name, "Unknown PMIC"); 2290SN/A } 2301637SN/A 2311637SN/A am335x_pmic_read(dev, TPS65217_STATUS_REG, (uint8_t *)&status_reg, 1); 2321637SN/A device_printf(dev, "%s powered by %s\n", name, 2330SN/A pwr[status_reg.usbpwr | (status_reg.acpwr << 1)]); 2341637SN/A 2351637SN/A /* Check devicetree for ti,pmic-shutdown-controller 2361637SN/A * if present; PMIC will go to shutdown state on PWR_EN toggle 2371637SN/A * if not present; PMIC will enter sleep state on PWR_EN toggle (default on reset) 2381637SN/A */ 2391637SN/A node = ofw_bus_get_node(dev); 2401637SN/A if (OF_hasprop(node, "ti,pmic-shutdown-controller")) { 2411637SN/A status_reg.off = 1; 2420SN/A am335x_pmic_write(dev, TPS65217_STATUS_REG, (uint8_t *)&status_reg, 1); 2431637SN/A } 2441637SN/A 2450SN/A if (am335x_pmic_vo[0] != '\0') { 2460SN/A for (vo = 0; vo < 4; vo++) { 2470SN/A if (strcmp(tps65217_voreg_c[vo], am335x_pmic_vo) == 0) 2480SN/A break; 2490SN/A } 2501637SN/A if (vo == 4) { 2511637SN/A device_printf(dev, "WARNING: hw.am335x_pmic.vo=\"%s\"" 2521637SN/A ": unsupported value\n", am335x_pmic_vo); 2531637SN/A } else { 2541637SN/A am335x_pmic_setvo(dev, vo); 2551637SN/A } 2561637SN/A } 2571637SN/A 2580SN/A if (bootverbose || am335x_pmic_bootverbose) { 2590SN/A am335x_pmic_dump_chgconfig(dev); 2601637SN/A } 2610SN/A 2620SN/A EVENTHANDLER_REGISTER(shutdown_final, am335x_pmic_shutdown, dev, 2630SN/A SHUTDOWN_PRI_LAST); 2640SN/A 2650SN/A /* Unmask all interrupts and clear pending status */ 2660SN/A reg = 0; 2670SN/A am335x_pmic_write(dev, TPS65217_INT_REG, ®, 1); 2680SN/A am335x_pmic_read(dev, TPS65217_INT_REG, ®, 1); 2690SN/A 2700SN/A if (sc->sc_irq_res != NULL) { 2710SN/A rv = bus_setup_intr(dev, sc->sc_irq_res, 2720SN/A INTR_TYPE_MISC | INTR_MPSAFE, NULL, am335x_pmic_intr, 2730SN/A sc, &sc->sc_intrhand); 2740SN/A if (rv != 0) 2750SN/A device_printf(dev, 2760SN/A "Unable to setup the irq handler.\n"); 2770SN/A } 2780SN/A} 2790SN/A 2800SN/Astatic int 2810SN/Aam335x_pmic_attach(device_t dev) 2820SN/A{ 2830SN/A struct am335x_pmic_softc *sc; 2840SN/A int rid; 2850SN/A 2860SN/A sc = device_get_softc(dev); 2870SN/A 2880SN/A rid = 0; 2890SN/A sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 2900SN/A RF_ACTIVE); 2910SN/A if (!sc->sc_irq_res) { 2920SN/A device_printf(dev, "cannot allocate interrupt\n"); 2930SN/A /* return (ENXIO); */ 2940SN/A } 2950SN/A 2960SN/A am335x_pmic_start(sc); 2970SN/A 2980SN/A return (0); 2990SN/A} 3000SN/A 30111166Sdarcystatic void 3020SN/Aam335x_pmic_shutdown(void *xdev, int howto) 3030SN/A{ 3040SN/A if (!(howto & RB_POWEROFF)) 3050SN/A return; 3060SN/A 3070SN/A /* Toggle pmic_pwr_enable to shutdown the PMIC. */ 3080SN/A am335x_rtc_pmic_pwr_toggle(); 3090SN/A} 3100SN/A 3110SN/Astatic device_method_t am335x_pmic_methods[] = { 3120SN/A DEVMETHOD(device_probe, am335x_pmic_probe), 3130SN/A DEVMETHOD(device_attach, am335x_pmic_attach), 3140SN/A {0, 0}, 3150SN/A}; 31612631Savstepan 3170SN/Astatic driver_t am335x_pmic_driver = { 3180SN/A "am335x_pmic", 3190SN/A am335x_pmic_methods, 3200SN/A sizeof(struct am335x_pmic_softc), 3210SN/A}; 32216118Salexsch 32316118SalexschDRIVER_MODULE(am335x_pmic, iicbus, am335x_pmic_driver, 0, 0); 32416118SalexschMODULE_VERSION(am335x_pmic, 1); 32516118SalexschMODULE_DEPEND(am335x_pmic, iicbus, 1, 1, 1); 32616118Salexsch