Module Name: src Committed By: isaki Date: Sun Nov 27 09:00:33 UTC 2011
Modified Files: src/distrib/sets/lists/man: mi src/share/man/man4/man4.x68k: Makefile src/sys/arch/x68k/conf: GENERIC files.x68k Added Files: src/share/man/man4/man4.x68k: powsw.4 src/sys/arch/x68k/dev: powsw.c Log Message: Add powsw(4) for x68k power switch. It substitutes for a part about power switch handler of pow(4) deleted before. Benefits than pow(4): - separate a front switch (= powsw0) and an EXPWON line (= powsw1) completely. Only powsw0 is enabled in GENERIC by default. - prevent chattering in some hardware individuals. thank you for a report and a test: Yasushi Oshima and Y.Sugahara. To generate a diff of this commit: cvs rdiff -u -r1.1358 -r1.1359 src/distrib/sets/lists/man/mi cvs rdiff -u -r1.8 -r1.9 src/share/man/man4/man4.x68k/Makefile cvs rdiff -u -r0 -r1.1 src/share/man/man4/man4.x68k/powsw.4 cvs rdiff -u -r1.157 -r1.158 src/sys/arch/x68k/conf/GENERIC cvs rdiff -u -r1.76 -r1.77 src/sys/arch/x68k/conf/files.x68k cvs rdiff -u -r0 -r1.1 src/sys/arch/x68k/dev/powsw.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/man/mi diff -u src/distrib/sets/lists/man/mi:1.1358 src/distrib/sets/lists/man/mi:1.1359 --- src/distrib/sets/lists/man/mi:1.1358 Sat Nov 26 15:39:49 2011 +++ src/distrib/sets/lists/man/mi Sun Nov 27 09:00:32 2011 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1358 2011/11/26 15:39:49 tsutsui Exp $ +# $NetBSD: mi,v 1.1359 2011/11/27 09:00:32 isaki Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -1826,6 +1826,7 @@ ./usr/share/man/cat4/x68k/mfp.0 man-sys-catman .cat ./usr/share/man/cat4/x68k/neptune.0 man-sys-catman .cat ./usr/share/man/cat4/x68k/pow.0 man-obsolete obsolete +./usr/share/man/cat4/x68k/powsw.0 man-sys-catman .cat ./usr/share/man/cat4/x68k/vs.0 man-sys-catman .cat ./usr/share/man/cat4/x86/amdpcib.0 man-sys-catman .cat ./usr/share/man/cat4/x86/apic.0 man-sys-catman .cat @@ -4592,6 +4593,7 @@ ./usr/share/man/html4/x68k/mfp.html man-sys-htmlman html ./usr/share/man/html4/x68k/neptune.html man-sys-htmlman html ./usr/share/man/html4/x68k/pow.html man-obsolete obsolete +./usr/share/man/html4/x68k/powsw.html man-sys-htmlman html ./usr/share/man/html4/x68k/vs.html man-sys-htmlman html ./usr/share/man/html4/x86/amdpcib.html man-sys-htmlman html ./usr/share/man/html4/x86/apic.html man-sys-htmlman html @@ -7293,6 +7295,7 @@ ./usr/share/man/man4/x68k/mfp.4 man-sys-man .man ./usr/share/man/man4/x68k/neptune.4 man-sys-man .man ./usr/share/man/man4/x68k/pow.4 man-obsolete obsolete +./usr/share/man/man4/x68k/powsw.4 man-sys-man .man ./usr/share/man/man4/x68k/vs.4 man-sys-man .man ./usr/share/man/man4/x86/amdpcib.4 man-sys-man .man ./usr/share/man/man4/x86/apic.4 man-sys-man .man Index: src/share/man/man4/man4.x68k/Makefile diff -u src/share/man/man4/man4.x68k/Makefile:1.8 src/share/man/man4/man4.x68k/Makefile:1.9 --- src/share/man/man4/man4.x68k/Makefile:1.8 Sat Nov 19 12:27:43 2011 +++ src/share/man/man4/man4.x68k/Makefile Sun Nov 27 09:00:33 2011 @@ -1,6 +1,6 @@ -# $NetBSD: Makefile,v 1.8 2011/11/19 12:27:43 isaki Exp $ +# $NetBSD: Makefile,v 1.9 2011/11/27 09:00:33 isaki Exp $ -MAN= bmd.4 intio.4 intro.4 mfp.4 neptune.4 vs.4 +MAN= bmd.4 intio.4 intro.4 mfp.4 neptune.4 powsw.4 vs.4 MANSUBDIR=/x68k .include <bsd.man.mk> Index: src/sys/arch/x68k/conf/GENERIC diff -u src/sys/arch/x68k/conf/GENERIC:1.157 src/sys/arch/x68k/conf/GENERIC:1.158 --- src/sys/arch/x68k/conf/GENERIC:1.157 Tue Nov 22 21:25:41 2011 +++ src/sys/arch/x68k/conf/GENERIC Sun Nov 27 09:00:32 2011 @@ -1,4 +1,4 @@ -# $NetBSD: GENERIC,v 1.157 2011/11/22 21:25:41 tls Exp $ +# $NetBSD: GENERIC,v 1.158 2011/11/27 09:00:32 isaki Exp $ # # GENERIC machine description file # @@ -22,7 +22,7 @@ include "arch/x68k/conf/std.x68k" options INCLUDE_CONFIG_FILE # embed config file in kernel binary -#ident "GENERIC-$Revision: 1.157 $" +#ident "GENERIC-$Revision: 1.158 $" maxusers 8 @@ -288,6 +288,9 @@ par0 at intio0 addr 0xe8c000 # Builtin sram0 at intio0 addr 0xed0000 # battery-backuped static RAM pseudo-device bell # OPM bell +powsw0 at mfp0 # Front switch +#powsw1 at mfp0 # External power switch + xcom0 at mainbus0 # NS16550 fast serial xcom1 at mainbus0 Index: src/sys/arch/x68k/conf/files.x68k diff -u src/sys/arch/x68k/conf/files.x68k:1.76 src/sys/arch/x68k/conf/files.x68k:1.77 --- src/sys/arch/x68k/conf/files.x68k:1.76 Sat Nov 19 12:27:43 2011 +++ src/sys/arch/x68k/conf/files.x68k Sun Nov 27 09:00:32 2011 @@ -1,4 +1,4 @@ -# $NetBSD: files.x68k,v 1.76 2011/11/19 12:27:43 isaki Exp $ +# $NetBSD: files.x68k,v 1.77 2011/11/27 09:00:32 isaki Exp $ # # new style config file for x68k architecture # @@ -96,6 +96,10 @@ device kbd: event attach kbd at mfp file arch/x68k/dev/kbd.c kbd needs-flag +device powsw: sysmon_power, sysmon_taskq +attach powsw at mfp +file arch/x68k/dev/powsw.c powsw + device rtc attach rtc at intio file arch/x68k/dev/rtclock.c rtc Added files: Index: src/share/man/man4/man4.x68k/powsw.4 diff -u /dev/null src/share/man/man4/man4.x68k/powsw.4:1.1 --- /dev/null Sun Nov 27 09:00:33 2011 +++ src/share/man/man4/man4.x68k/powsw.4 Sun Nov 27 09:00:33 2011 @@ -0,0 +1,55 @@ +.\" $NetBSD: powsw.4,v 1.1 2011/11/27 09:00:33 isaki Exp $ +.\" +.\" Copyright (c) 2011 Tetsuya Isaki. 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 ``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 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 November 27, 2011 +.Dt POWSW 4 x68k +.Os +.Sh NAME +.Nm powsw +.Nd x68k power switch handler +.Sh SYNOPSIS +.Cd powsw0 at mfp0 +.Cd powsw1 at mfp0 +.Sh DESCRIPTION +The +.Nm +driver monitors x68k's power switch, +and is made as interface to +.Xr sysmon_pswitch 9 . +.Pp +.Nm powsw0 +monitors a front switch. +.Nm powsw1 +monitors an external power switch (EXPWON signal in I/O slot). +.Sh SEE ALSO +.Xr powerd 8 +.Sh HISTORY +.Nm +appeared in +.Nx 6.0 . +.Sh BUGS +I have no idea for +.Nm powsw2 +(rtc alarm). Index: src/sys/arch/x68k/dev/powsw.c diff -u /dev/null src/sys/arch/x68k/dev/powsw.c:1.1 --- /dev/null Sun Nov 27 09:00:33 2011 +++ src/sys/arch/x68k/dev/powsw.c Sun Nov 27 09:00:32 2011 @@ -0,0 +1,290 @@ +/* $NetBSD: powsw.c,v 1.1 2011/11/27 09:00:32 isaki Exp $ */ + +/* + * Copyright (c) 2011 Tetsuya Isaki. 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 ``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 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. + */ + +/* + * Power switch monitor + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: powsw.c,v 1.1 2011/11/27 09:00:32 isaki Exp $"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/device.h> +#include <sys/intr.h> +#include <sys/callout.h> + +#include <machine/bus.h> +#include <machine/cpu.h> + +#include <arch/x68k/dev/intiovar.h> +#include <arch/x68k/dev/mfp.h> + +#include <dev/sysmon/sysmonvar.h> +#include <dev/sysmon/sysmon_taskq.h> + +extern int power_switch_is_off; /* XXX should be in .h */ + +//#define POWSW_DEBUG + +#if defined(POWSW_DEBUG) +#define DPRINTF(fmt...) printf(fmt) +#define DEBUG_LOG_ADD(c) sc->sc_log[sc->sc_loglen++] = (c) +#define DEBUG_LOG_PRINT() do { \ + sc->sc_log[sc->sc_loglen] = '\0'; \ + printf("%s", sc->sc_log); \ +} while (0) +#else +#define DPRINTF(fmt...) +#define DEBUG_LOG_ADD(c) +#define DEBUG_LOG_PRINT() +#endif + +/* mask */ +#define POWSW_ALARM (0x01) +#define POWSW_EXTERNAL (0x02) +#define POWSW_FRONT (0x04) + +/* parameter */ +#define POWSW_MAX_TICK (30) +#define POWSW_THRESHOLD (10) + +struct powsw_softc { + device_t sc_dev; + struct sysmon_pswitch sc_smpsw; + callout_t sc_callout; + int sc_mask; + int sc_prev; + int sc_last_sw; + int sc_tick; + int sc_count; +#if defined(POWSW_DEBUG) + char sc_log[100]; + int sc_loglen; +#endif +}; + +extern struct cfdriver powsw_cd; + +static int powsw_match(device_t, cfdata_t, void *); +static void powsw_attach(device_t, device_t, void *); +static int powsw_intr(void *); +static void powsw_softintr(void *); +static void powsw_pswitch_event(void *); +static void powsw_shutdown_check(void *); +static void powsw_reset_counter(struct powsw_softc *); +static void powsw_set_aer(struct powsw_softc *, int); + +CFATTACH_DECL_NEW(powsw, sizeof(struct powsw_softc), + powsw_match, powsw_attach, NULL, NULL); + + +typedef const struct { + int vector; /* interrupt vector */ + int mask; /* mask bit for MFP GPIP */ + const char *name; +} powsw_desc_t; + +static powsw_desc_t powsw_desc[2] = { + { 66, POWSW_FRONT, "Front Switch", }, + { 65, POWSW_EXTERNAL, "External Power Switch", }, + /* XXX I'm not sure about alarm bit */ +}; + + +static int +powsw_match(device_t parent, cfdata_t cf, void *aux) +{ + return 1; +} + +static void +powsw_attach(device_t parent, device_t self, void *aux) +{ + struct powsw_softc *sc = device_private(self); + powsw_desc_t *desc; + const char *xname; + int unit; + int sw; + + unit = device_unit(self); + xname = device_xname(self); + desc = &powsw_desc[unit]; + + memset(sc, 0, sizeof(*sc)); + sc->sc_dev = self; + sc->sc_mask = desc->mask; + sc->sc_prev = -1; + powsw_reset_counter(sc); + + sysmon_task_queue_init(); + sc->sc_smpsw.smpsw_name = xname; + sc->sc_smpsw.smpsw_type = PSWITCH_TYPE_POWER; + if (sysmon_pswitch_register(&sc->sc_smpsw) != 0) + panic("can't register with sysmon"); + + callout_init(&sc->sc_callout, 0); + callout_setfunc(&sc->sc_callout, powsw_softintr, sc); + + if (shutdownhook_establish(powsw_shutdown_check, sc) == NULL) + panic("%s: can't establish shutdown hook", xname); + + if (intio_intr_establish(desc->vector, xname, powsw_intr, sc) < 0) + panic("%s: can't establish interrupt", xname); + + /* Set AER and enable interrupt */ + sw = (mfp_get_gpip() & sc->sc_mask); + powsw_set_aer(sc, sw ? 0 : 1); + mfp_bit_set_ierb(sc->sc_mask); + + aprint_normal(": %s\n", desc->name); +} + +static int +powsw_intr(void *arg) +{ + struct powsw_softc *sc = arg; + + if (sc->sc_tick == 0) { + mfp_bit_clear_ierb(sc->sc_mask); + sc->sc_tick++; + DEBUG_LOG_ADD('i'); + /* + * The button state seems unstable for few ticks, + * so wait a bit to settle. + */ + callout_schedule(&sc->sc_callout, 1); + } else { + DEBUG_LOG_ADD('x'); + } + return 0; +} + +void +powsw_softintr(void *arg) +{ + struct powsw_softc *sc = arg; + int sw; + int s; + + s = spl6(); + + if (sc->sc_tick++ >= POWSW_MAX_TICK) { + /* tick is over, broken switch? */ + printf("%s: unstable power switch?, ignored\n", + device_xname(sc->sc_dev)); + powsw_reset_counter(sc); + + mfp_bit_set_ierb(sc->sc_mask); + splx(s); + return; + } + + sw = (mfp_get_gpip() & sc->sc_mask) ? 1 : 0; + DEBUG_LOG_ADD('0' + sw); + + if (sw == sc->sc_last_sw) { + sc->sc_count++; + } else { + sc->sc_last_sw = sw; + sc->sc_count = 1; + } + + if (sc->sc_count < POWSW_THRESHOLD) { + callout_schedule(&sc->sc_callout, 1); + } else { + /* switch seems stable */ + DEBUG_LOG_PRINT(); + + if (sc->sc_last_sw == sc->sc_prev) { + /* switch state is not changed, it was a noise */ + DPRINTF(" ignore(sw=%d,prev=%d)\n", sc->sc_last_sw, sc->sc_prev); + } else { + /* switch state has been changed */ + sc->sc_prev = sc->sc_last_sw; + powsw_set_aer(sc, 1 - sc->sc_prev); + sysmon_task_queue_sched(0, powsw_pswitch_event, sc); + } + powsw_reset_counter(sc); + mfp_bit_set_ierb(sc->sc_mask); // enable interrupt + } + + splx(s); +} + +static void +powsw_pswitch_event(void *arg) +{ + struct powsw_softc *sc = arg; + int poweroff; + + poweroff = sc->sc_prev; + + DPRINTF(" %s is %s\n", device_xname(sc->sc_dev), + poweroff ? "off(PRESS)" : "on(RELEASE)"); + + sysmon_pswitch_event(&sc->sc_smpsw, + poweroff ? PSWITCH_EVENT_PRESSED : PSWITCH_EVENT_RELEASED); +} + +static void +powsw_shutdown_check(void *arg) +{ + struct powsw_softc *sc = arg; + int poweroff; + + poweroff = sc->sc_prev; + if (poweroff) + power_switch_is_off = 1; + DPRINTF("powsw_shutdown_check %s = %d\n", + device_xname(sc->sc_dev), power_switch_is_off); +} + +static void +powsw_reset_counter(struct powsw_softc *sc) +{ + sc->sc_last_sw = -1; + sc->sc_tick = 0; + sc->sc_count = 0; +#if defined(POWSW_DEBUG) + sc->sc_loglen = 0; +#endif +} + +static void +powsw_set_aer(struct powsw_softc *sc, int aer) +{ + KASSERT(aer == 0 || aer == 1); + + if (aer == 0) { + mfp_bit_clear_aer(sc->sc_mask); + } else { + mfp_bit_set_aer(sc->sc_mask); + } + DPRINTF(" SetAER=%d", aer); +}