A driver for HP 3D DriverGuard; a LIS3LV02DL-based accelerometer. Tested on

HP NC4400. Like aps(4), this is commented out in the GENERIC kernels.
This commit is contained in:
jruoho 2011-07-13 07:52:48 +00:00
parent 69e4520422
commit b5dc3d4af2
14 changed files with 751 additions and 14 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.1323 2011/07/03 21:59:31 tron Exp $
# $NetBSD: mi,v 1.1324 2011/07/13 07:52:49 jruoho Exp $
#
# Note: don't delete entries from here - mark them as "obsolete" instead.
#
@ -1080,6 +1080,7 @@
./usr/share/man/cat4/hpcsh/j6x0tp.0 man-sys-catman .cat
./usr/share/man/cat4/hpcsh/psh3lcd.0 man-sys-catman .cat
./usr/share/man/cat4/hpcsh/psh3tp.0 man-sys-catman .cat
./usr/share/man/cat4/hpacel.0 man-sys-catman .cat
./usr/share/man/cat4/hpqlb.0 man-sys-catman .cat
./usr/share/man/cat4/hptide.0 man-sys-catman .cat
./usr/share/man/cat4/i386/PCIBIOS.0 man-sys-catman .cat
@ -3865,6 +3866,7 @@
./usr/share/man/html4/hpcsh/j6x0tp.html man-sys-htmlman html
./usr/share/man/html4/hpcsh/psh3lcd.html man-sys-htmlman html
./usr/share/man/html4/hpcsh/psh3tp.html man-sys-htmlman html
./usr/share/man/html4/hpacel.html man-sys-htmlman html
./usr/share/man/html4/hpqlb.html man-sys-htmlman html
./usr/share/man/html4/hptide.html man-sys-htmlman html
./usr/share/man/html4/i386/PCIBIOS.html man-sys-htmlman html
@ -6445,6 +6447,7 @@
./usr/share/man/man4/hpcsh/j6x0tp.4 man-sys-man .man
./usr/share/man/man4/hpcsh/psh3lcd.4 man-sys-man .man
./usr/share/man/man4/hpcsh/psh3tp.4 man-sys-man .man
./usr/share/man/man4/hpacel.4 man-sys-man .man
./usr/share/man/man4/hpqlb.4 man-sys-man .man
./usr/share/man/man4/hptide.4 man-sys-man .man
./usr/share/man/man4/i386/PCIBIOS.4 man-sys-man .man

View File

@ -1,4 +1,4 @@
# $NetBSD: md.amd64,v 1.22 2011/06/15 08:19:43 jruoho Exp $
# $NetBSD: md.amd64,v 1.23 2011/07/13 07:52:49 jruoho Exp $
./@MODULEDIR@/acpiacad base-kernel-modules kmod
./@MODULEDIR@/acpiacad/acpiacad.kmod base-kernel-modules kmod
./@MODULEDIR@/acpibat base-kernel-modules kmod
@ -57,6 +57,8 @@
./@MODULEDIR@/fujbp/fujbp.kmod base-kernel-modules kmod
./@MODULEDIR@/fujhk base-kernel-modules kmod
./@MODULEDIR@/fujhk/fujhk.kmod base-kernel-modules kmod
./@MODULEDIR@/hpacel base-kernel-modules kmod
./@MODULEDIR@/hpacel/hpacel.kmod base-kernel-modules kmod
./@MODULEDIR@/hpet base-kernel-modules kmod
./@MODULEDIR@/hpet/hpet.kmod base-kernel-modules kmod
./@MODULEDIR@/hpqlb base-kernel-modules kmod

View File

@ -1,4 +1,4 @@
# $NetBSD: md.i386,v 1.26 2011/06/15 08:19:43 jruoho Exp $
# $NetBSD: md.i386,v 1.27 2011/07/13 07:52:49 jruoho Exp $
./@MODULEDIR@/acpiacad base-kernel-modules kmod
./@MODULEDIR@/acpiacad/acpiacad.kmod base-kernel-modules kmod
./@MODULEDIR@/acpibat base-kernel-modules kmod
@ -59,6 +59,8 @@
./@MODULEDIR@/fujbp/fujbp.kmod base-kernel-modules kmod
./@MODULEDIR@/fujhk base-kernel-modules kmod
./@MODULEDIR@/fujhk/fujhk.kmod base-kernel-modules kmod
./@MODULEDIR@/hpacel base-kernel-modules kmod
./@MODULEDIR@/hpacel/hpacel.kmod base-kernel-modules kmod
./@MODULEDIR@/hpet base-kernel-modules kmod
./@MODULEDIR@/hpet/hpet.kmod base-kernel-modules kmod
./@MODULEDIR@/hpqlb base-kernel-modules kmod

View File

@ -1,4 +1,4 @@
# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.1576 $>
# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.1577 $>
#
#
# [Note: This file does not mention every change made to the NetBSD source tree.
@ -1061,3 +1061,5 @@ Changes from NetBSD 5.0 to NetBSD 6.0:
for AR71xx (24K) and AR9344 (74K) SoCs.
dtv(4): Add digital TV framework. [jmcneill 20110709]
auvitek(4): Add digital capture support. [jmcneill 20110709]
hpacel(4): Add a driver for HP 3D DriverGuard; a LIS3LV02DL-based
accelerometer. [jruoho 20110713]

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.560 2011/06/22 20:29:38 jruoho Exp $
# $NetBSD: Makefile,v 1.561 2011/07/13 07:52:49 jruoho Exp $
# @(#)Makefile 8.1 (Berkeley) 6/18/93
MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 \
@ -27,7 +27,7 @@ MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 \
fast_ipsec.4 fd.4 finsio.4 flash.4 fpa.4 fms.4 fss.4 fujbp.4 fxp.4 \
gcscaudio.4 gem.4 genfb.4 gentbi.4 geodeide.4 \
glxtphy.4 gpib.4 gpio.4 gpiolock.4 gpiosim.4 gre.4 gphyter.4 gsip.4 \
hdaudio.4 hifn.4 hme.4 hpqlb.4 hptide.4 \
hdaudio.4 hifn.4 hme.4 hpacel.4 hpqlb.4 hptide.4 \
ibmhawk.4 ichsmb.4 icmp.4 icp.4 icsphy.4 iee.4 ieee80211.4 \
ifmedia.4 igphy.4 igsfb.4 iha.4 ihphy.4 iic.4 inet.4 ikphy.4 inphy.4 \
intersil7170.4 \

85
share/man/man4/hpacel.4 Normal file
View File

@ -0,0 +1,85 @@
.\" $NetBSD
.\"
.\" Copyright (c) 2011 Jukka Ruohonen <jruohonen@iki.fi>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Neither the name of the author nor the names of any
.\" contributors may be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd June 23, 2011
.Dt HPACEL 4
.Os
.Sh NAME
.Nm hpacel
.Nd HP 3D DriveGuard accelerometer
.Sh SYNOPSIS
.Cd "hpacel* at acpi?"
.Sh DESCRIPTION
The
.Nm
device driver supports accelerometers that are
commonly available in Hewlett-Packard laptops.
The supported chip is
.Dv LIS3LV02DL
from STMicroelectronics, although other chips from the same family, such as
.Dv LIS3LV02DQ ,
may also work, provided that that the vendor has implemented suitable
.Dv ACPI
access methods.
.Pp
The
.Nm
driver reports the acceleration readings of the X-, Y-, and Z-axis
via the
.Xr envsys 4
.Tn API
and the
.Xr envstat 8
command.
.Sh SEE ALSO
.Xr acpi 4 ,
.Xr aps 4 ,
.Xr hpqlb 4 ,
.Xr wmihp 4
.Rs
.%A STMicroelectronics
.%T "TLIS3LV02DL: 3-Axis - \*(Pm\* 2g/\*(Pm\* 6g digital output \
low voltage linear accelerometer. AN2381 Application Note"
.%N Revision 1
.%D June, 2006
.%U http://www.st.com/stonline/products/literature/anp/12441.pdf
.Re
.Sh HISTORY
The
.Nm
device driver appeared in
.Nx 6.0 .
.Sh AUTHORS
.An Jukka Ruohonen
.Aq jruohonen@iki.fi
.Sh BUGS
The used accelerometer chip is capable of generating wake-up,
direction detection, and free-fall interrupts.
In the ideal situation these could be used to evoke possible emergency action.
However, the
.Nm
driver only reports the readings from the accelerometer via
.Xr sysmon_envsys 9 .

View File

@ -1,4 +1,4 @@
# $NetBSD: GENERIC,v 1.322 2011/07/03 10:40:16 bouyer Exp $
# $NetBSD: GENERIC,v 1.323 2011/07/13 07:52:49 jruoho Exp $
#
# GENERIC machine description file
#
@ -22,7 +22,7 @@ include "arch/amd64/conf/std.amd64"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
#ident "GENERIC-$Revision: 1.322 $"
#ident "GENERIC-$Revision: 1.323 $"
maxusers 64 # estimated number of users
@ -301,6 +301,7 @@ attimer* at acpi? # AT Timer
#fdc* at acpi? # Floppy disk controller
fujbp* at acpi? # Fujitsu Brightness & Pointer
fujhk* at acpi? # Fujitsu Hotkeys
#hpacel* at acpi? # HP 3D DriveGuard accelerometer
#hpqlb* at acpi? # HP Quick Launch Buttons
hpet* at acpihpetbus? # High Precision Event Timer (table)
hpet* at acpinodebus? # High Precision Event Timer (device)

View File

@ -1,4 +1,4 @@
# $NetBSD: ALL,v 1.310 2011/07/11 18:31:10 jmcneill Exp $
# $NetBSD: ALL,v 1.311 2011/07/13 07:52:48 jruoho Exp $
# From NetBSD: GENERIC,v 1.787 2006/10/01 18:37:54 bouyer Exp
#
# ALL machine description file
@ -17,7 +17,7 @@ include "arch/i386/conf/std.i386"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
#ident "ALL-$Revision: 1.310 $"
#ident "ALL-$Revision: 1.311 $"
maxusers 64 # estimated number of users
@ -376,6 +376,7 @@ com* at acpi? # Serial communications interface
fdc* at acpi? # Floppy disk controller
fujbp* at acpi? # Fujitsu Brightness & Pointer
fujhk* at acpi? # Fujitsu Hotkeys
hpacel* at acpi? # HP 3D DriveGuard accelerometer
hpqlb* at acpi? # HP Quick Launch Buttons
hpet* at acpihpetbus? # High Precision Event Timer (table)
hpet* at acpinodebus? # High Precision Event Timer (device)

View File

@ -1,4 +1,4 @@
# $NetBSD: GENERIC,v 1.1037 2011/07/11 18:31:10 jmcneill Exp $
# $NetBSD: GENERIC,v 1.1038 2011/07/13 07:52:48 jruoho Exp $
#
# GENERIC machine description file
#
@ -22,7 +22,7 @@ include "arch/i386/conf/std.i386"
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
#ident "GENERIC-$Revision: 1.1037 $"
#ident "GENERIC-$Revision: 1.1038 $"
maxusers 64 # estimated number of users
@ -366,6 +366,7 @@ attimer* at acpi? # AT Timer
#fdc* at acpi? # Floppy disk controller
fujbp* at acpi? # Fujitsu Brightness & Pointer
fujhk* at acpi? # Fujitsu Hotkeys
#hpacel* at acpi? # HP 3D DriveGuard accelerometer
#hpqlb* at acpi? # HP Quick Launch Buttons
hpet* at acpihpetbus? # High Precision Event Timer (table)
hpet* at acpinodebus? # High Precision Event Timer (device)

View File

@ -1,4 +1,4 @@
# $NetBSD: files.acpi,v 1.90 2011/06/14 13:59:23 jruoho Exp $
# $NetBSD: files.acpi,v 1.91 2011/07/13 07:52:48 jruoho Exp $
include "dev/acpi/acpica/files.acpica"
@ -144,6 +144,11 @@ file dev/acpi/asus_acpi.c asus
attach ug at acpinodebus with ug_acpi
file dev/acpi/ug_acpi.c ug_acpi
# HP 3D DriveGuard accelerometer
device hpacel: sysmon_envsys
attach hpacel at acpinodebus
file dev/acpi/hpacel_acpi.c hpacel
# HP Quick Launch Buttons
device hpqlb: sysmon_power
attach hpqlb at acpinodebus

611
sys/dev/acpi/hpacel_acpi.c Normal file
View File

@ -0,0 +1,611 @@
/* $NetBSD: hpacel_acpi.c,v 1.1 2011/07/13 07:52:48 jruoho Exp $ */
/*-
* Copyright (c) 2009, 2011 Jukka Ruohonen <jruohonen@iki.fi>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: hpacel_acpi.c,v 1.1 2011/07/13 07:52:48 jruoho Exp $");
#include <sys/param.h>
#include <sys/module.h>
#include <dev/acpi/acpireg.h>
#include <dev/acpi/acpivar.h>
#include <dev/acpi/acpi_power.h>
#include <dev/sysmon/sysmonvar.h>
#define _COMPONENT ACPI_RESOURCE_COMPONENT
ACPI_MODULE_NAME ("hpacel_acpi")
/*
* An ACPI driver for Hewlett-Packard 3D DriveGuard accelerometer.
*
* The supported chipset is LIS3LV02DL from STMicroelectronics:
*
* http://www.st.com/stonline/products/literature/anp/12441.pdf
*
* (Obtained on Sat Apr 25 00:32:04 EEST 2009.)
*
* The chip is a three axes digital output linear accelerometer
* that is controllable through I2C / SPI serial interface. This
* implementation however supports only indirect connection through
* ACPI. Other chips from the same family, such as LIS3LV02DQ, may
* also work with the driver, provided that there is a suitable DSDT.
*
* The chip can generate wake-up, direction detection and free-fall
* interrupts. The latter could be used to evoke emergency action.
* None of this is however supported. Only sysmon_envsys(9) is used.
*/
enum {
HPACEL_SENSOR_X = 0,
HPACEL_SENSOR_Y,
HPACEL_SENSOR_Z,
HPACEL_SENSOR_COUNT
};
#define LIS3LV02DL_ID 0x3A
enum lis3lv02dl_reg {
WHO_AM_I = 0x0F, /* r */
OFFSET_X = 0x16, /* rw */
OFFSET_Y = 0x17, /* rw */
OFFSET_Z = 0x18, /* rw */
GAIN_X = 0x19, /* rw */
GAIN_Y = 0x1A, /* rw */
GAIN_Z = 0x1B, /* rw */
CTRL_REG1 = 0x20, /* rw */
CTRL_REG2 = 0x21, /* rw */
CTRL_REG3 = 0x22, /* rw */
HP_FILTER_RESET = 0x23, /* r */
STATUS_REG = 0x27, /* rw */
OUTX_L = 0x28, /* r */
OUTX_H = 0x29, /* r */
OUTY_L = 0x2A, /* r */
OUTY_H = 0x2B, /* r */
OUTZ_L = 0x2C, /* r */
OUTZ_H = 0x2D, /* r */
FF_WU_CFG = 0x30, /* r */
FF_WU_SRC = 0x31, /* rw */
FF_WU_ACK = 0x32, /* r */
FF_WU_THS_L = 0x34, /* rw */
FF_WU_THS_H = 0x35, /* rw */
FF_WU_DURATION = 0x36, /* rw */
DD_CFG = 0x38, /* rw */
DD_SRC = 0x39, /* rw */
DD_ACK = 0x3A, /* r */
DD_THSI_L = 0x3C, /* rw */
DD_THSI_H = 0x3D, /* rw */
DD_THSE_L = 0x3E, /* rw */
DD_THSE_H = 0x3F /* rw */
};
enum lis3lv02dl_ctrl1 {
CTRL1_Xen = (1 << 0), /* X-axis enable */
CTRL1_Yen = (1 << 1), /* Y-axis enable */
CTRL1_Zen = (1 << 2), /* Z-axis enable */
CTRL1_ST = (1 << 3), /* Self test enable */
CTRL1_DF0 = (1 << 4), /* Decimation factor control */
CTRL1_DF1 = (1 << 5), /* Decimation factor control */
CTRL1_PD0 = (1 << 6), /* Power down control */
CTRL1_PD1 = (1 << 7) /* Power down control */
};
enum lis3lv02dl_ctrl2 {
CTRL2_DAS = (1 << 0), /* Data alignment selection */
CTRL2_SIM = (1 << 1), /* SPI serial interface mode */
CTRL2_DRDY = (1 << 2), /* Enable data-ready generation */
CTRL2_IEN = (1 << 3), /* Enable interrupt mode */
CTRL2_BOOT = (1 << 4), /* Reboot memory contents */
CTRL2_BLE = (1 << 5), /* Endian mode */
CTRL2_BDU = (1 << 6), /* Block data update */
CTRL2_FS = (1 << 7) /* Full scale selection */
};
enum lis3lv02dl_ctrl3 {
CTRL3_CFS0 = (1 << 0), /* High-pass filter cut-off frequency */
CTRL3_CFS1 = (1 << 1), /* High-pass filter cut-off frequency */
CTRL3_FDS = (1 << 4), /* Filtered data selection */
CTRL3_HPFF = (1 << 5), /* High pass filter for free-fall */
CTRL3_HPDD = (1 << 6), /* High pass filter for DD */
CTRL3_ECK = (1 << 7) /* External clock */
};
struct hpacel_softc {
device_t sc_dev;
struct acpi_devnode *sc_node;
struct sysmon_envsys *sc_sme;
bool sc_state;
uint8_t sc_whoami;
uint8_t sc_ctrl[3];
envsys_data_t sc_sensor[HPACEL_SENSOR_COUNT];
};
const char * const hpacel_ids[] = {
"HPQ0004",
NULL
};
static int hpacel_match(device_t, cfdata_t, void *);
static void hpacel_attach(device_t, device_t, void *);
static int hpacel_detach(device_t, int);
static bool hpacel_reg_init(device_t);
static bool hpacel_suspend(device_t, const pmf_qual_t *);
static bool hpacel_resume(device_t, const pmf_qual_t *);
static ACPI_STATUS hpacel_reg_info(device_t);
static ACPI_STATUS hpacel_reg_read(ACPI_HANDLE, ACPI_INTEGER, uint8_t *);
static ACPI_STATUS hpacel_reg_write(ACPI_HANDLE, ACPI_INTEGER, uint8_t);
static ACPI_STATUS hpacel_reg_xyz(ACPI_HANDLE, const int, int16_t *);
static ACPI_STATUS hpacel_power(device_t, bool);
static bool hpacel_sensor_init(device_t);
static void hpacel_sensor_refresh(struct sysmon_envsys *,
envsys_data_t *);
CFATTACH_DECL_NEW(hpacel, sizeof(struct hpacel_softc),
hpacel_match, hpacel_attach, hpacel_detach, NULL);
static int
hpacel_match(device_t parent, cfdata_t match, void *aux)
{
struct acpi_attach_args *aa = aux;
if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
return 0;
return acpi_match_hid(aa->aa_node->ad_devinfo, hpacel_ids);
}
static void
hpacel_attach(device_t parent, device_t self, void *aux)
{
struct hpacel_softc *sc = device_private(self);
struct acpi_attach_args *aa = aux;
sc->sc_sme = NULL;
sc->sc_dev = self;
sc->sc_state = false;
sc->sc_node = aa->aa_node;
aprint_naive("\n");
aprint_normal(": HP 3D DriveGuard accelerometer (rev. 0x%02x)\n",
sc->sc_whoami);
if (hpacel_reg_init(self) != true)
return;
(void)pmf_device_register(self, hpacel_suspend, hpacel_resume);
if (hpacel_sensor_init(self) != false)
(void)hpacel_power(self, true);
sc->sc_state = true;
}
static int
hpacel_detach(device_t self, int flags)
{
struct hpacel_softc *sc = device_private(self);
if (sc->sc_state != false)
(void)hpacel_power(self, false);
if (sc->sc_sme != NULL)
sysmon_envsys_unregister(sc->sc_sme);
return 0;
}
static bool
hpacel_suspend(device_t self, const pmf_qual_t *qual)
{
struct hpacel_softc *sc = device_private(self);
if (sc->sc_state != false)
(void)hpacel_power(self, false);
return true;
}
static bool
hpacel_resume(device_t self, const pmf_qual_t *qual)
{
struct hpacel_softc *sc = device_private(self);
if (sc->sc_state != false)
(void)hpacel_power(self, true);
return true;
}
static bool
hpacel_reg_init(device_t self)
{
struct hpacel_softc *sc = device_private(self);
ACPI_HANDLE hdl = sc->sc_node->ad_handle;
ACPI_STATUS rv;
uint8_t val;
rv = AcpiEvaluateObject(hdl, "_INI", NULL, NULL);
if (ACPI_FAILURE(rv))
goto out;
/*
* Since the "_INI" is practically
* a black box, it is better to verify
* the control registers manually.
*/
rv = hpacel_reg_info(self);
if (ACPI_FAILURE(rv))
goto out;
val = sc->sc_ctrl[0];
if ((sc->sc_ctrl[0] & CTRL1_Xen) == 0)
val |= CTRL1_Xen;
if ((sc->sc_ctrl[0] & CTRL1_Yen) == 0)
val |= CTRL1_Yen;
if ((sc->sc_ctrl[0] & CTRL1_Zen) == 0)
val |= CTRL1_Zen;
if (val != sc->sc_ctrl[0]) {
rv = hpacel_reg_write(hdl, CTRL_REG1, val);
if (ACPI_FAILURE(rv))
return rv;
}
val = sc->sc_ctrl[1];
if ((sc->sc_ctrl[1] & CTRL2_BDU) == 0)
val |= CTRL2_BDU;
if ((sc->sc_ctrl[1] & CTRL2_BLE) != 0)
val &= ~CTRL2_BLE;
if ((sc->sc_ctrl[1] & CTRL2_DAS) != 0)
val &= ~CTRL2_DAS;
/*
* Given the use of sysmon_envsys(9),
* there is no need for the data-ready pin.
*/
if ((sc->sc_ctrl[1] & CTRL2_DRDY) != 0)
val &= ~CTRL2_DRDY;
/*
* Disable interrupt mode.
*/
if ((sc->sc_ctrl[1] & CTRL2_IEN) != 0)
val &= ~CTRL2_IEN;
if (val != sc->sc_ctrl[1]) {
rv = hpacel_reg_write(hdl, CTRL_REG2, val);
if (ACPI_FAILURE(rv))
return rv;
}
/*
* Clear possible interrupt setups from
* the direction-detection register and
* from the free-fall-wake-up register.
*/
(void)hpacel_reg_write(hdl, DD_CFG, 0x00);
(void)hpacel_reg_write(hdl, FF_WU_CFG, 0x00);
/*
* Update the register information.
*/
(void)hpacel_reg_info(hdl);
out:
if (ACPI_FAILURE(rv))
aprint_error_dev(self, "failed to initialize "
"device: %s\n", AcpiFormatException(rv));
return (rv != AE_OK) ? false : true;
}
static ACPI_STATUS
hpacel_reg_info(device_t self)
{
struct hpacel_softc *sc = device_private(self);
ACPI_HANDLE hdl = sc->sc_node->ad_handle;
ACPI_STATUS rv;
size_t i;
rv = hpacel_reg_read(hdl, WHO_AM_I, &sc->sc_whoami);
if (ACPI_FAILURE(rv))
return rv;
for (i = 0; i < __arraycount(sc->sc_sensor); i++) {
rv = hpacel_reg_read(hdl, CTRL_REG1 + i, &sc->sc_ctrl[i]);
if (ACPI_FAILURE(rv))
return rv;
}
return AE_OK;
}
static ACPI_STATUS
hpacel_reg_read(ACPI_HANDLE hdl, ACPI_INTEGER reg, uint8_t *valp)
{
ACPI_OBJECT_LIST arg;
ACPI_OBJECT obj, val;
ACPI_BUFFER buf;
ACPI_STATUS rv;
obj.Type = ACPI_TYPE_INTEGER;
obj.Integer.Value = reg;
buf.Pointer = &val;
buf.Length = sizeof(val);
arg.Count = 1;
arg.Pointer = &obj;
rv = AcpiEvaluateObjectTyped(hdl, "ALRD",
&arg, &buf, ACPI_TYPE_INTEGER);
if (ACPI_FAILURE(rv))
return rv;
if (val.Integer.Value > UINT8_MAX)
return AE_AML_NUMERIC_OVERFLOW;
*valp = val.Integer.Value;
return AE_OK;
}
static ACPI_STATUS
hpacel_reg_write(ACPI_HANDLE hdl, ACPI_INTEGER reg, uint8_t val)
{
ACPI_OBJECT_LIST arg;
ACPI_OBJECT obj[2];
obj[0].Type = obj[1].Type = ACPI_TYPE_INTEGER;
obj[0].Integer.Value = reg;
obj[1].Integer.Value = val;
arg.Count = 2;
arg.Pointer = obj;
return AcpiEvaluateObject(hdl, "ALWR", &arg, NULL);
}
static ACPI_STATUS
hpacel_reg_xyz(ACPI_HANDLE hdl, const int xyz, int16_t *out)
{
ACPI_INTEGER reg[2];
ACPI_STATUS rv[2];
uint8_t hi, lo;
switch (xyz) {
case HPACEL_SENSOR_X:
reg[0] = OUTX_L;
reg[1] = OUTX_H;
break;
case HPACEL_SENSOR_Y:
reg[0] = OUTY_L;
reg[1] = OUTY_H;
break;
case HPACEL_SENSOR_Z:
reg[0] = OUTZ_L;
reg[1] = OUTZ_H;
break;
default:
return AE_BAD_PARAMETER;
}
rv[0] = hpacel_reg_read(hdl, reg[0], &lo);
rv[1] = hpacel_reg_read(hdl, reg[1], &hi);
if (ACPI_FAILURE(rv[0]) || ACPI_FAILURE(rv[1]))
return AE_ERROR;
/*
* These registers are read in "12 bit right
* justified mode", meaning that the four
* most significant bits are replaced with
* the value of bit 12. Note the signed type.
*/
hi = (hi & 0x10) ? hi | 0xE0 : hi & ~0xE0;
*out = (hi << 8) | lo;
return AE_OK;
}
static ACPI_STATUS
hpacel_power(device_t self, bool enable)
{
struct hpacel_softc *sc = device_private(self);
ACPI_HANDLE hdl = sc->sc_node->ad_handle;
ACPI_OBJECT_LIST arg;
ACPI_OBJECT obj;
ACPI_STATUS rv;
uint8_t val;
rv = hpacel_reg_info(self);
if (ACPI_FAILURE(rv))
return rv;
val = sc->sc_ctrl[0];
if (enable != false)
val |= CTRL1_PD0 | CTRL1_PD1;
else {
val &= ~(CTRL1_PD0 | CTRL1_PD1);
}
if (val != sc->sc_ctrl[0]) {
rv = hpacel_reg_write(hdl, CTRL_REG1, val);
if (ACPI_FAILURE(rv))
return rv;
}
obj.Type = ACPI_TYPE_INTEGER;
obj.Integer.Value = enable;
arg.Count = 1;
arg.Pointer = &obj;
/*
* This should turn on/off a led, if available.
*/
(void)AcpiEvaluateObject(hdl, "ALED", &arg, NULL);
return rv;
}
static bool
hpacel_sensor_init(device_t self)
{
const char zyx[HPACEL_SENSOR_COUNT] = { 'x', 'y', 'z' };
struct hpacel_softc *sc = device_private(self);
size_t i;
int rv;
CTASSERT(HPACEL_SENSOR_X == 0);
CTASSERT(HPACEL_SENSOR_Y == 1);
CTASSERT(HPACEL_SENSOR_Z == 2);
sc->sc_sme = sysmon_envsys_create();
for (i = 0; i < __arraycount(sc->sc_sensor); i++) {
sc->sc_sensor[i].units = ENVSYS_INTEGER;
sc->sc_sensor[i].state = ENVSYS_SINVALID;
(void)snprintf(sc->sc_sensor[i].desc,
ENVSYS_DESCLEN, "%c-acceleration", zyx[i]);
rv = sysmon_envsys_sensor_attach(sc->sc_sme,&sc->sc_sensor[i]);
if (rv != 0)
goto fail;
}
/*
* We only do polling, given the hopelessly
* slow way of reading registers with ACPI.
*/
sc->sc_sme->sme_cookie = sc;
sc->sc_sme->sme_flags = SME_POLL_ONLY;
sc->sc_sme->sme_name = device_xname(self);
sc->sc_sme->sme_refresh = hpacel_sensor_refresh;
rv = sysmon_envsys_register(sc->sc_sme);
if (rv != 0)
goto fail;
return true;
fail:
aprint_error_dev(self, "failed to initialize sensors\n");
sysmon_envsys_destroy(sc->sc_sme);
sc->sc_sme = NULL;
return false;
}
static void
hpacel_sensor_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
{
struct hpacel_softc *sc = sme->sme_cookie;
ACPI_STATUS rv;
int16_t val;
size_t i;
for (i = 0; i < __arraycount(sc->sc_sensor); i++) {
rv = hpacel_reg_xyz(sc->sc_node->ad_handle, i, &val);
if (ACPI_SUCCESS(rv)) {
sc->sc_sensor[i].value_cur = val;
sc->sc_sensor[i].state = ENVSYS_SVALID;
continue;
}
sc->sc_sensor[i].state = ENVSYS_SINVALID;
}
}
MODULE(MODULE_CLASS_DRIVER, hpacel, NULL);
#ifdef _MODULE
#include "ioconf.c"
#endif
static int
hpacel_modcmd(modcmd_t cmd, void *aux)
{
int rv = 0;
switch (cmd) {
case MODULE_CMD_INIT:
#ifdef _MODULE
rv = config_init_component(cfdriver_ioconf_hpacel,
cfattach_ioconf_hpacel, cfdata_ioconf_hpacel);
#endif
break;
case MODULE_CMD_FINI:
#ifdef _MODULE
rv = config_fini_component(cfdriver_ioconf_hpacel,
cfattach_ioconf_hpacel, cfdata_ioconf_hpacel);
#endif
break;
default:
rv = ENOTTY;
}
return rv;
}

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.74 2011/07/09 14:56:43 jmcneill Exp $
# $NetBSD: Makefile,v 1.75 2011/07/13 07:52:49 jruoho Exp $
.include <bsd.own.mk>
@ -123,6 +123,7 @@ SUBDIR+= aibs
SUBDIR+= asus
SUBDIR+= fujbp
SUBDIR+= fujhk
SUBDIR+= hpacel
SUBDIR+= hpqlb
SUBDIR+= thinkpad
SUBDIR+= wmidell

View File

@ -0,0 +1,13 @@
# $NetBSD: Makefile,v 1.1 2011/07/13 07:52:49 jruoho Exp $
.include "../Makefile.inc"
.PATH: ${S}/dev/acpi
KMOD= hpacel
IOCONF= hpacel.ioconf
SRCS= hpacel_acpi.c
WARNS= 4
.include <bsd.kmodule.mk>

View File

@ -0,0 +1,10 @@
# $NetBSD: hpacel.ioconf,v 1.1 2011/07/13 07:52:49 jruoho Exp $
ioconf hpacel
include "conf/files"
include "dev/acpi/files.acpi"
pseudo-root acpi*
hpacel* at acpi?