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:
isaki 2011-11-27 09:00:32 +00:00
parent d1a1bb2cc0
commit 9289c438ac
6 changed files with 361 additions and 6 deletions

View File

@ -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

View File

@ -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>

View 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).

View File

@ -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

View File

@ -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
View 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);
}