diff --git a/distrib/sets/lists/man/mi b/distrib/sets/lists/man/mi index c64eaf0af0c2..17aa54fd6716 100644 --- a/distrib/sets/lists/man/mi +++ b/distrib/sets/lists/man/mi @@ -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 diff --git a/distrib/sets/lists/modules/md.amd64 b/distrib/sets/lists/modules/md.amd64 index e83a375d7749..d80a8b551844 100644 --- a/distrib/sets/lists/modules/md.amd64 +++ b/distrib/sets/lists/modules/md.amd64 @@ -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 diff --git a/distrib/sets/lists/modules/md.i386 b/distrib/sets/lists/modules/md.i386 index 29015ec78cc6..cb08cae6e0b9 100644 --- a/distrib/sets/lists/modules/md.i386 +++ b/distrib/sets/lists/modules/md.i386 @@ -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 diff --git a/doc/CHANGES b/doc/CHANGES index fa6549205bfb..241199165dd0 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -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] diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index cece52f82416..5c9614a1e418 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -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 \ diff --git a/share/man/man4/hpacel.4 b/share/man/man4/hpacel.4 new file mode 100644 index 000000000000..eff52b607d1f --- /dev/null +++ b/share/man/man4/hpacel.4 @@ -0,0 +1,85 @@ +.\" $NetBSD +.\" +.\" Copyright (c) 2011 Jukka Ruohonen +.\" 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 . diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC index 2d07b1c950c7..0107999fc96c 100644 --- a/sys/arch/amd64/conf/GENERIC +++ b/sys/arch/amd64/conf/GENERIC @@ -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) diff --git a/sys/arch/i386/conf/ALL b/sys/arch/i386/conf/ALL index 764c554ee717..84c44c4a0660 100644 --- a/sys/arch/i386/conf/ALL +++ b/sys/arch/i386/conf/ALL @@ -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) diff --git a/sys/arch/i386/conf/GENERIC b/sys/arch/i386/conf/GENERIC index c2eab0c2c037..9f71f309eddb 100644 --- a/sys/arch/i386/conf/GENERIC +++ b/sys/arch/i386/conf/GENERIC @@ -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) diff --git a/sys/dev/acpi/files.acpi b/sys/dev/acpi/files.acpi index f34fd4e717f0..b058503d1092 100644 --- a/sys/dev/acpi/files.acpi +++ b/sys/dev/acpi/files.acpi @@ -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 diff --git a/sys/dev/acpi/hpacel_acpi.c b/sys/dev/acpi/hpacel_acpi.c new file mode 100644 index 000000000000..8d26bbafaf1f --- /dev/null +++ b/sys/dev/acpi/hpacel_acpi.c @@ -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 + * 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 +__KERNEL_RCSID(0, "$NetBSD: hpacel_acpi.c,v 1.1 2011/07/13 07:52:48 jruoho Exp $"); + +#include +#include + +#include +#include +#include + +#include + +#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; +} diff --git a/sys/modules/Makefile b/sys/modules/Makefile index d1728439caf6..650945b64cc2 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -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 @@ -123,6 +123,7 @@ SUBDIR+= aibs SUBDIR+= asus SUBDIR+= fujbp SUBDIR+= fujhk +SUBDIR+= hpacel SUBDIR+= hpqlb SUBDIR+= thinkpad SUBDIR+= wmidell diff --git a/sys/modules/hpacel/Makefile b/sys/modules/hpacel/Makefile new file mode 100644 index 000000000000..f906d706ad87 --- /dev/null +++ b/sys/modules/hpacel/Makefile @@ -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 diff --git a/sys/modules/hpacel/hpacel.ioconf b/sys/modules/hpacel/hpacel.ioconf new file mode 100644 index 000000000000..eca3bc5a3aaf --- /dev/null +++ b/sys/modules/hpacel/hpacel.ioconf @@ -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?