Home | History | Annotate | Line # | Download | only in dev
      1  1.6   thorpej /*/* $NetBSD: tadpmu.c,v 1.6 2023/12/20 05:33:58 thorpej Exp $ */
      2  1.1  macallan 
      3  1.1  macallan /*-
      4  1.1  macallan  * Copyright (c) 2018 Michael Lorenz <macallan (at) netbsd.org>
      5  1.1  macallan  * All rights reserved.
      6  1.1  macallan  *
      7  1.1  macallan  * Redistribution and use in source and binary forms, with or without
      8  1.1  macallan  * modification, are permitted provided that the following conditions
      9  1.1  macallan  * are met:
     10  1.1  macallan  * 1. Redistributions of source code must retain the above copyright
     11  1.1  macallan  *    notice, this list of conditions and the following disclaimer.
     12  1.1  macallan  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  macallan  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  macallan  *    documentation and/or other materials provided with the distribution.
     15  1.1  macallan  *
     16  1.1  macallan  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  1.1  macallan  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  1.1  macallan  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  1.1  macallan  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  1.1  macallan  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  1.1  macallan  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  1.1  macallan  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  1.1  macallan  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  1.1  macallan  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  1.1  macallan  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  1.1  macallan  * POSSIBILITY OF SUCH DAMAGE.
     27  1.1  macallan  */
     28  1.1  macallan 
     29  1.5       jdc /* a driver for the PMU found in Tadpole Viper and SPARCle laptops */
     30  1.1  macallan 
     31  1.3  macallan #include "opt_tadpmu.h"
     32  1.3  macallan #ifdef HAVE_TADPMU
     33  1.1  macallan #include <sys/param.h>
     34  1.1  macallan #include <sys/systm.h>
     35  1.1  macallan #include <sys/kernel.h>
     36  1.1  macallan #include <sys/device.h>
     37  1.2  macallan #include <sys/proc.h>
     38  1.1  macallan #include <sys/bus.h>
     39  1.1  macallan #include <sys/intr.h>
     40  1.4  macallan #include <sys/kthread.h>
     41  1.4  macallan #include <sys/mutex.h>
     42  1.1  macallan 
     43  1.1  macallan #include <dev/sysmon/sysmonvar.h>
     44  1.2  macallan #include <dev/sysmon/sysmon_taskq.h>
     45  1.1  macallan 
     46  1.1  macallan #include <sparc64/dev/tadpmureg.h>
     47  1.1  macallan #include <sparc64/dev/tadpmuvar.h>
     48  1.1  macallan 
     49  1.2  macallan #ifdef TADPMU_DEBUG
     50  1.2  macallan #define DPRINTF printf
     51  1.2  macallan #else
     52  1.2  macallan #define DPRINTF while (0) printf
     53  1.2  macallan #endif
     54  1.2  macallan 
     55  1.1  macallan static bus_space_tag_t tadpmu_iot;
     56  1.1  macallan static bus_space_handle_t tadpmu_hcmd;
     57  1.1  macallan static bus_space_handle_t tadpmu_hdata;
     58  1.5       jdc static struct sysmon_envsys *tadpmu_sens_sme;
     59  1.5       jdc static struct sysmon_envsys *tadpmu_acad_sme;
     60  1.5       jdc static struct sysmon_envsys *tadpmu_batt_sme;
     61  1.5       jdc static envsys_data_t tadpmu_sensors[8];
     62  1.2  macallan static uint8_t idata = 0xff;
     63  1.2  macallan static uint8_t ivalid = 0;
     64  1.5       jdc static uint8_t ev_data = 0;
     65  1.4  macallan static wchan_t tadpmu, tadpmuev;
     66  1.5       jdc static struct sysmon_pswitch tadpmu_pbutton, tadpmu_lidswitch, tadpmu_dcpower;
     67  1.5       jdc static kmutex_t tadpmu_lock, data_lock;
     68  1.4  macallan static lwp_t *tadpmu_thread;
     69  1.4  macallan static int tadpmu_dying = 0;
     70  1.1  macallan 
     71  1.1  macallan static inline void
     72  1.1  macallan tadpmu_cmd(uint8_t d)
     73  1.1  macallan {
     74  1.1  macallan 	bus_space_write_1(tadpmu_iot, tadpmu_hcmd, 0, d);
     75  1.1  macallan }
     76  1.1  macallan 
     77  1.1  macallan static inline void
     78  1.1  macallan tadpmu_wdata(uint8_t d)
     79  1.1  macallan {
     80  1.1  macallan 	bus_space_write_1(tadpmu_iot, tadpmu_hdata, 0, d);
     81  1.1  macallan }
     82  1.1  macallan 
     83  1.1  macallan static inline uint8_t
     84  1.1  macallan tadpmu_status(void)
     85  1.1  macallan {
     86  1.1  macallan 	return bus_space_read_1(tadpmu_iot, tadpmu_hcmd, 0);
     87  1.1  macallan }
     88  1.1  macallan 
     89  1.1  macallan static inline uint8_t
     90  1.1  macallan tadpmu_data(void)
     91  1.1  macallan {
     92  1.1  macallan 	return bus_space_read_1(tadpmu_iot, tadpmu_hdata, 0);
     93  1.1  macallan }
     94  1.1  macallan 
     95  1.1  macallan static void
     96  1.1  macallan tadpmu_flush(void)
     97  1.1  macallan {
     98  1.1  macallan 	volatile uint8_t junk, d;
     99  1.1  macallan 	int bail = 0;
    100  1.1  macallan 
    101  1.1  macallan 	d = tadpmu_status();
    102  1.1  macallan 	while (d & STATUS_HAVE_DATA) {
    103  1.1  macallan 		junk = tadpmu_data();
    104  1.1  macallan 		__USE(junk);
    105  1.1  macallan 		delay(10);
    106  1.1  macallan 		bail++;
    107  1.1  macallan 		if (bail > 100) {
    108  1.1  macallan 			printf("%s: timeout waiting for data out to clear %2x\n",
    109  1.1  macallan 			    __func__, d);
    110  1.1  macallan 			break;
    111  1.1  macallan 		}
    112  1.1  macallan 		d = tadpmu_status();
    113  1.1  macallan 	}
    114  1.1  macallan 	bail = 0;
    115  1.1  macallan 	d = tadpmu_status();
    116  1.1  macallan 	while (d & STATUS_SEND_DATA) {
    117  1.1  macallan 		bus_space_write_1(tadpmu_iot, tadpmu_hdata, 0, 0);
    118  1.1  macallan 		delay(10);
    119  1.1  macallan 		bail++;
    120  1.1  macallan 		if (bail > 100) {
    121  1.1  macallan 			printf("%s: timeout waiting for data in to clear %02x\n",
    122  1.1  macallan 			    __func__, d);
    123  1.1  macallan 			break;
    124  1.1  macallan 		}
    125  1.1  macallan 		d = tadpmu_status();
    126  1.1  macallan 	}
    127  1.1  macallan }
    128  1.1  macallan 
    129  1.1  macallan static void
    130  1.1  macallan tadpmu_send_cmd(uint8_t cmd)
    131  1.1  macallan {
    132  1.1  macallan 	int bail = 0;
    133  1.1  macallan 	uint8_t d;
    134  1.1  macallan 
    135  1.2  macallan 	ivalid = 0;
    136  1.1  macallan 	tadpmu_cmd(cmd);
    137  1.1  macallan 
    138  1.1  macallan 	d = tadpmu_status();
    139  1.1  macallan 	while ((d & STATUS_CMD_IN_PROGRESS) == 0) {
    140  1.1  macallan 		delay(10);
    141  1.1  macallan 		bail++;
    142  1.1  macallan 		if (bail > 100) {
    143  1.1  macallan 			printf("%s: timeout waiting for command to start\n",
    144  1.1  macallan 			    __func__);
    145  1.1  macallan 			break;
    146  1.1  macallan 		}
    147  1.1  macallan 		d = tadpmu_status();
    148  1.1  macallan 	}
    149  1.1  macallan }
    150  1.1  macallan 
    151  1.1  macallan static uint8_t
    152  1.1  macallan tadpmu_recv(void)
    153  1.1  macallan {
    154  1.1  macallan 	int bail = 0;
    155  1.1  macallan 	uint8_t d;
    156  1.1  macallan 
    157  1.2  macallan 	if (cold) {
    158  1.2  macallan 		d = tadpmu_status();
    159  1.2  macallan 		while ((d & STATUS_HAVE_DATA) == 0) {
    160  1.2  macallan 			delay(10);
    161  1.2  macallan 			bail++;
    162  1.2  macallan 			if (bail > 1000) {
    163  1.2  macallan 				printf("%s: timeout waiting for data %02x\n",
    164  1.2  macallan 				    __func__, d);
    165  1.2  macallan 				break;
    166  1.2  macallan 			}
    167  1.2  macallan 			d = tadpmu_status();
    168  1.1  macallan 		}
    169  1.2  macallan 		return bus_space_read_1(tadpmu_iot, tadpmu_hdata, 0);
    170  1.2  macallan 	} else {
    171  1.2  macallan 		while (ivalid == 0)
    172  1.2  macallan 			tsleep(tadpmu, 0, "pmucmd", 1);
    173  1.2  macallan 		return idata;
    174  1.1  macallan 	}
    175  1.1  macallan }
    176  1.1  macallan 
    177  1.1  macallan static void
    178  1.1  macallan tadpmu_send(uint8_t v)
    179  1.1  macallan {
    180  1.1  macallan 	int bail = 0;
    181  1.1  macallan 	uint8_t d;
    182  1.1  macallan 
    183  1.1  macallan 	d = tadpmu_status();
    184  1.1  macallan 	while ((d & STATUS_SEND_DATA) == 0) {
    185  1.1  macallan 		delay(10);
    186  1.1  macallan 		bail++;
    187  1.1  macallan 		if (bail > 1000) {
    188  1.1  macallan 			printf("%s: timeout waiting for PMU ready %02x\n", __func__, d);
    189  1.1  macallan 			break;
    190  1.1  macallan 		}
    191  1.1  macallan 		d = tadpmu_status();
    192  1.1  macallan 	}
    193  1.1  macallan 
    194  1.1  macallan 	tadpmu_wdata(v);
    195  1.1  macallan 
    196  1.1  macallan 	while ((d & STATUS_SEND_DATA) != 0) {
    197  1.1  macallan 		delay(10);
    198  1.1  macallan 		bail++;
    199  1.1  macallan 		if (bail > 1000) {
    200  1.1  macallan 			printf("%s: timeout waiting for accept data %02x\n", __func__, d);
    201  1.1  macallan 			break;
    202  1.1  macallan 		}
    203  1.1  macallan 		d = tadpmu_status();
    204  1.1  macallan 	}
    205  1.1  macallan }
    206  1.1  macallan 
    207  1.5       jdc static uint32_t
    208  1.5       jdc tadpmu_battery_capacity(uint8_t gstat)
    209  1.5       jdc {
    210  1.5       jdc 	uint8_t res;
    211  1.5       jdc 
    212  1.5       jdc 	if (gstat == GENSTAT_STATE_BATTERY_FULL) {
    213  1.5       jdc 		return ENVSYS_BATTERY_CAPACITY_NORMAL;
    214  1.5       jdc 	}
    215  1.5       jdc 
    216  1.5       jdc 	mutex_enter(&tadpmu_lock);
    217  1.5       jdc 	tadpmu_flush();
    218  1.5       jdc 	tadpmu_send_cmd(CMD_READ_VBATT);
    219  1.5       jdc 	res = tadpmu_recv();
    220  1.5       jdc 	mutex_exit(&tadpmu_lock);
    221  1.5       jdc 
    222  1.5       jdc 	if (gstat & GENSTAT_STATE_BATTERY_DISCHARGE) {
    223  1.5       jdc 		if (res < TADPMU_BATT_DIS_CAP_CRIT)
    224  1.5       jdc 			return ENVSYS_BATTERY_CAPACITY_CRITICAL;
    225  1.5       jdc 		if (res < TADPMU_BATT_DIS_CAP_WARN)
    226  1.5       jdc 			return ENVSYS_BATTERY_CAPACITY_WARNING;
    227  1.5       jdc 		if (res < TADPMU_BATT_DIS_CAP_LOW)
    228  1.5       jdc 			return ENVSYS_BATTERY_CAPACITY_LOW;
    229  1.5       jdc 		else
    230  1.5       jdc 			return ENVSYS_BATTERY_CAPACITY_NORMAL;
    231  1.5       jdc 	} else if (gstat == GENSTAT_STATE_BATTERY_CHARGE) {
    232  1.5       jdc 		if (res < TADPMU_BATT_CHG_CAP_CRIT)
    233  1.5       jdc 			return ENVSYS_BATTERY_CAPACITY_CRITICAL;
    234  1.5       jdc 		else if (res < TADPMU_BATT_CHG_CAP_WARN)
    235  1.5       jdc 			return ENVSYS_BATTERY_CAPACITY_WARNING;
    236  1.5       jdc 		else if (res < TADPMU_BATT_CHG_CAP_LOW)
    237  1.5       jdc 			return ENVSYS_BATTERY_CAPACITY_LOW;
    238  1.5       jdc 		else
    239  1.5       jdc 			return ENVSYS_BATTERY_CAPACITY_NORMAL;
    240  1.5       jdc 	} else {
    241  1.5       jdc 		DPRINTF("%s unknown battery state %02x\n",
    242  1.5       jdc 		    __func__, gstat);
    243  1.5       jdc 		return ENVSYS_BATTERY_CAPACITY_NORMAL;
    244  1.5       jdc 	}
    245  1.5       jdc }
    246  1.5       jdc 
    247  1.5       jdc /* The data to read is calculated from the command and the units */
    248  1.1  macallan static void
    249  1.1  macallan tadpmu_sensors_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
    250  1.1  macallan {
    251  1.1  macallan 	int res;
    252  1.5       jdc 
    253  1.1  macallan 	if (edata->private > 0) {
    254  1.4  macallan 		mutex_enter(&tadpmu_lock);
    255  1.1  macallan 		tadpmu_flush();
    256  1.1  macallan 		tadpmu_send_cmd(edata->private);
    257  1.1  macallan 		res = tadpmu_recv();
    258  1.4  macallan 		mutex_exit(&tadpmu_lock);
    259  1.1  macallan 		if (edata->units == ENVSYS_STEMP) {
    260  1.1  macallan 			edata->value_cur = res * 1000000 + 273150000;
    261  1.5       jdc 		} else if (edata->units == ENVSYS_SVOLTS_DC) {
    262  1.5       jdc 			edata->value_cur = res * 100000;
    263  1.5       jdc 		} else if (edata->units == ENVSYS_BATTERY_CHARGE) {
    264  1.5       jdc 			if (res & GENSTAT_BATTERY_CHARGING)
    265  1.5       jdc 				edata->value_cur = ENVSYS_INDICATOR_TRUE;
    266  1.5       jdc 			else
    267  1.5       jdc 				edata->value_cur = ENVSYS_INDICATOR_FALSE;
    268  1.5       jdc 		} else if (edata->units == ENVSYS_BATTERY_CAPACITY) {
    269  1.5       jdc 			edata->value_cur = tadpmu_battery_capacity(res);
    270  1.1  macallan 		} else {
    271  1.5       jdc 			if (edata->units == ENVSYS_INDICATOR &&
    272  1.5       jdc 			    edata->private == CMD_READ_GENSTAT) {
    273  1.5       jdc 				if (res & GENSTAT_DC_PRESENT)
    274  1.5       jdc 					edata->value_cur =
    275  1.5       jdc 					    ENVSYS_INDICATOR_TRUE;
    276  1.5       jdc 				else
    277  1.5       jdc 					edata->value_cur =
    278  1.5       jdc 					    ENVSYS_INDICATOR_FALSE;
    279  1.5       jdc 			} else {
    280  1.5       jdc 				edata->value_cur = res;
    281  1.5       jdc 			}
    282  1.1  macallan 		}
    283  1.1  macallan 		edata->state = ENVSYS_SVALID;
    284  1.1  macallan 	} else {
    285  1.1  macallan 		edata->state = ENVSYS_SINVALID;
    286  1.1  macallan 	}
    287  1.1  macallan }
    288  1.1  macallan 
    289  1.4  macallan static void
    290  1.4  macallan tadpmu_events(void *cookie)
    291  1.4  macallan {
    292  1.5       jdc 	uint8_t events, gs, vb;
    293  1.5       jdc 
    294  1.4  macallan 	while (!tadpmu_dying) {
    295  1.4  macallan 		mutex_enter(&tadpmu_lock);
    296  1.4  macallan 		tadpmu_flush();
    297  1.4  macallan 		tadpmu_send_cmd(CMD_READ_GENSTAT);
    298  1.5       jdc 		gs = tadpmu_recv();
    299  1.5       jdc 		tadpmu_send_cmd(CMD_READ_VBATT);
    300  1.5       jdc 		vb = tadpmu_recv();
    301  1.4  macallan 		mutex_exit(&tadpmu_lock);
    302  1.5       jdc 
    303  1.5       jdc 		mutex_enter(&data_lock);
    304  1.5       jdc 		events = ev_data;
    305  1.5       jdc 		mutex_exit(&data_lock);
    306  1.5       jdc 		DPRINTF("%s event %02x, status %02x/%02x\n", __func__,
    307  1.5       jdc 		    events, gs, vb);
    308  1.5       jdc 
    309  1.5       jdc 		if (events & TADPMU_EV_PWRBUTT) {
    310  1.5       jdc 			mutex_enter(&data_lock);
    311  1.5       jdc 			ev_data &= ~TADPMU_EV_PWRBUTT;
    312  1.5       jdc 			mutex_exit(&data_lock);
    313  1.5       jdc 			sysmon_pswitch_event(&tadpmu_pbutton,
    314  1.5       jdc 			    PSWITCH_EVENT_PRESSED);
    315  1.5       jdc 		}
    316  1.5       jdc 
    317  1.5       jdc 		if (events & TADPMU_EV_LID) {
    318  1.5       jdc 			mutex_enter(&data_lock);
    319  1.5       jdc 			ev_data &= ~TADPMU_EV_LID;
    320  1.5       jdc 			mutex_exit(&data_lock);
    321  1.4  macallan 			sysmon_pswitch_event(&tadpmu_lidswitch,
    322  1.5       jdc 			    gs & GENSTAT_LID_CLOSED ?
    323  1.5       jdc 		            PSWITCH_EVENT_PRESSED : PSWITCH_EVENT_RELEASED);
    324  1.5       jdc 		}
    325  1.5       jdc 
    326  1.5       jdc 		if (events & TADPMU_EV_DCPOWER) {
    327  1.5       jdc 			mutex_enter(&data_lock);
    328  1.5       jdc 			ev_data &= ~TADPMU_EV_DCPOWER;
    329  1.5       jdc 			mutex_exit(&data_lock);
    330  1.5       jdc 			sysmon_pswitch_event(&tadpmu_dcpower,
    331  1.5       jdc 			    gs & GENSTAT_DC_PRESENT ?
    332  1.5       jdc 		            PSWITCH_EVENT_PRESSED : PSWITCH_EVENT_RELEASED);
    333  1.4  macallan 		}
    334  1.5       jdc 
    335  1.5       jdc 		if (events & TADPMU_EV_BATTCHANGE) {
    336  1.5       jdc 			mutex_enter(&data_lock);
    337  1.5       jdc 			ev_data &= ~TADPMU_EV_BATTCHANGE;
    338  1.5       jdc 			mutex_exit(&data_lock);
    339  1.5       jdc 			if (gs == GENSTAT_STATE_BATTERY_DISCHARGE) {
    340  1.5       jdc 				if (vb < TADPMU_BATT_DIS_CAP_CRIT)
    341  1.5       jdc 					printf("Battery critical!\n");
    342  1.5       jdc 				else if (vb < TADPMU_BATT_DIS_CAP_WARN)
    343  1.5       jdc 					printf("Battery warning!\n");
    344  1.5       jdc 			}
    345  1.5       jdc 		}
    346  1.5       jdc 
    347  1.5       jdc 		if (events & TADPMU_EV_BATTCHARGED) {
    348  1.5       jdc 			mutex_enter(&data_lock);
    349  1.5       jdc 			ev_data &= ~TADPMU_EV_BATTCHARGED;
    350  1.5       jdc 			mutex_exit(&data_lock);
    351  1.5       jdc 			printf("Battery charged\n");
    352  1.5       jdc 		}
    353  1.5       jdc 
    354  1.4  macallan 		tsleep(tadpmuev, 0, "tadpmuev", hz);
    355  1.4  macallan 	}
    356  1.4  macallan 	kthread_exit(0);
    357  1.4  macallan }
    358  1.4  macallan 
    359  1.2  macallan int
    360  1.2  macallan tadpmu_intr(void *cookie)
    361  1.2  macallan {
    362  1.2  macallan 	uint8_t s = tadpmu_status(), d;
    363  1.2  macallan 	if (s & STATUS_INTR) {
    364  1.2  macallan 		/* interrupt message */
    365  1.2  macallan 		d = tadpmu_data();
    366  1.5       jdc 		DPRINTF("%s status change %02x\n", __func__, d);
    367  1.5       jdc 
    368  1.2  macallan 		switch (d) {
    369  1.5       jdc 			case TADPMU_INTR_POWERBUTTON:
    370  1.5       jdc 				mutex_enter(&data_lock);
    371  1.5       jdc 				ev_data |= TADPMU_EV_PWRBUTT;;
    372  1.5       jdc 				mutex_exit(&data_lock);
    373  1.5       jdc 				break;
    374  1.5       jdc 			case TADPMU_INTR_LID:
    375  1.5       jdc 				mutex_enter(&data_lock);
    376  1.5       jdc 				ev_data |= TADPMU_EV_LID;
    377  1.5       jdc 				mutex_exit(&data_lock);
    378  1.5       jdc 				break;
    379  1.5       jdc 			case TADPMU_INTR_DCPOWER:
    380  1.5       jdc 				mutex_enter(&data_lock);
    381  1.5       jdc 				ev_data |= TADPMU_EV_DCPOWER;
    382  1.5       jdc 				mutex_exit(&data_lock);
    383  1.2  macallan 				break;
    384  1.5       jdc 			case TADPMU_INTR_BATTERY_STATE:
    385  1.5       jdc 				mutex_enter(&data_lock);
    386  1.5       jdc 				ev_data |= TADPMU_EV_BATTCHANGE;
    387  1.5       jdc 				mutex_exit(&data_lock);
    388  1.5       jdc 				break;
    389  1.5       jdc 			case TADPMU_INTR_BATTERY_CHARGED:
    390  1.5       jdc 				mutex_enter(&data_lock);
    391  1.5       jdc 				ev_data |= TADPMU_EV_BATTCHARGED;
    392  1.5       jdc 				mutex_exit(&data_lock);
    393  1.2  macallan 				break;
    394  1.2  macallan 		}
    395  1.5       jdc 		/* Report events */
    396  1.5       jdc 		if (ev_data)
    397  1.5       jdc 			wakeup(tadpmuev);
    398  1.2  macallan 	}
    399  1.2  macallan 	s = tadpmu_status();
    400  1.2  macallan 	if (s & STATUS_HAVE_DATA) {
    401  1.2  macallan 		idata = tadpmu_data();
    402  1.2  macallan 		ivalid = 1;
    403  1.2  macallan 		wakeup(tadpmu);
    404  1.2  macallan 		DPRINTF("%s data %02x\n", __func__, idata);
    405  1.2  macallan 	}
    406  1.2  macallan 
    407  1.2  macallan 	return 1;
    408  1.2  macallan }
    409  1.2  macallan 
    410  1.1  macallan int
    411  1.1  macallan tadpmu_init(bus_space_tag_t t, bus_space_handle_t hcmd, bus_space_handle_t hdata)
    412  1.1  macallan {
    413  1.5       jdc 	uint8_t ver;
    414  1.1  macallan 
    415  1.1  macallan 	tadpmu_iot = t;
    416  1.1  macallan 	tadpmu_hcmd = hcmd;
    417  1.1  macallan 	tadpmu_hdata = hdata;
    418  1.1  macallan 
    419  1.1  macallan 	tadpmu_flush();
    420  1.1  macallan 	delay(1000);
    421  1.1  macallan 
    422  1.1  macallan 	tadpmu_send_cmd(CMD_READ_VERSION);
    423  1.1  macallan 	ver = tadpmu_recv();
    424  1.1  macallan 	printf("Tadpole PMU Version 1.%d\n", ver);
    425  1.1  macallan 
    426  1.1  macallan 	tadpmu_send_cmd(CMD_SET_OPMODE);
    427  1.5       jdc 	tadpmu_send(OPMODE_UNIX);
    428  1.1  macallan 
    429  1.5       jdc #ifdef TADPMU_DEBUG
    430  1.1  macallan 	tadpmu_send_cmd(CMD_READ_SYSTEMP);
    431  1.1  macallan 	ver = tadpmu_recv();
    432  1.5       jdc 	printf("Temperature 0x%02x\n", ver);
    433  1.1  macallan 
    434  1.1  macallan 	tadpmu_send_cmd(CMD_READ_VBATT);
    435  1.1  macallan 	ver = tadpmu_recv();
    436  1.5       jdc 	printf("Battery voltage 0x%02x\n", ver);
    437  1.1  macallan 
    438  1.1  macallan 	tadpmu_send_cmd(CMD_READ_GENSTAT);
    439  1.1  macallan 	ver = tadpmu_recv();
    440  1.5       jdc 	printf("status 0x%02x\n", ver);
    441  1.5       jdc #endif
    442  1.1  macallan 
    443  1.4  macallan 	mutex_init(&tadpmu_lock, MUTEX_DEFAULT, IPL_NONE);
    444  1.5       jdc 	mutex_init(&data_lock, MUTEX_DEFAULT, IPL_HIGH);
    445  1.4  macallan 
    446  1.5       jdc 	tadpmu_sens_sme = sysmon_envsys_create();
    447  1.5       jdc 	tadpmu_sens_sme->sme_name = "tadpmu";
    448  1.5       jdc 	tadpmu_sens_sme->sme_cookie = NULL;
    449  1.5       jdc 	tadpmu_sens_sme->sme_refresh = tadpmu_sensors_refresh;
    450  1.5       jdc 
    451  1.5       jdc 	tadpmu_acad_sme = sysmon_envsys_create();
    452  1.5       jdc 	tadpmu_acad_sme->sme_name = "ac adapter";
    453  1.5       jdc 	tadpmu_acad_sme->sme_cookie = NULL;
    454  1.5       jdc 	tadpmu_acad_sme->sme_refresh = tadpmu_sensors_refresh;
    455  1.5       jdc 	tadpmu_acad_sme->sme_class = SME_CLASS_ACADAPTER;
    456  1.5       jdc 
    457  1.5       jdc 	tadpmu_batt_sme = sysmon_envsys_create();
    458  1.5       jdc 	tadpmu_batt_sme->sme_name = "battery";
    459  1.5       jdc 	tadpmu_batt_sme->sme_cookie = NULL;
    460  1.5       jdc 	tadpmu_batt_sme->sme_refresh = tadpmu_sensors_refresh;
    461  1.5       jdc 	tadpmu_batt_sme->sme_class = SME_CLASS_BATTERY;
    462  1.1  macallan 
    463  1.5       jdc 	tadpmu_sensors[0].state = ENVSYS_SINVALID;
    464  1.1  macallan 	tadpmu_sensors[0].units = ENVSYS_STEMP;
    465  1.1  macallan 	tadpmu_sensors[0].private = CMD_READ_SYSTEMP;
    466  1.1  macallan 	strcpy(tadpmu_sensors[0].desc, "systemp");
    467  1.5       jdc 	sysmon_envsys_sensor_attach(tadpmu_sens_sme, &tadpmu_sensors[0]);
    468  1.5       jdc 
    469  1.5       jdc 	tadpmu_sensors[1].state = ENVSYS_SINVALID;
    470  1.5       jdc 	tadpmu_sensors[1].units = ENVSYS_INDICATOR;
    471  1.5       jdc 	tadpmu_sensors[1].private = CMD_READ_FAN_EN;
    472  1.5       jdc 	strcpy(tadpmu_sensors[1].desc, "fan on");
    473  1.5       jdc 	sysmon_envsys_sensor_attach(tadpmu_sens_sme, &tadpmu_sensors[1]);
    474  1.5       jdc 
    475  1.5       jdc 	tadpmu_sensors[2].state = ENVSYS_SINVALID;
    476  1.5       jdc 	tadpmu_sensors[2].units = ENVSYS_INDICATOR;
    477  1.5       jdc 	tadpmu_sensors[2].private = CMD_READ_GENSTAT;
    478  1.5       jdc 	strcpy(tadpmu_sensors[2].desc, "DC power");
    479  1.5       jdc 	sysmon_envsys_sensor_attach(tadpmu_acad_sme, &tadpmu_sensors[2]);
    480  1.5       jdc 
    481  1.5       jdc 	tadpmu_sensors[3].state = ENVSYS_SINVALID;
    482  1.5       jdc 	tadpmu_sensors[3].units = ENVSYS_SVOLTS_DC;
    483  1.5       jdc 	tadpmu_sensors[3].private = CMD_READ_VBATT;
    484  1.5       jdc 	strcpy(tadpmu_sensors[3].desc, "Vbatt");
    485  1.5       jdc 	sysmon_envsys_sensor_attach(tadpmu_batt_sme, &tadpmu_sensors[3]);
    486  1.5       jdc 
    487  1.5       jdc 	tadpmu_sensors[4].state = ENVSYS_SINVALID;
    488  1.5       jdc 	tadpmu_sensors[4].units = ENVSYS_BATTERY_CAPACITY;
    489  1.5       jdc 	tadpmu_sensors[4].private = CMD_READ_GENSTAT;
    490  1.5       jdc 	/* We must provide an initial value for battery capacity */
    491  1.5       jdc 	tadpmu_sensors[4].value_cur = ENVSYS_BATTERY_CAPACITY_NORMAL;
    492  1.5       jdc 	strcpy(tadpmu_sensors[4].desc, "capacity");
    493  1.5       jdc 	sysmon_envsys_sensor_attach(tadpmu_batt_sme, &tadpmu_sensors[4]);
    494  1.5       jdc 
    495  1.5       jdc 	tadpmu_sensors[5].state = ENVSYS_SINVALID;
    496  1.5       jdc 	tadpmu_sensors[5].units = ENVSYS_BATTERY_CHARGE;
    497  1.5       jdc 	tadpmu_sensors[5].private = CMD_READ_GENSTAT;
    498  1.5       jdc 	strcpy(tadpmu_sensors[5].desc, "charging");
    499  1.5       jdc 	sysmon_envsys_sensor_attach(tadpmu_batt_sme, &tadpmu_sensors[5]);
    500  1.5       jdc 
    501  1.1  macallan #ifdef TADPMU_DEBUG
    502  1.5       jdc 	tadpmu_sensors[6].state = ENVSYS_SINVALID;
    503  1.5       jdc 	tadpmu_sensors[6].units = ENVSYS_INTEGER;
    504  1.5       jdc 	tadpmu_sensors[6].private = CMD_READ_GENSTAT;
    505  1.5       jdc 	strcpy(tadpmu_sensors[6].desc, "genstat");
    506  1.5       jdc 	sysmon_envsys_sensor_attach(tadpmu_sens_sme, &tadpmu_sensors[6]);
    507  1.1  macallan #endif
    508  1.5       jdc 
    509  1.5       jdc 	sysmon_envsys_register(tadpmu_sens_sme);
    510  1.5       jdc 	sysmon_envsys_register(tadpmu_acad_sme);
    511  1.5       jdc 	sysmon_envsys_register(tadpmu_batt_sme);
    512  1.1  macallan 
    513  1.2  macallan 	sysmon_task_queue_init();
    514  1.2  macallan 	memset(&tadpmu_pbutton, 0, sizeof(struct sysmon_pswitch));
    515  1.4  macallan 	tadpmu_pbutton.smpsw_name = "power";
    516  1.2  macallan 	tadpmu_pbutton.smpsw_type = PSWITCH_TYPE_POWER;
    517  1.2  macallan 	if (sysmon_pswitch_register(&tadpmu_pbutton) != 0)
    518  1.2  macallan 		aprint_error(
    519  1.2  macallan 		    "unable to register power button with sysmon\n");
    520  1.2  macallan 
    521  1.5       jdc 	memset(&tadpmu_lidswitch, 0, sizeof(struct sysmon_pswitch));
    522  1.4  macallan 	tadpmu_lidswitch.smpsw_name = "lid";
    523  1.4  macallan 	tadpmu_lidswitch.smpsw_type = PSWITCH_TYPE_LID;
    524  1.4  macallan 	if (sysmon_pswitch_register(&tadpmu_lidswitch) != 0)
    525  1.4  macallan 		aprint_error(
    526  1.4  macallan 		    "unable to register lid switch with sysmon\n");
    527  1.4  macallan 
    528  1.5       jdc 	memset(&tadpmu_dcpower, 0, sizeof(struct sysmon_pswitch));
    529  1.5       jdc 	tadpmu_dcpower.smpsw_name = "AC adapter";
    530  1.5       jdc 	tadpmu_dcpower.smpsw_type = PSWITCH_TYPE_ACADAPTER;
    531  1.5       jdc 	if (sysmon_pswitch_register(&tadpmu_dcpower) != 0)
    532  1.5       jdc 		aprint_error(
    533  1.5       jdc 		    "unable to register AC adapter with sysmon\n");
    534  1.5       jdc 
    535  1.4  macallan 	kthread_create(PRI_NONE, 0, curcpu(), tadpmu_events, NULL,
    536  1.4  macallan 	    &tadpmu_thread, "tadpmu_events");
    537  1.4  macallan 
    538  1.1  macallan 	return 0;
    539  1.1  macallan }
    540  1.3  macallan #endif /* HAVE_TADPMU */
    541