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.
This commit is contained in:
parent
d1a1bb2cc0
commit
9289c438ac
@ -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
|
||||
|
@ -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>
|
||||
|
55
share/man/man4/man4.x68k/powsw.4
Normal file
55
share/man/man4/man4.x68k/powsw.4
Normal file
@ -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).
|
@ -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 printer port
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
290
sys/arch/x68k/dev/powsw.c
Normal file
290
sys/arch/x68k/dev/powsw.c
Normal file
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user