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