diff --git a/sys/arch/hpcsh/dev/hd64461/hd64461video.c b/sys/arch/hpcsh/dev/hd64461/hd64461video.c index 60bf68092764..690a52f9f6dd 100644 --- a/sys/arch/hpcsh/dev/hd64461/hd64461video.c +++ b/sys/arch/hpcsh/dev/hd64461/hd64461video.c @@ -1,4 +1,4 @@ -/* $NetBSD: hd64461video.c,v 1.41 2007/07/09 20:52:14 ad Exp $ */ +/* $NetBSD: hd64461video.c,v 1.42 2007/09/24 16:16:42 kiyohara Exp $ */ /*- * Copyright (c) 2001, 2002, 2004 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: hd64461video.c,v 1.41 2007/07/09 20:52:14 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hd64461video.c,v 1.42 2007/09/24 16:16:42 kiyohara Exp $"); #include "opt_hd64461video.h" // #define HD64461VIDEO_HWACCEL @@ -74,6 +74,9 @@ __KERNEL_RCSID(0, "$NetBSD: hd64461video.c,v 1.41 2007/07/09 20:52:14 ad Exp $") #include #include +#include +#include + #ifdef HD64461VIDEO_DEBUG #define DPRINTF_ENABLE #define DPRINTF_DEBUG hd64461video_debug @@ -1222,6 +1225,9 @@ hd64461video_display_onoff(void *arg, bool on) /* struct hd64461video_chip *vc = arg; */ uint16_t r; + if (platid_match(&platid, &platid_mask_MACH_HITACHI_PERSONA)) + return; + /* turn on/off display in LCDC */ r = hd64461_reg_read_2(HD64461_LCDLDR1_REG16); if (on) diff --git a/sys/arch/hpcsh/dev/pfckbd.c b/sys/arch/hpcsh/dev/pfckbd.c index e594fcd3e945..aa12f8cb4b68 100644 --- a/sys/arch/hpcsh/dev/pfckbd.c +++ b/sys/arch/hpcsh/dev/pfckbd.c @@ -1,4 +1,4 @@ -/* $NetBSD: pfckbd.c,v 1.21 2007/07/09 20:52:13 ad Exp $ */ +/* $NetBSD: pfckbd.c,v 1.22 2007/09/24 16:16:42 kiyohara Exp $ */ /*- * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ * currently, HP Jornada 680/690, HITACHI PERSONA HPW-50PAD only. */ #include -__KERNEL_RCSID(0, "$NetBSD: pfckbd.c,v 1.21 2007/07/09 20:52:13 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pfckbd.c,v 1.22 2007/09/24 16:16:42 kiyohara Exp $"); #include "debug_hpcsh.h" @@ -94,6 +94,8 @@ static void (*pfckbd_callout_lookup(void))(void *); static void pfckbd_callout_unknown(void *); static void pfckbd_callout_hp(void *); static void pfckbd_callout_hitachi(void *); +void pfckbd_poll_hitachi_power(void); + /* callout function table. this function is platfrom specific. */ static const struct { @@ -347,8 +349,8 @@ pfckbd_callout_hitachi(void *arg) #define PFCKBD_HITACHI_PECR_MASK 0x30cf #define PFCKBD_HITACHI_PCDR_SCN_MASK 0xfd -#define PFCKBD_HITACHI_PDDR_SCN_MASK 0xf7 -#define PFCKBD_HITACHI_PEDR_SCN_MASK 0xff +#define PFCKBD_HITACHI_PDDR_SCN_MASK 0x02 +#define PFCKBD_HITACHI_PEDR_SCN_MASK 0x4b #define PFCKBD_HITACHI_PCDR_SNS_MASK 0x01 #define PFCKBD_HITACHI_PFDR_SNS_MASK 0xfe @@ -390,10 +392,6 @@ pfckbd_callout_hitachi(void *arg) PC(3), PC(2), PD(1), PC(0) }; -#undef PC -#undef PD -#undef PE - struct pfckbd_core *pc = arg; uint16_t cc, dc, ec; uint8_t data[2], cd, dd, ed; @@ -407,10 +405,6 @@ pfckbd_callout_hitachi(void *arg) dc = _reg_read_2(SH7709_PDCR) & ~PFCKBD_HITACHI_PDCR_MASK; ec = _reg_read_2(SH7709_PECR) & ~PFCKBD_HITACHI_PECR_MASK; - cd = _reg_read_1(SH7709_PCDR); - dd = _reg_read_1(SH7709_PDDR); - ed = _reg_read_1(SH7709_PEDR); - for (i = 0; i < 12; i++) { /* disable output to all lines except the one we scan */ _reg_write_2(SH7709_PCCR, cc | scan[i].cc); @@ -418,10 +412,14 @@ pfckbd_callout_hitachi(void *arg) _reg_write_2(SH7709_PECR, ec | scan[i].ec); delay(5); + cd = _reg_read_1(SH7709_PCDR) & ~PFCKBD_HITACHI_PCDR_SCN_MASK; + dd = _reg_read_1(SH7709_PDDR) & ~PFCKBD_HITACHI_PDDR_SCN_MASK; + ed = _reg_read_1(SH7709_PEDR) & ~PFCKBD_HITACHI_PEDR_SCN_MASK; + /* pull the scan line low */ - _reg_write_1(SH7709_PCDR, scan[i].c); - _reg_write_1(SH7709_PDDR, scan[i].d); - _reg_write_1(SH7709_PEDR, scan[i].e); + _reg_write_1(SH7709_PCDR, cd | scan[i].c); + _reg_write_1(SH7709_PDDR, dd | scan[i].d); + _reg_write_1(SH7709_PEDR, ed | scan[i].e); delay(50); /* read sense */ @@ -433,11 +431,6 @@ pfckbd_callout_hitachi(void *arg) pfckbd_input(pc, (i >> 1), (data[0] | (data[1] << 8))); } - /* scan no lines */ - _reg_write_1(SH7709_PCDR, cd); - _reg_write_1(SH7709_PDDR, dd); - _reg_write_1(SH7709_PEDR, ed); - /* enable all scan lines */ _reg_write_2(SH7709_PCCR, cc | (0x5555 & PFCKBD_HITACHI_PCCR_MASK)); _reg_write_2(SH7709_PDCR, dc | (0x5555 & PFCKBD_HITACHI_PDCR_MASK)); @@ -446,3 +439,47 @@ pfckbd_callout_hitachi(void *arg) reinstall: callout_schedule(&pc->pc_soft_ch, 1); } + +void +pfckbd_poll_hitachi_power() +{ + static const struct { + uint16_t cc, dc, ec; uint8_t c, d, e; + } poll = PD(1); + +#undef PC +#undef PD +#undef PE + + uint16_t cc, dc, ec; + uint8_t cd, dd, ed; + + /* bits in C/D/E control regs we do not touch (XXX: can they change?) */ + cc = _reg_read_2(SH7709_PCCR) & ~PFCKBD_HITACHI_PCCR_MASK; + dc = _reg_read_2(SH7709_PDCR) & ~PFCKBD_HITACHI_PDCR_MASK; + ec = _reg_read_2(SH7709_PECR) & ~PFCKBD_HITACHI_PECR_MASK; + + /* disable output to all lines except the one we scan */ + _reg_write_2(SH7709_PCCR, cc | poll.cc); + _reg_write_2(SH7709_PDCR, dc | poll.dc); + _reg_write_2(SH7709_PECR, ec | poll.ec); + delay(5); + + cd = _reg_read_1(SH7709_PCDR) & ~PFCKBD_HITACHI_PCDR_SCN_MASK; + dd = _reg_read_1(SH7709_PDDR) & ~PFCKBD_HITACHI_PDDR_SCN_MASK; + ed = _reg_read_1(SH7709_PEDR) & ~PFCKBD_HITACHI_PEDR_SCN_MASK; + + /* pull the scan line low */ + _reg_write_1(SH7709_PCDR, cd | poll.c); + _reg_write_1(SH7709_PDDR, dd | poll.d); + _reg_write_1(SH7709_PEDR, ed | poll.e); + delay(50); + + /* poll POWER On */ + while (_reg_read_1(SH7709_PCDR) & PFCKBD_HITACHI_PCDR_SNS_MASK & 0x01); + + /* enable all scan lines */ + _reg_write_2(SH7709_PCCR, cc | (0x5555 & PFCKBD_HITACHI_PCCR_MASK)); + _reg_write_2(SH7709_PDCR, dc | (0x5555 & PFCKBD_HITACHI_PDCR_MASK)); + _reg_write_2(SH7709_PECR, ec | (0x5555 & PFCKBD_HITACHI_PECR_MASK)); +} diff --git a/sys/arch/hpcsh/dev/psh3pwr.c b/sys/arch/hpcsh/dev/psh3pwr.c new file mode 100644 index 000000000000..b6daf7c77a39 --- /dev/null +++ b/sys/arch/hpcsh/dev/psh3pwr.c @@ -0,0 +1,262 @@ +/* $NetBSD: psh3pwr.c,v 1.1 2007/09/24 16:16:42 kiyohara Exp $ */ +/* + * 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 +__KERNEL_RCSID(0, "$NetBSD: psh3pwr.c,v 1.1 2007/09/24 16:16:42 kiyohara Exp $"); + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include + + +#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; + + /* regisiter 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: out\n", device_xname(&sc->sc_dev)); + } else { + sc->sc_plug = 1; + printf("%s: plug status: in\n", device_xname(&sc->sc_dev)); + } + 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", device_xname(&sc->sc_dev), "plug"); + + sc->sc_sysmon.sme_sensor_data = &sc->sc_data; + sc->sc_sysmon.sme_name = device_xname(&sc->sc_dev); + 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 sysmon\n", + device_xname(&sc->sc_dev)); +} + + +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)) { + return 0; + } + _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 out\n", device_xname(&sc->sc_dev))); + + 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)) + return 0; + _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 in\n", device_xname(&sc->sc_dev))); + + 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=%-4d\n", + device_xname(&sc->sc_dev), sc->sc_capacity); + + if (!sc->sc_plug && sc->sc_capacity < PSH3PWR_BATTERY_WARNING_THRESHOLD) + printf("%s: WARNING: main battery %d is low!\n", + device_xname(&sc->sc_dev), 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; +}