|
List Info
Thread: once more psh3pwr(4)
|
|
| once more psh3pwr(4) |

|
2007-09-23 11:42:53 |
Hi! uwe
I will commit the psh3pwr. Moreover, it supports
sysmon_envsys(9).
Thanks,
--
kiyohara
/* $NetBSD$ */
/*
* Copyright (c) 2005, 2007 KIYOHARA Takashi
* 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.
*
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/systm.h>
#include <sys/callout.h>
#include <machine/platid.h>
#include <machine/platid_mask.h>
#include <machine/config_hook.h>
#include <dev/sysmon/sysmonvar.h>
#include <sh3/exception.h>
#include <sh3/intcreg.h>
#include <sh3/pfcreg.h>
#include <sh3/dev/adcvar.h>
#ifdef PSH3PWR_DEBUG
#define DPRINTF(arg) printf arg
#else
#define DPRINTF(arg) ((void)0)
#endif
/* A/D covnerter channels to get power stats from */
#define ADC_CHANNEL_BATTERY 3
/* On/Off bit for Green LED. pin 7 in SH7709 GPIO port H.
*/
#define PSH3_GREEN_LED_ON 0x80
/*
* XXXX:
* WindowsCE seem to be using this as a flag.
* pin 6 in SH7709 GPIO port SCPDR.
*/
#define PSH3PWR_PLUG_OUT 0x40
/* warn that main battery is low after drops below this
value */
#define PSH3PWR_BATTERY_WARNING_THRESHOLD 200
struct psh3pwr_softc {
struct device sc_dev;
struct callout sc_poll_ch;
void *sc_ih_pin;
void *sc_ih_pout;
int sc_plug; /* In/Out flug */
int sc_capacity;
struct sysmon_envsys sc_sysmon;
struct envsys_data sc_data;
};
static int psh3pwr_match(struct device *, struct cfdata *,
void *);
static void psh3pwr_attach(struct device *, struct device *,
void *);
CFATTACH_DECL(psh3pwr, sizeof(struct psh3pwr_softc),
psh3pwr_match, psh3pwr_attach, NULL, NULL);
static int psh3pwr_intr_plug_out(void *);
static int psh3pwr_intr_plug_in(void *);
static void psh3pwr_poll_callout(void *);
static void psh3pwr_sleep(void *);
static int psh3pwr_gtredata(struct sysmon_envsys *,
envsys_data_t *);
static int
psh3pwr_match(struct device *parent, struct cfdata *cfp,
void *aux)
{
if (!platid_match(&platid,
&platid_mask_MACH_HITACHI_PERSONA))
return (0);
if (strcmp(cfp->cf_name, "psh3pwr") != 0)
return (0);
return (1);
}
static void
psh3pwr_attach(struct device *parent, struct device *self,
void *aux)
{
extern void (*__sleep_func)(void *);
extern void *__sleep_ctx;
struct psh3pwr_softc *sc = (struct psh3pwr_softc *)self;
uint8_t phdr, scpdr;
/* regsiter sleep function to APM */
__sleep_func = psh3pwr_sleep;
__sleep_ctx = self;
callout_init(&sc->sc_poll_ch, 0);
callout_setfunc(&sc->sc_poll_ch,
psh3pwr_poll_callout, sc);
phdr = _reg_read_1(SH7709_PHDR);
_reg_write_1(SH7709_PHDR, phdr | PSH3_GREEN_LED_ON);
printf("n");
sc->sc_ih_pout =
intc_intr_establish(SH7709_INTEVT2_IRQ0,
IST_EDGE, IPL_TTY, psh3pwr_intr_plug_out, sc);
sc->sc_ih_pin =
intc_intr_establish(SH7709_INTEVT2_IRQ1,
IST_EDGE, IPL_TTY, psh3pwr_intr_plug_in, sc);
/* XXXX: WindowsCE sets this bit. */
scpdr = _reg_read_1(SH7709_SCPDR);
if (scpdr & PSH3PWR_PLUG_OUT) {
sc->sc_plug = 0;
printf("%s: plug status: outn",
sc->sc_dev.dv_xname);
} else {
sc->sc_plug = 1;
printf("%s: plug status: inn",
sc->sc_dev.dv_xname);
}
psh3pwr_poll_callout(sc);
sc->sc_data.sensor = 0;
sc->sc_data.units = ENVSYS_INDICATOR;
sc->sc_data.state = ENVSYS_SVALID;
sc->sc_data.value_cur = sc->sc_plug;
snprintf(sc->sc_data.desc, sizeof(sc->sc_data.desc),
"%s %s", sc->sc_dev.dv_xname,
"plug");
sc->sc_sysmon.sme_sensor_data = &sc->sc_data;
sc->sc_sysmon.sme_name = sc->sc_dev.dv_xname;
sc->sc_sysmon.sme_cookie = sc;
sc->sc_sysmon.sme_gtredata = psh3pwr_gtredata;
sc->sc_sysmon.sme_nsensors =
sizeof(sc->sc_data) / sizeof(struct envsys_data);
if (sysmon_envsys_register(&sc->sc_sysmon))
aprint_error("%s: unable to register with
sysmonn",
sc->sc_dev.dv_xname);
}
static int
psh3pwr_intr_plug_out(void *self)
{
struct psh3pwr_softc *sc = (struct psh3pwr_softc *)self;
uint8_t irr0, scpdr;
irr0 = _reg_read_1(SH7709_IRR0);
if (irr0 & IRR0_IRQ0)
_reg_write_1(SH7709_IRR0, irr0 & ~IRR0_IRQ0);
/* XXXX: WindowsCE sets this bit. */
scpdr = _reg_read_1(SH7709_SCPDR);
_reg_write_1(SH7709_SCPDR, scpdr | PSH3PWR_PLUG_OUT);
sc->sc_plug = 0;
DPRINTF(("%s: plug outn",
sc->sc_dev.dv_xname));
return (1);
}
static int
psh3pwr_intr_plug_in(void *self)
{
struct psh3pwr_softc *sc = (struct psh3pwr_softc *)self;
uint8_t irr0, scpdr;
irr0 = _reg_read_1(SH7709_IRR0);
if (irr0 & IRR0_IRQ1)
_reg_write_1(SH7709_IRR0, irr0 & ~IRR0_IRQ1);
/* XXXX: WindowsCE sets this bit. */
scpdr = _reg_read_1(SH7709_SCPDR);
_reg_write_1(SH7709_SCPDR, scpdr & ~PSH3PWR_PLUG_OUT);
sc->sc_plug = 1;
DPRINTF(("%s: plug inn",
sc->sc_dev.dv_xname));
return (1);
}
void
psh3pwr_sleep(void *self)
{
/* splhigh on entry */
extern void pfckbd_poll_hitachi_power(void);
uint8_t phdr;
phdr = _reg_read_1(SH7709_PHDR);
_reg_write_1(SH7709_PHDR, phdr & ~PSH3_GREEN_LED_ON);
pfckbd_poll_hitachi_power();
phdr = _reg_read_1(SH7709_PHDR);
_reg_write_1(SH7709_PHDR, phdr | PSH3_GREEN_LED_ON);
}
volatile int psh3pwr_poll_verbose = 0; /* XXX: tweak from
ddb */
static void
psh3pwr_poll_callout(void *self)
{
struct psh3pwr_softc *sc = (struct psh3pwr_softc *)self;
int s;
s = spltty();
sc->sc_capacity =
adc_sample_channel(ADC_CHANNEL_BATTERY);
splx(s);
if (psh3pwr_poll_verbose != 0)
printf_nolog("%s: main=%-4dn",
sc->sc_dev.dv_xname, sc->sc_capacity);
if (!sc->sc_plug && sc->sc_capacity <
PSH3PWR_BATTERY_WARNING_THRESHOLD)
printf("%s: WARNING: main battery %d is
low!n",
sc->sc_dev.dv_xname, sc->sc_capacity);
callout_schedule(&sc->sc_poll_ch, 5 * hz);
}
static int
psh3pwr_gtredata(struct sysmon_envsys *sme, envsys_data_t
*edata)
{
struct psh3pwr_softc *sc = sme->sme_cookie;
edata->value_cur = sc->sc_plug;
return 0;
}
|
|
| Re: once more psh3pwr(4) |

|
2007-09-23 13:08:56 |
On Mon, Sep 24, 2007 at 01:42:53 +0900, KIYOHARA Takashi
wrote:
> I will commit the psh3pwr. Moreover, it supports
sysmon_envsys(9).
Thanks. Some comments below.
> #include <machine/config_hook.h>
I don't see any config_hook calls.
> /* regsiter sleep function to APM */
> __sleep_func = psh3pwr_sleep;
> __sleep_ctx = self;
Also arrange necessary config_hooks to get hpcapm connected
to this
driver?
> printf("%s: plug status: outn",
> sc->sc_dev.dv_xname);
device_xname(&sc->sc_dev) is preferred way to do it
(I know, j6x0pwr.c
hasn't been converted yet
> sc->sc_data.sensor = 0;
> sc->sc_data.units = ENVSYS_INDICATOR;
> sc->sc_data.state = ENVSYS_SVALID;
> sc->sc_data.value_cur = sc->sc_plug;
> snprintf(sc->sc_data.desc,
sizeof(sc->sc_data.desc),
> "%s %s", sc->sc_dev.dv_xname,
"plug");
I wonder if it makes sense to convert hpcapm to use sysmon
instead of
doing that in each driver (just thinking out loud here).
> irr0 = _reg_read_1(SH7709_IRR0);
> if (irr0 & IRR0_IRQ0)
> _reg_write_1(SH7709_IRR0, irr0 & ~IRR0_IRQ0);
>
If the bit is not set, you probably want to return 0
(interrupt not
handled) and bail. Ditto in _plug_in().
> /* splhigh on entry */
> extern void pfckbd_poll_hitachi_power(void);
I assume this will be in pfckbd.c. Isn't there any
interrupt to wake
us up?
Just commit it, and the details can be hashed out in the
tree.
Thanks!
SY, Uwe
--
uwe stderr.spb.ru | Zu Grunde
kommen
http://snark.ptc.spbu.
ru/~uwe/ | Ist zu Grunde gehen
|
|
| Re: once more psh3pwr(4) |

|
2007-09-24 10:32:21 |
Hi! uwe,
From: "Valeriy E. Ushakov" <uwe stderr.spb.ru>
Date: Sun, 23 Sep 2007 22:08:56 +0400
> On Mon, Sep 24, 2007 at 01:42:53 +0900, KIYOHARA
Takashi wrote:
> > /* regsiter sleep function to APM */
> > __sleep_func = psh3pwr_sleep;
> > __sleep_ctx = self;
>
> Also arrange necessary config_hooks to get hpcapm
connected to this
> driver?
hmm.. I can't know your meaning. X-<
> > sc->sc_data.sensor = 0;
> > sc->sc_data.units = ENVSYS_INDICATOR;
> > sc->sc_data.state = ENVSYS_SVALID;
> > sc->sc_data.value_cur = sc->sc_plug;
> > snprintf(sc->sc_data.desc,
sizeof(sc->sc_data.desc),
> > "%s %s", sc->sc_dev.dv_xname,
"plug");
>
> I wonder if it makes sense to convert hpcapm to use
sysmon instead of
> doing that in each driver (just thinking out loud
here).
In a word, should we treat sysmon_envsys with hpcapm layer?
> > /* splhigh on entry */
> > extern void pfckbd_poll_hitachi_power(void);
>
> I assume this will be in pfckbd.c. Isn't there any
interrupt to wake
> us up?
Oops.
Yes. Our PERSONA not occur the interrupt to power-button
with on/off.
Therefore, we are setting *_ special_keymap in
hpckbdkeymap.h. And,
KEY_SPECIAL_OFF is detected with hpckbd.c.
Thanks,
--
kiyohara
|
|
| Re: once more psh3pwr(4) |

|
2007-09-24 10:59:56 |
On Tue, Sep 25, 2007 at 00:32:21 +0900, KIYOHARA Takashi
wrote:
> From: "Valeriy E. Ushakov" <uwe stderr.spb.ru>
> Date: Sun, 23 Sep 2007 22:08:56 +0400
>
> > On Mon, Sep 24, 2007 at 01:42:53 +0900, KIYOHARA
Takashi wrote:
>
> > > /* regsiter sleep function to APM */
> > > __sleep_func = psh3pwr_sleep;
> > > __sleep_ctx = self;
> >
> > Also arrange necessary config_hooks to get hpcapm
connected to this
> > driver?
>
> hmm.. I can't know your meaning. X-<
This is to make apm(8) work. apm(8) queries apm device and
that ends
un in hpcapm(4). hpcapm uses config hooks to ask real
"power" device
about things like A/C adapter plugged/unplugged, battery
state, etc.
Check how it's done in j6x0pwr(4).
E.g. on my jornada with the battery not inserted (the deice
is always
on external power):
# apm
Battery charge state: absent
Battery remaining: 0 percent (0 minutes)
A/C adapter state: connected
Power management enabled
> > > sc->sc_data.sensor = 0;
> > > sc->sc_data.units = ENVSYS_INDICATOR;
> > > sc->sc_data.state = ENVSYS_SVALID;
> > > sc->sc_data.value_cur = sc->sc_plug;
> > > snprintf(sc->sc_data.desc,
sizeof(sc->sc_data.desc),
> > > "%s %s",
sc->sc_dev.dv_xname, "plug");
> >
> > I wonder if it makes sense to convert hpcapm to
use sysmon instead of
> > doing that in each driver (just thinking out loud
here).
>
> In a word, should we treat sysmon_envsys with hpcapm
layer?
I haven't checked how real i386 apm plugs into
sysmon_envsys, but we
probably should make hpcapm congruent with the real one.
Since hpcapm
already queries real power device about e.g. A/C adapter
state via
config hook, it seems logical to have sysmon glue in one
place
(hpcapm). But again, I haven't actually looked and havben't
thought
it through.
> > > /* splhigh on entry */
> > > extern void
pfckbd_poll_hitachi_power(void);
> >
> > I assume this will be in pfckbd.c. Isn't there
any interrupt to wake
> > us up?
>
> Oops.
> Yes. Our PERSONA not occur the interrupt to
power-button with on/off.
> Therefore, we are setting *_ special_keymap in
hpckbdkeymap.h. And,
> KEY_SPECIAL_OFF is detected with hpckbd.c.
I remember we discussed this. How does WinCE handles wakeup
on
PERSONA then? It would be very nice to add real suspend
when Jared's
PM branch is merged to the trunk. On Jornada WinCE does a
very clever
trick for the suspend - it powers down everything and puts
memory into
self-refresh mode, but just before that it prefetches
interrupt
handler into the CPU cache, so that when wakeup interrupt
occurs CPU
can run that interrupt handler out of cache (preserved in
sleep) and
the handler brings memory back from self-refresh and then
jumps into a
real handler that is in the memory. If there's no wakeup
interrupt in
PERSONA I wonder how can they implement efficient suspend at
all.
But anyway, commit and let's figure out the details when the
code is
in the tree.
Thanks.
SY, Uwe
--
uwe stderr.spb.ru | Zu Grunde
kommen
http://snark.ptc.spbu.
ru/~uwe/ | Ist zu Grunde gehen
|
|
[1-4]
|
|